1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 * Brian Paul
31 */
32
33
34 #include "main/imports.h"
35 #include "main/hash.h"
36 #include "main/mfeatures.h"
37 #include "main/mtypes.h"
38 #include "program/prog_parameter.h"
39 #include "program/prog_print.h"
40 #include "program/programopt.h"
41
42 #include "pipe/p_context.h"
43 #include "pipe/p_defines.h"
44 #include "pipe/p_shader_tokens.h"
45 #include "draw/draw_context.h"
46 #include "tgsi/tgsi_dump.h"
47 #include "tgsi/tgsi_ureg.h"
48
49 #include "st_debug.h"
50 #include "st_cb_bitmap.h"
51 #include "st_cb_drawpixels.h"
52 #include "st_context.h"
53 #include "st_program.h"
54 #include "st_mesa_to_tgsi.h"
55 #include "cso_cache/cso_context.h"
56
57
58
59 /**
60 * Delete a vertex program variant. Note the caller must unlink
61 * the variant from the linked list.
62 */
63 static void
delete_vp_variant(struct st_context * st,struct st_vp_variant * vpv)64 delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv)
65 {
66 if (vpv->driver_shader)
67 cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
68
69 #if FEATURE_feedback || FEATURE_rastpos
70 if (vpv->draw_shader)
71 draw_delete_vertex_shader( st->draw, vpv->draw_shader );
72 #endif
73
74 if (vpv->tgsi.tokens)
75 st_free_tokens(vpv->tgsi.tokens);
76
77 FREE( vpv );
78 }
79
80
81
82 /**
83 * Clean out any old compilations:
84 */
85 void
st_release_vp_variants(struct st_context * st,struct st_vertex_program * stvp)86 st_release_vp_variants( struct st_context *st,
87 struct st_vertex_program *stvp )
88 {
89 struct st_vp_variant *vpv;
90
91 for (vpv = stvp->variants; vpv; ) {
92 struct st_vp_variant *next = vpv->next;
93 delete_vp_variant(st, vpv);
94 vpv = next;
95 }
96
97 stvp->variants = NULL;
98 }
99
100
101
102 /**
103 * Delete a fragment program variant. Note the caller must unlink
104 * the variant from the linked list.
105 */
106 static void
delete_fp_variant(struct st_context * st,struct st_fp_variant * fpv)107 delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv)
108 {
109 if (fpv->driver_shader)
110 cso_delete_fragment_shader(st->cso_context, fpv->driver_shader);
111 if (fpv->parameters)
112 _mesa_free_parameter_list(fpv->parameters);
113 if (fpv->tgsi.tokens)
114 st_free_tokens(fpv->tgsi.tokens);
115 FREE(fpv);
116 }
117
118
119 /**
120 * Free all variants of a fragment program.
121 */
122 void
st_release_fp_variants(struct st_context * st,struct st_fragment_program * stfp)123 st_release_fp_variants(struct st_context *st, struct st_fragment_program *stfp)
124 {
125 struct st_fp_variant *fpv;
126
127 for (fpv = stfp->variants; fpv; ) {
128 struct st_fp_variant *next = fpv->next;
129 delete_fp_variant(st, fpv);
130 fpv = next;
131 }
132
133 stfp->variants = NULL;
134 }
135
136
137 /**
138 * Delete a geometry program variant. Note the caller must unlink
139 * the variant from the linked list.
140 */
141 static void
delete_gp_variant(struct st_context * st,struct st_gp_variant * gpv)142 delete_gp_variant(struct st_context *st, struct st_gp_variant *gpv)
143 {
144 if (gpv->driver_shader)
145 cso_delete_geometry_shader(st->cso_context, gpv->driver_shader);
146
147 FREE(gpv);
148 }
149
150
151 /**
152 * Free all variants of a geometry program.
153 */
154 void
st_release_gp_variants(struct st_context * st,struct st_geometry_program * stgp)155 st_release_gp_variants(struct st_context *st, struct st_geometry_program *stgp)
156 {
157 struct st_gp_variant *gpv;
158
159 for (gpv = stgp->variants; gpv; ) {
160 struct st_gp_variant *next = gpv->next;
161 delete_gp_variant(st, gpv);
162 gpv = next;
163 }
164
165 stgp->variants = NULL;
166 }
167
168
169
170
171 /**
172 * Translate a Mesa vertex shader into a TGSI shader.
173 * \param outputMapping to map vertex program output registers (VERT_RESULT_x)
174 * to TGSI output slots
175 * \param tokensOut destination for TGSI tokens
176 * \return pointer to cached pipe_shader object.
177 */
178 void
st_prepare_vertex_program(struct gl_context * ctx,struct st_vertex_program * stvp)179 st_prepare_vertex_program(struct gl_context *ctx,
180 struct st_vertex_program *stvp)
181 {
182 GLuint attr;
183
184 stvp->num_inputs = 0;
185 stvp->num_outputs = 0;
186
187 if (stvp->Base.IsPositionInvariant)
188 _mesa_insert_mvp_code(ctx, &stvp->Base);
189
190 if (!stvp->glsl_to_tgsi)
191 assert(stvp->Base.Base.NumInstructions > 1);
192
193 /*
194 * Determine number of inputs, the mappings between VERT_ATTRIB_x
195 * and TGSI generic input indexes, plus input attrib semantic info.
196 */
197 for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
198 if ((stvp->Base.Base.InputsRead & BITFIELD64_BIT(attr)) != 0) {
199 stvp->input_to_index[attr] = stvp->num_inputs;
200 stvp->index_to_input[stvp->num_inputs] = attr;
201 stvp->num_inputs++;
202 }
203 }
204 /* bit of a hack, presetup potentially unused edgeflag input */
205 stvp->input_to_index[VERT_ATTRIB_EDGEFLAG] = stvp->num_inputs;
206 stvp->index_to_input[stvp->num_inputs] = VERT_ATTRIB_EDGEFLAG;
207
208 /* Compute mapping of vertex program outputs to slots.
209 */
210 for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
211 if ((stvp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) == 0) {
212 stvp->result_to_output[attr] = ~0;
213 }
214 else {
215 unsigned slot = stvp->num_outputs++;
216
217 stvp->result_to_output[attr] = slot;
218
219 switch (attr) {
220 case VERT_RESULT_HPOS:
221 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
222 stvp->output_semantic_index[slot] = 0;
223 break;
224 case VERT_RESULT_COL0:
225 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
226 stvp->output_semantic_index[slot] = 0;
227 break;
228 case VERT_RESULT_COL1:
229 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
230 stvp->output_semantic_index[slot] = 1;
231 break;
232 case VERT_RESULT_BFC0:
233 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
234 stvp->output_semantic_index[slot] = 0;
235 break;
236 case VERT_RESULT_BFC1:
237 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
238 stvp->output_semantic_index[slot] = 1;
239 break;
240 case VERT_RESULT_FOGC:
241 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
242 stvp->output_semantic_index[slot] = 0;
243 break;
244 case VERT_RESULT_PSIZ:
245 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
246 stvp->output_semantic_index[slot] = 0;
247 break;
248 case VERT_RESULT_CLIP_DIST0:
249 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
250 stvp->output_semantic_index[slot] = 0;
251 break;
252 case VERT_RESULT_CLIP_DIST1:
253 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
254 stvp->output_semantic_index[slot] = 1;
255 break;
256 case VERT_RESULT_EDGE:
257 assert(0);
258 break;
259 case VERT_RESULT_CLIP_VERTEX:
260 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX;
261 stvp->output_semantic_index[slot] = 0;
262 break;
263
264 case VERT_RESULT_TEX0:
265 case VERT_RESULT_TEX1:
266 case VERT_RESULT_TEX2:
267 case VERT_RESULT_TEX3:
268 case VERT_RESULT_TEX4:
269 case VERT_RESULT_TEX5:
270 case VERT_RESULT_TEX6:
271 case VERT_RESULT_TEX7:
272 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
273 stvp->output_semantic_index[slot] = attr - VERT_RESULT_TEX0;
274 break;
275
276 case VERT_RESULT_VAR0:
277 default:
278 assert(attr < VERT_RESULT_MAX);
279 stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
280 stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 -
281 FRAG_ATTRIB_TEX0 +
282 attr -
283 VERT_RESULT_VAR0);
284 break;
285 }
286 }
287 }
288 /* similar hack to above, presetup potentially unused edgeflag output */
289 stvp->result_to_output[VERT_RESULT_EDGE] = stvp->num_outputs;
290 stvp->output_semantic_name[stvp->num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
291 stvp->output_semantic_index[stvp->num_outputs] = 0;
292 }
293
294
295 /**
296 * Translate a vertex program to create a new variant.
297 */
298 static struct st_vp_variant *
st_translate_vertex_program(struct st_context * st,struct st_vertex_program * stvp,const struct st_vp_variant_key * key)299 st_translate_vertex_program(struct st_context *st,
300 struct st_vertex_program *stvp,
301 const struct st_vp_variant_key *key)
302 {
303 struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant);
304 struct pipe_context *pipe = st->pipe;
305 struct ureg_program *ureg;
306 enum pipe_error error;
307 unsigned num_outputs;
308
309 st_prepare_vertex_program(st->ctx, stvp);
310
311 if (!stvp->glsl_to_tgsi)
312 {
313 _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT);
314 _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING);
315 }
316
317 ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
318 if (ureg == NULL) {
319 FREE(vpv);
320 return NULL;
321 }
322
323 vpv->key = *key;
324
325 vpv->num_inputs = stvp->num_inputs;
326 num_outputs = stvp->num_outputs;
327 if (key->passthrough_edgeflags) {
328 vpv->num_inputs++;
329 num_outputs++;
330 }
331
332 if (ST_DEBUG & DEBUG_MESA) {
333 _mesa_print_program(&stvp->Base.Base);
334 _mesa_print_program_parameters(st->ctx, &stvp->Base.Base);
335 debug_printf("\n");
336 }
337
338 if (stvp->glsl_to_tgsi)
339 error = st_translate_program(st->ctx,
340 TGSI_PROCESSOR_VERTEX,
341 ureg,
342 stvp->glsl_to_tgsi,
343 &stvp->Base.Base,
344 /* inputs */
345 stvp->num_inputs,
346 stvp->input_to_index,
347 NULL, /* input semantic name */
348 NULL, /* input semantic index */
349 NULL, /* interp mode */
350 NULL, /* is centroid */
351 /* outputs */
352 stvp->num_outputs,
353 stvp->result_to_output,
354 stvp->output_semantic_name,
355 stvp->output_semantic_index,
356 key->passthrough_edgeflags,
357 key->clamp_color);
358 else
359 error = st_translate_mesa_program(st->ctx,
360 TGSI_PROCESSOR_VERTEX,
361 ureg,
362 &stvp->Base.Base,
363 /* inputs */
364 vpv->num_inputs,
365 stvp->input_to_index,
366 NULL, /* input semantic name */
367 NULL, /* input semantic index */
368 NULL,
369 /* outputs */
370 num_outputs,
371 stvp->result_to_output,
372 stvp->output_semantic_name,
373 stvp->output_semantic_index,
374 key->passthrough_edgeflags,
375 key->clamp_color);
376
377 if (error)
378 goto fail;
379
380 vpv->tgsi.tokens = ureg_get_tokens( ureg, NULL );
381 if (!vpv->tgsi.tokens)
382 goto fail;
383
384 ureg_destroy( ureg );
385
386 if (stvp->glsl_to_tgsi) {
387 st_translate_stream_output_info(stvp->glsl_to_tgsi,
388 stvp->result_to_output,
389 &vpv->tgsi.stream_output);
390 }
391
392 vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi);
393
394 if (ST_DEBUG & DEBUG_TGSI) {
395 tgsi_dump( vpv->tgsi.tokens, 0 );
396 debug_printf("\n");
397 }
398
399 return vpv;
400
401 fail:
402 debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__);
403 _mesa_print_program(&stvp->Base.Base);
404 debug_assert(0);
405
406 ureg_destroy( ureg );
407 return NULL;
408 }
409
410
411 /**
412 * Find/create a vertex program variant.
413 */
414 struct st_vp_variant *
st_get_vp_variant(struct st_context * st,struct st_vertex_program * stvp,const struct st_vp_variant_key * key)415 st_get_vp_variant(struct st_context *st,
416 struct st_vertex_program *stvp,
417 const struct st_vp_variant_key *key)
418 {
419 struct st_vp_variant *vpv;
420
421 /* Search for existing variant */
422 for (vpv = stvp->variants; vpv; vpv = vpv->next) {
423 if (memcmp(&vpv->key, key, sizeof(*key)) == 0) {
424 break;
425 }
426 }
427
428 if (!vpv) {
429 /* create now */
430 vpv = st_translate_vertex_program(st, stvp, key);
431 if (vpv) {
432 /* insert into list */
433 vpv->next = stvp->variants;
434 stvp->variants = vpv;
435 }
436 }
437
438 return vpv;
439 }
440
441
442 static unsigned
st_translate_interp(enum glsl_interp_qualifier glsl_qual,bool is_color)443 st_translate_interp(enum glsl_interp_qualifier glsl_qual, bool is_color)
444 {
445 switch (glsl_qual) {
446 case INTERP_QUALIFIER_NONE:
447 if (is_color)
448 return TGSI_INTERPOLATE_COLOR;
449 return TGSI_INTERPOLATE_PERSPECTIVE;
450 case INTERP_QUALIFIER_SMOOTH:
451 return TGSI_INTERPOLATE_PERSPECTIVE;
452 case INTERP_QUALIFIER_FLAT:
453 return TGSI_INTERPOLATE_CONSTANT;
454 case INTERP_QUALIFIER_NOPERSPECTIVE:
455 return TGSI_INTERPOLATE_LINEAR;
456 default:
457 assert(0 && "unexpected interp mode in st_translate_interp()");
458 return TGSI_INTERPOLATE_PERSPECTIVE;
459 }
460 }
461
462
463 /**
464 * Translate a Mesa fragment shader into a TGSI shader using extra info in
465 * the key.
466 * \return new fragment program variant
467 */
468 static struct st_fp_variant *
st_translate_fragment_program(struct st_context * st,struct st_fragment_program * stfp,const struct st_fp_variant_key * key)469 st_translate_fragment_program(struct st_context *st,
470 struct st_fragment_program *stfp,
471 const struct st_fp_variant_key *key)
472 {
473 struct pipe_context *pipe = st->pipe;
474 struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
475 GLboolean deleteFP = GL_FALSE;
476
477 GLuint outputMapping[FRAG_RESULT_MAX];
478 GLuint inputMapping[FRAG_ATTRIB_MAX];
479 GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */
480 GLuint attr;
481 GLbitfield64 inputsRead;
482 struct ureg_program *ureg;
483
484 GLboolean write_all = GL_FALSE;
485
486 ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
487 ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
488 GLboolean is_centroid[PIPE_MAX_SHADER_INPUTS];
489 uint fs_num_inputs = 0;
490
491 ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
492 ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
493 uint fs_num_outputs = 0;
494
495 if (!variant)
496 return NULL;
497
498 assert(!(key->bitmap && key->drawpixels));
499
500 #if FEATURE_drawpix
501 if (key->bitmap) {
502 /* glBitmap drawing */
503 struct gl_fragment_program *fp; /* we free this temp program below */
504
505 st_make_bitmap_fragment_program(st, &stfp->Base,
506 &fp, &variant->bitmap_sampler);
507
508 variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
509 stfp = st_fragment_program(fp);
510 deleteFP = GL_TRUE;
511 }
512 else if (key->drawpixels) {
513 /* glDrawPixels drawing */
514 struct gl_fragment_program *fp; /* we free this temp program below */
515
516 if (key->drawpixels_z || key->drawpixels_stencil) {
517 fp = st_make_drawpix_z_stencil_program(st, key->drawpixels_z,
518 key->drawpixels_stencil);
519 }
520 else {
521 /* RGBA */
522 st_make_drawpix_fragment_program(st, &stfp->Base, &fp);
523 variant->parameters = _mesa_clone_parameter_list(fp->Base.Parameters);
524 deleteFP = GL_TRUE;
525 }
526 stfp = st_fragment_program(fp);
527 }
528 #endif
529
530 if (!stfp->glsl_to_tgsi)
531 _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);
532
533 /*
534 * Convert Mesa program inputs to TGSI input register semantics.
535 */
536 inputsRead = stfp->Base.Base.InputsRead;
537 for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
538 if ((inputsRead & BITFIELD64_BIT(attr)) != 0) {
539 const GLuint slot = fs_num_inputs++;
540
541 inputMapping[attr] = slot;
542 is_centroid[slot] = (stfp->Base.IsCentroid & BITFIELD64_BIT(attr)) != 0;
543
544 switch (attr) {
545 case FRAG_ATTRIB_WPOS:
546 input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
547 input_semantic_index[slot] = 0;
548 interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
549 break;
550 case FRAG_ATTRIB_COL0:
551 input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
552 input_semantic_index[slot] = 0;
553 interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr],
554 TRUE);
555 break;
556 case FRAG_ATTRIB_COL1:
557 input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
558 input_semantic_index[slot] = 1;
559 interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr],
560 TRUE);
561 break;
562 case FRAG_ATTRIB_FOGC:
563 input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
564 input_semantic_index[slot] = 0;
565 interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
566 break;
567 case FRAG_ATTRIB_FACE:
568 input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
569 input_semantic_index[slot] = 0;
570 interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
571 break;
572 case FRAG_ATTRIB_CLIP_DIST0:
573 input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
574 input_semantic_index[slot] = 0;
575 interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
576 break;
577 case FRAG_ATTRIB_CLIP_DIST1:
578 input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
579 input_semantic_index[slot] = 1;
580 interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
581 break;
582 /* In most cases, there is nothing special about these
583 * inputs, so adopt a convention to use the generic
584 * semantic name and the mesa FRAG_ATTRIB_ number as the
585 * index.
586 *
587 * All that is required is that the vertex shader labels
588 * its own outputs similarly, and that the vertex shader
589 * generates at least every output required by the
590 * fragment shader plus fixed-function hardware (such as
591 * BFC).
592 *
593 * There is no requirement that semantic indexes start at
594 * zero or be restricted to a particular range -- nobody
595 * should be building tables based on semantic index.
596 */
597 case FRAG_ATTRIB_PNTC:
598 case FRAG_ATTRIB_TEX0:
599 case FRAG_ATTRIB_TEX1:
600 case FRAG_ATTRIB_TEX2:
601 case FRAG_ATTRIB_TEX3:
602 case FRAG_ATTRIB_TEX4:
603 case FRAG_ATTRIB_TEX5:
604 case FRAG_ATTRIB_TEX6:
605 case FRAG_ATTRIB_TEX7:
606 case FRAG_ATTRIB_VAR0:
607 default:
608 /* Actually, let's try and zero-base this just for
609 * readability of the generated TGSI.
610 */
611 assert(attr >= FRAG_ATTRIB_TEX0);
612 input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);
613 input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
614 if (attr == FRAG_ATTRIB_PNTC)
615 interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
616 else
617 interpMode[slot] = st_translate_interp(stfp->Base.InterpQualifier[attr],
618 FALSE);
619 break;
620 }
621 }
622 else {
623 inputMapping[attr] = -1;
624 }
625 }
626
627 /*
628 * Semantics and mapping for outputs
629 */
630 {
631 uint numColors = 0;
632 GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten;
633
634 /* if z is written, emit that first */
635 if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
636 fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
637 fs_output_semantic_index[fs_num_outputs] = 0;
638 outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs;
639 fs_num_outputs++;
640 outputsWritten &= ~(1 << FRAG_RESULT_DEPTH);
641 }
642
643 if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) {
644 fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL;
645 fs_output_semantic_index[fs_num_outputs] = 0;
646 outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs;
647 fs_num_outputs++;
648 outputsWritten &= ~(1 << FRAG_RESULT_STENCIL);
649 }
650
651 /* handle remaining outputs (color) */
652 for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
653 if (outputsWritten & BITFIELD64_BIT(attr)) {
654 switch (attr) {
655 case FRAG_RESULT_DEPTH:
656 case FRAG_RESULT_STENCIL:
657 /* handled above */
658 assert(0);
659 break;
660 case FRAG_RESULT_COLOR:
661 write_all = GL_TRUE; /* fallthrough */
662 default:
663 assert(attr == FRAG_RESULT_COLOR ||
664 (FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
665 fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
666 fs_output_semantic_index[fs_num_outputs] = numColors;
667 outputMapping[attr] = fs_num_outputs;
668 numColors++;
669 break;
670 }
671
672 fs_num_outputs++;
673 }
674 }
675 }
676
677 ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
678 if (ureg == NULL) {
679 FREE(variant);
680 return NULL;
681 }
682
683 if (ST_DEBUG & DEBUG_MESA) {
684 _mesa_print_program(&stfp->Base.Base);
685 _mesa_print_program_parameters(st->ctx, &stfp->Base.Base);
686 debug_printf("\n");
687 }
688 if (write_all == GL_TRUE)
689 ureg_property_fs_color0_writes_all_cbufs(ureg, 1);
690
691 if (stfp->Base.FragDepthLayout != FRAG_DEPTH_LAYOUT_NONE) {
692 switch (stfp->Base.FragDepthLayout) {
693 case FRAG_DEPTH_LAYOUT_ANY:
694 ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_ANY);
695 break;
696 case FRAG_DEPTH_LAYOUT_GREATER:
697 ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_GREATER);
698 break;
699 case FRAG_DEPTH_LAYOUT_LESS:
700 ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_LESS);
701 break;
702 case FRAG_DEPTH_LAYOUT_UNCHANGED:
703 ureg_property_fs_depth_layout(ureg, TGSI_FS_DEPTH_LAYOUT_UNCHANGED);
704 break;
705 default:
706 assert(0);
707 }
708 }
709
710 if (stfp->glsl_to_tgsi)
711 st_translate_program(st->ctx,
712 TGSI_PROCESSOR_FRAGMENT,
713 ureg,
714 stfp->glsl_to_tgsi,
715 &stfp->Base.Base,
716 /* inputs */
717 fs_num_inputs,
718 inputMapping,
719 input_semantic_name,
720 input_semantic_index,
721 interpMode,
722 is_centroid,
723 /* outputs */
724 fs_num_outputs,
725 outputMapping,
726 fs_output_semantic_name,
727 fs_output_semantic_index, FALSE,
728 key->clamp_color );
729 else
730 st_translate_mesa_program(st->ctx,
731 TGSI_PROCESSOR_FRAGMENT,
732 ureg,
733 &stfp->Base.Base,
734 /* inputs */
735 fs_num_inputs,
736 inputMapping,
737 input_semantic_name,
738 input_semantic_index,
739 interpMode,
740 /* outputs */
741 fs_num_outputs,
742 outputMapping,
743 fs_output_semantic_name,
744 fs_output_semantic_index, FALSE,
745 key->clamp_color);
746
747 variant->tgsi.tokens = ureg_get_tokens( ureg, NULL );
748 ureg_destroy( ureg );
749
750 /* fill in variant */
751 variant->driver_shader = pipe->create_fs_state(pipe, &variant->tgsi);
752 variant->key = *key;
753
754 if (ST_DEBUG & DEBUG_TGSI) {
755 tgsi_dump( variant->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
756 debug_printf("\n");
757 }
758
759 if (deleteFP) {
760 /* Free the temporary program made above */
761 struct gl_fragment_program *fp = &stfp->Base;
762 _mesa_reference_fragprog(st->ctx, &fp, NULL);
763 }
764
765 return variant;
766 }
767
768
769 /**
770 * Translate fragment program if needed.
771 */
772 struct st_fp_variant *
st_get_fp_variant(struct st_context * st,struct st_fragment_program * stfp,const struct st_fp_variant_key * key)773 st_get_fp_variant(struct st_context *st,
774 struct st_fragment_program *stfp,
775 const struct st_fp_variant_key *key)
776 {
777 struct st_fp_variant *fpv;
778
779 /* Search for existing variant */
780 for (fpv = stfp->variants; fpv; fpv = fpv->next) {
781 if (memcmp(&fpv->key, key, sizeof(*key)) == 0) {
782 break;
783 }
784 }
785
786 if (!fpv) {
787 /* create new */
788 fpv = st_translate_fragment_program(st, stfp, key);
789 if (fpv) {
790 /* insert into list */
791 fpv->next = stfp->variants;
792 stfp->variants = fpv;
793 }
794 }
795
796 return fpv;
797 }
798
799
800 /**
801 * Translate a geometry program to create a new variant.
802 */
803 static struct st_gp_variant *
st_translate_geometry_program(struct st_context * st,struct st_geometry_program * stgp,const struct st_gp_variant_key * key)804 st_translate_geometry_program(struct st_context *st,
805 struct st_geometry_program *stgp,
806 const struct st_gp_variant_key *key)
807 {
808 GLuint inputMapping[GEOM_ATTRIB_MAX];
809 GLuint outputMapping[GEOM_RESULT_MAX];
810 struct pipe_context *pipe = st->pipe;
811 GLuint attr;
812 GLbitfield64 inputsRead;
813 GLuint vslot = 0;
814 GLuint num_generic = 0;
815
816 uint gs_num_inputs = 0;
817 uint gs_builtin_inputs = 0;
818 uint gs_array_offset = 0;
819
820 ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
821 ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
822 uint gs_num_outputs = 0;
823
824 GLint i;
825 GLuint maxSlot = 0;
826 struct ureg_program *ureg;
827
828 struct st_gp_variant *gpv;
829
830 gpv = CALLOC_STRUCT(st_gp_variant);
831 if (!gpv)
832 return NULL;
833
834 _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT);
835 _mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING);
836
837 ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY );
838 if (ureg == NULL) {
839 FREE(gpv);
840 return NULL;
841 }
842
843 /* which vertex output goes to the first geometry input */
844 vslot = 0;
845
846 memset(inputMapping, 0, sizeof(inputMapping));
847 memset(outputMapping, 0, sizeof(outputMapping));
848
849 /*
850 * Convert Mesa program inputs to TGSI input register semantics.
851 */
852 inputsRead = stgp->Base.Base.InputsRead;
853 for (attr = 0; attr < GEOM_ATTRIB_MAX; attr++) {
854 if ((inputsRead & BITFIELD64_BIT(attr)) != 0) {
855 const GLuint slot = gs_num_inputs;
856
857 gs_num_inputs++;
858
859 inputMapping[attr] = slot;
860
861 stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs;
862 stgp->input_to_index[attr] = vslot;
863 stgp->index_to_input[vslot] = attr;
864 ++vslot;
865
866 if (attr != GEOM_ATTRIB_PRIMITIVE_ID) {
867 gs_array_offset += 2;
868 } else
869 ++gs_builtin_inputs;
870
871 #if 0
872 debug_printf("input map at %d = %d\n",
873 slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]);
874 #endif
875
876 switch (attr) {
877 case GEOM_ATTRIB_PRIMITIVE_ID:
878 stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
879 stgp->input_semantic_index[slot] = 0;
880 break;
881 case GEOM_ATTRIB_POSITION:
882 stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
883 stgp->input_semantic_index[slot] = 0;
884 break;
885 case GEOM_ATTRIB_COLOR0:
886 stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
887 stgp->input_semantic_index[slot] = 0;
888 break;
889 case GEOM_ATTRIB_COLOR1:
890 stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
891 stgp->input_semantic_index[slot] = 1;
892 break;
893 case GEOM_ATTRIB_FOG_FRAG_COORD:
894 stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
895 stgp->input_semantic_index[slot] = 0;
896 break;
897 case GEOM_ATTRIB_TEX_COORD:
898 stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
899 stgp->input_semantic_index[slot] = num_generic++;
900 break;
901 case GEOM_ATTRIB_VAR0:
902 /* fall-through */
903 default:
904 stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
905 stgp->input_semantic_index[slot] = num_generic++;
906 }
907 }
908 }
909
910 /* initialize output semantics to defaults */
911 for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
912 gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
913 gs_output_semantic_index[i] = 0;
914 }
915
916 num_generic = 0;
917 /*
918 * Determine number of outputs, the (default) output register
919 * mapping and the semantic information for each output.
920 */
921 for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
922 if (stgp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) {
923 GLuint slot;
924
925 slot = gs_num_outputs;
926 gs_num_outputs++;
927 outputMapping[attr] = slot;
928
929 switch (attr) {
930 case GEOM_RESULT_POS:
931 assert(slot == 0);
932 gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
933 gs_output_semantic_index[slot] = 0;
934 break;
935 case GEOM_RESULT_COL0:
936 gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
937 gs_output_semantic_index[slot] = 0;
938 break;
939 case GEOM_RESULT_COL1:
940 gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
941 gs_output_semantic_index[slot] = 1;
942 break;
943 case GEOM_RESULT_SCOL0:
944 gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
945 gs_output_semantic_index[slot] = 0;
946 break;
947 case GEOM_RESULT_SCOL1:
948 gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
949 gs_output_semantic_index[slot] = 1;
950 break;
951 case GEOM_RESULT_FOGC:
952 gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
953 gs_output_semantic_index[slot] = 0;
954 break;
955 case GEOM_RESULT_PSIZ:
956 gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
957 gs_output_semantic_index[slot] = 0;
958 break;
959 case GEOM_RESULT_TEX0:
960 case GEOM_RESULT_TEX1:
961 case GEOM_RESULT_TEX2:
962 case GEOM_RESULT_TEX3:
963 case GEOM_RESULT_TEX4:
964 case GEOM_RESULT_TEX5:
965 case GEOM_RESULT_TEX6:
966 case GEOM_RESULT_TEX7:
967 /* fall-through */
968 case GEOM_RESULT_VAR0:
969 /* fall-through */
970 default:
971 assert(slot < Elements(gs_output_semantic_name));
972 /* use default semantic info */
973 gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
974 gs_output_semantic_index[slot] = num_generic++;
975 }
976 }
977 }
978
979 assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION);
980
981 /* find max output slot referenced to compute gs_num_outputs */
982 for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
983 if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
984 maxSlot = outputMapping[attr];
985 }
986 gs_num_outputs = maxSlot + 1;
987
988 #if 0 /* debug */
989 {
990 GLuint i;
991 printf("outputMapping? %d\n", outputMapping ? 1 : 0);
992 if (outputMapping) {
993 printf("attr -> slot\n");
994 for (i = 0; i < 16; i++) {
995 printf(" %2d %3d\n", i, outputMapping[i]);
996 }
997 }
998 printf("slot sem_name sem_index\n");
999 for (i = 0; i < gs_num_outputs; i++) {
1000 printf(" %2d %d %d\n",
1001 i,
1002 gs_output_semantic_name[i],
1003 gs_output_semantic_index[i]);
1004 }
1005 }
1006 #endif
1007
1008 /* free old shader state, if any */
1009 if (stgp->tgsi.tokens) {
1010 st_free_tokens(stgp->tgsi.tokens);
1011 stgp->tgsi.tokens = NULL;
1012 }
1013
1014 ureg_property_gs_input_prim(ureg, stgp->Base.InputType);
1015 ureg_property_gs_output_prim(ureg, stgp->Base.OutputType);
1016 ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut);
1017
1018 st_translate_mesa_program(st->ctx,
1019 TGSI_PROCESSOR_GEOMETRY,
1020 ureg,
1021 &stgp->Base.Base,
1022 /* inputs */
1023 gs_num_inputs,
1024 inputMapping,
1025 stgp->input_semantic_name,
1026 stgp->input_semantic_index,
1027 NULL,
1028 /* outputs */
1029 gs_num_outputs,
1030 outputMapping,
1031 gs_output_semantic_name,
1032 gs_output_semantic_index,
1033 FALSE,
1034 FALSE);
1035
1036 stgp->num_inputs = gs_num_inputs;
1037 stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
1038 ureg_destroy( ureg );
1039
1040 if (stgp->glsl_to_tgsi) {
1041 st_translate_stream_output_info(stgp->glsl_to_tgsi,
1042 outputMapping,
1043 &stgp->tgsi.stream_output);
1044 }
1045
1046 /* fill in new variant */
1047 gpv->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
1048 gpv->key = *key;
1049
1050 if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
1051 _mesa_print_program(&stgp->Base.Base);
1052 debug_printf("\n");
1053 }
1054
1055 if (ST_DEBUG & DEBUG_TGSI) {
1056 tgsi_dump(stgp->tgsi.tokens, 0);
1057 debug_printf("\n");
1058 }
1059
1060 return gpv;
1061 }
1062
1063
1064 /**
1065 * Get/create geometry program variant.
1066 */
1067 struct st_gp_variant *
st_get_gp_variant(struct st_context * st,struct st_geometry_program * stgp,const struct st_gp_variant_key * key)1068 st_get_gp_variant(struct st_context *st,
1069 struct st_geometry_program *stgp,
1070 const struct st_gp_variant_key *key)
1071 {
1072 struct st_gp_variant *gpv;
1073
1074 /* Search for existing variant */
1075 for (gpv = stgp->variants; gpv; gpv = gpv->next) {
1076 if (memcmp(&gpv->key, key, sizeof(*key)) == 0) {
1077 break;
1078 }
1079 }
1080
1081 if (!gpv) {
1082 /* create new */
1083 gpv = st_translate_geometry_program(st, stgp, key);
1084 if (gpv) {
1085 /* insert into list */
1086 gpv->next = stgp->variants;
1087 stgp->variants = gpv;
1088 }
1089 }
1090
1091 return gpv;
1092 }
1093
1094
1095
1096
1097 /**
1098 * Debug- print current shader text
1099 */
1100 void
st_print_shaders(struct gl_context * ctx)1101 st_print_shaders(struct gl_context *ctx)
1102 {
1103 struct gl_shader_program *shProg[3] = {
1104 ctx->Shader.CurrentVertexProgram,
1105 ctx->Shader.CurrentGeometryProgram,
1106 ctx->Shader.CurrentFragmentProgram,
1107 };
1108 unsigned j;
1109
1110 for (j = 0; j < 3; j++) {
1111 unsigned i;
1112
1113 if (shProg[j] == NULL)
1114 continue;
1115
1116 for (i = 0; i < shProg[j]->NumShaders; i++) {
1117 struct gl_shader *sh;
1118
1119 switch (shProg[j]->Shaders[i]->Type) {
1120 case GL_VERTEX_SHADER:
1121 sh = (i != 0) ? NULL : shProg[j]->Shaders[i];
1122 break;
1123 case GL_GEOMETRY_SHADER_ARB:
1124 sh = (i != 1) ? NULL : shProg[j]->Shaders[i];
1125 break;
1126 case GL_FRAGMENT_SHADER:
1127 sh = (i != 2) ? NULL : shProg[j]->Shaders[i];
1128 break;
1129 default:
1130 assert(0);
1131 sh = NULL;
1132 break;
1133 }
1134
1135 if (sh != NULL) {
1136 printf("GLSL shader %u of %u:\n", i, shProg[j]->NumShaders);
1137 printf("%s\n", sh->Source);
1138 }
1139 }
1140 }
1141 }
1142
1143
1144 /**
1145 * Vert/Geom/Frag programs have per-context variants. Free all the
1146 * variants attached to the given program which match the given context.
1147 */
1148 static void
destroy_program_variants(struct st_context * st,struct gl_program * program)1149 destroy_program_variants(struct st_context *st, struct gl_program *program)
1150 {
1151 if (!program)
1152 return;
1153
1154 switch (program->Target) {
1155 case GL_VERTEX_PROGRAM_ARB:
1156 {
1157 struct st_vertex_program *stvp = (struct st_vertex_program *) program;
1158 struct st_vp_variant *vpv, **prevPtr = &stvp->variants;
1159
1160 for (vpv = stvp->variants; vpv; ) {
1161 struct st_vp_variant *next = vpv->next;
1162 if (vpv->key.st == st) {
1163 /* unlink from list */
1164 *prevPtr = next;
1165 /* destroy this variant */
1166 delete_vp_variant(st, vpv);
1167 }
1168 else {
1169 prevPtr = &vpv->next;
1170 }
1171 vpv = next;
1172 }
1173 }
1174 break;
1175 case GL_FRAGMENT_PROGRAM_ARB:
1176 {
1177 struct st_fragment_program *stfp =
1178 (struct st_fragment_program *) program;
1179 struct st_fp_variant *fpv, **prevPtr = &stfp->variants;
1180
1181 for (fpv = stfp->variants; fpv; ) {
1182 struct st_fp_variant *next = fpv->next;
1183 if (fpv->key.st == st) {
1184 /* unlink from list */
1185 *prevPtr = next;
1186 /* destroy this variant */
1187 delete_fp_variant(st, fpv);
1188 }
1189 else {
1190 prevPtr = &fpv->next;
1191 }
1192 fpv = next;
1193 }
1194 }
1195 break;
1196 case MESA_GEOMETRY_PROGRAM:
1197 {
1198 struct st_geometry_program *stgp =
1199 (struct st_geometry_program *) program;
1200 struct st_gp_variant *gpv, **prevPtr = &stgp->variants;
1201
1202 for (gpv = stgp->variants; gpv; ) {
1203 struct st_gp_variant *next = gpv->next;
1204 if (gpv->key.st == st) {
1205 /* unlink from list */
1206 *prevPtr = next;
1207 /* destroy this variant */
1208 delete_gp_variant(st, gpv);
1209 }
1210 else {
1211 prevPtr = &gpv->next;
1212 }
1213 gpv = next;
1214 }
1215 }
1216 break;
1217 default:
1218 _mesa_problem(NULL, "Unexpected program target 0x%x in "
1219 "destroy_program_variants_cb()", program->Target);
1220 }
1221 }
1222
1223
1224 /**
1225 * Callback for _mesa_HashWalk. Free all the shader's program variants
1226 * which match the given context.
1227 */
1228 static void
destroy_shader_program_variants_cb(GLuint key,void * data,void * userData)1229 destroy_shader_program_variants_cb(GLuint key, void *data, void *userData)
1230 {
1231 struct st_context *st = (struct st_context *) userData;
1232 struct gl_shader *shader = (struct gl_shader *) data;
1233
1234 switch (shader->Type) {
1235 case GL_SHADER_PROGRAM_MESA:
1236 {
1237 struct gl_shader_program *shProg = (struct gl_shader_program *) data;
1238 GLuint i;
1239
1240 for (i = 0; i < shProg->NumShaders; i++) {
1241 destroy_program_variants(st, shProg->Shaders[i]->Program);
1242 }
1243
1244 for (i = 0; i < Elements(shProg->_LinkedShaders); i++) {
1245 if (shProg->_LinkedShaders[i])
1246 destroy_program_variants(st, shProg->_LinkedShaders[i]->Program);
1247 }
1248 }
1249 break;
1250 case GL_VERTEX_SHADER:
1251 case GL_FRAGMENT_SHADER:
1252 case GL_GEOMETRY_SHADER:
1253 {
1254 destroy_program_variants(st, shader->Program);
1255 }
1256 break;
1257 default:
1258 assert(0);
1259 }
1260 }
1261
1262
1263 /**
1264 * Callback for _mesa_HashWalk. Free all the program variants which match
1265 * the given context.
1266 */
1267 static void
destroy_program_variants_cb(GLuint key,void * data,void * userData)1268 destroy_program_variants_cb(GLuint key, void *data, void *userData)
1269 {
1270 struct st_context *st = (struct st_context *) userData;
1271 struct gl_program *program = (struct gl_program *) data;
1272 destroy_program_variants(st, program);
1273 }
1274
1275
1276 /**
1277 * Walk over all shaders and programs to delete any variants which
1278 * belong to the given context.
1279 * This is called during context tear-down.
1280 */
1281 void
st_destroy_program_variants(struct st_context * st)1282 st_destroy_program_variants(struct st_context *st)
1283 {
1284 /* ARB vert/frag program */
1285 _mesa_HashWalk(st->ctx->Shared->Programs,
1286 destroy_program_variants_cb, st);
1287
1288 /* GLSL vert/frag/geom shaders */
1289 _mesa_HashWalk(st->ctx->Shared->ShaderObjects,
1290 destroy_shader_program_variants_cb, st);
1291 }
1292
1293
1294 /**
1295 * For debugging, print/dump the current vertex program.
1296 */
1297 void
st_print_current_vertex_program(void)1298 st_print_current_vertex_program(void)
1299 {
1300 GET_CURRENT_CONTEXT(ctx);
1301
1302 if (ctx->VertexProgram._Current) {
1303 struct st_vertex_program *stvp =
1304 (struct st_vertex_program *) ctx->VertexProgram._Current;
1305 struct st_vp_variant *stv;
1306
1307 debug_printf("Vertex program %u\n", stvp->Base.Base.Id);
1308
1309 for (stv = stvp->variants; stv; stv = stv->next) {
1310 debug_printf("variant %p\n", stv);
1311 tgsi_dump(stv->tgsi.tokens, 0);
1312 }
1313 }
1314 }
1315