svgadump: Several improvements to shader dumping.
[mesa.git] / src / gallium / drivers / svga / svgadump / svga_shader_dump.c
1 /**********************************************************
2 * Copyright 2008-2009 VMware, Inc. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use, copy,
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
9 * of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 *
24 **********************************************************/
25
26 /**
27 * @file
28 * SVGA Shader Dump Facilities
29 *
30 * @author Michal Krol <michal@vmware.com>
31 */
32
33 #include "svga_shader.h"
34 #include "svga_shader_dump.h"
35 #include "svga_shader_op.h"
36 #include "util/u_debug.h"
37
38 #include "../svga_hw_reg.h"
39 #include "svga3d_shaderdefs.h"
40
41 struct dump_info
42 {
43 uint32 version;
44 boolean is_ps;
45 int indent;
46 };
47
48 #define DUMP_MAX_OP_SRC 4
49
50 struct dump_op
51 {
52 struct sh_op op;
53 struct sh_dstreg dst;
54 struct sh_srcreg dstind;
55 struct sh_srcreg src[DUMP_MAX_OP_SRC];
56 struct sh_srcreg srcind[DUMP_MAX_OP_SRC];
57 struct sh_srcreg p0;
58 };
59
60 static void
61 dump_indent(int indent)
62 {
63 int i;
64
65 for (i = 0; i < indent; ++i) {
66 _debug_printf(" ");
67 }
68 }
69
70 static void dump_op( struct sh_op op, const char *mnemonic )
71 {
72 assert( op.is_reg == 0 );
73
74 if (op.predicated) {
75 _debug_printf("(p0) ");
76 }
77 if (op.coissue)
78 _debug_printf( "+" );
79 _debug_printf( "%s", mnemonic );
80
81 switch (op.opcode) {
82 case SVGA3DOP_TEX:
83 switch (op.control) {
84 case 0:
85 break;
86 case 1 /* PROJECT */:
87 _debug_printf("p");
88 break;
89 case 2 /* BIAS */:
90 _debug_printf("b");
91 break;
92 default:
93 assert(0);
94 }
95 break;
96
97 case SVGA3DOP_IFC:
98 case SVGA3DOP_BREAKC:
99 case SVGA3DOP_SETP:
100 switch (op.control) {
101 case SVGA3DOPCOMP_GT:
102 _debug_printf("_gt");
103 break;
104 case SVGA3DOPCOMP_EQ:
105 _debug_printf("_eq");
106 break;
107 case SVGA3DOPCOMP_GE:
108 _debug_printf("_ge");
109 break;
110 case SVGA3DOPCOMP_LT:
111 _debug_printf("_lt");
112 break;
113 case SVGA3DOPCOMPC_NE:
114 _debug_printf("_ne");
115 break;
116 case SVGA3DOPCOMP_LE:
117 _debug_printf("_le");
118 break;
119 default:
120 assert(0);
121 }
122 break;
123
124 default:
125 assert(op.control == 0);
126 }
127 }
128
129 static void
130 format_reg(const char *name,
131 const struct sh_reg reg,
132 const struct sh_srcreg *indreg)
133 {
134 if (reg.relative) {
135 assert(indreg);
136
137 if (sh_srcreg_type(*indreg) == SVGA3DREG_LOOP) {
138 _debug_printf("%s[aL+%u]", name, reg.number);
139 } else {
140 _debug_printf("%s[a%u.x+%u]", name, indreg->number, reg.number);
141 }
142 } else {
143 _debug_printf("%s%u", name, reg.number);
144 }
145 }
146
147 static void dump_reg( struct sh_reg reg, struct sh_srcreg *indreg, const struct dump_info *di )
148 {
149 assert( reg.is_reg == 1 );
150
151 switch (sh_reg_type( reg )) {
152 case SVGA3DREG_TEMP:
153 format_reg("r", reg, NULL);
154 break;
155
156 case SVGA3DREG_INPUT:
157 format_reg("v", reg, indreg);
158 break;
159
160 case SVGA3DREG_CONST:
161 format_reg("c", reg, indreg);
162 break;
163
164 case SVGA3DREG_ADDR: /* VS */
165 /* SVGA3DREG_TEXTURE */ /* PS */
166 assert(!reg.relative);
167 if (di->is_ps) {
168 format_reg("t", reg, NULL);
169 } else {
170 format_reg("a", reg, NULL);
171 }
172 break;
173
174 case SVGA3DREG_RASTOUT:
175 assert(!reg.relative);
176 switch (reg.number) {
177 case 0 /*POSITION*/:
178 _debug_printf( "oPos" );
179 break;
180 case 1 /*FOG*/:
181 _debug_printf( "oFog" );
182 break;
183 case 2 /*POINT_SIZE*/:
184 _debug_printf( "oPts" );
185 break;
186 default:
187 assert( 0 );
188 _debug_printf( "???" );
189 }
190 break;
191
192 case SVGA3DREG_ATTROUT:
193 assert( reg.number < 2 );
194 format_reg("oD", reg, NULL);
195 break;
196
197 case SVGA3DREG_TEXCRDOUT: /* VS */
198 /* SVGA3DREG_OUTPUT */ /* VS3.0+ */
199 if (!di->is_ps && di->version >= SVGA3D_VS_30) {
200 format_reg("o", reg, indreg);
201 } else {
202 format_reg("oT", reg, NULL);
203 }
204 break;
205
206 case SVGA3DREG_COLOROUT:
207 format_reg("oC", reg, NULL);
208 break;
209
210 case SVGA3DREG_DEPTHOUT:
211 assert(!reg.relative);
212 assert(reg.number == 0);
213 _debug_printf("oDepth");
214 break;
215
216 case SVGA3DREG_SAMPLER:
217 format_reg("s", reg, NULL);
218 break;
219
220 case SVGA3DREG_CONSTBOOL:
221 format_reg("b", reg, NULL);
222 break;
223
224 case SVGA3DREG_CONSTINT:
225 format_reg("i", reg, NULL);
226 break;
227
228 case SVGA3DREG_LOOP:
229 assert(!reg.relative);
230 assert( reg.number == 0 );
231 _debug_printf( "aL" );
232 break;
233
234 case SVGA3DREG_MISCTYPE:
235 assert(!reg.relative);
236 switch (reg.number) {
237 case SVGA3DMISCREG_POSITION:
238 _debug_printf("vPos");
239 break;
240 case SVGA3DMISCREG_FACE:
241 _debug_printf("vFace");
242 break;
243 default:
244 assert(0);
245 _debug_printf("???");
246 }
247 break;
248
249 case SVGA3DREG_LABEL:
250 format_reg("l", reg, NULL);
251 break;
252
253 case SVGA3DREG_PREDICATE:
254 format_reg("p", reg, NULL);
255 break;
256
257 default:
258 assert( 0 );
259 _debug_printf( "???" );
260 }
261 }
262
263 static void dump_cdata( struct sh_cdata cdata )
264 {
265 _debug_printf( "%f, %f, %f, %f", cdata.xyzw[0], cdata.xyzw[1], cdata.xyzw[2], cdata.xyzw[3] );
266 }
267
268 static void dump_idata( struct sh_idata idata )
269 {
270 _debug_printf( "%d, %d, %d, %d", idata.xyzw[0], idata.xyzw[1], idata.xyzw[2], idata.xyzw[3] );
271 }
272
273 static void dump_bdata( boolean bdata )
274 {
275 _debug_printf( bdata ? "TRUE" : "FALSE" );
276 }
277
278 static void
279 dump_sampleinfo(struct sh_sampleinfo sampleinfo)
280 {
281 assert( sampleinfo.is_reg == 1 );
282
283 switch (sampleinfo.texture_type) {
284 case SVGA3DSAMP_2D:
285 _debug_printf( "_2d" );
286 break;
287 case SVGA3DSAMP_CUBE:
288 _debug_printf( "_cube" );
289 break;
290 case SVGA3DSAMP_VOLUME:
291 _debug_printf( "_volume" );
292 break;
293 default:
294 assert( 0 );
295 }
296 }
297
298 static void
299 dump_semantic(uint usage,
300 uint usage_index)
301 {
302 switch (usage) {
303 case SVGA3D_DECLUSAGE_POSITION:
304 _debug_printf("_position");
305 break;
306 case SVGA3D_DECLUSAGE_BLENDWEIGHT:
307 _debug_printf("_blendweight");
308 break;
309 case SVGA3D_DECLUSAGE_BLENDINDICES:
310 _debug_printf("_blendindices");
311 break;
312 case SVGA3D_DECLUSAGE_NORMAL:
313 _debug_printf("_normal");
314 break;
315 case SVGA3D_DECLUSAGE_PSIZE:
316 _debug_printf("_psize");
317 break;
318 case SVGA3D_DECLUSAGE_TEXCOORD:
319 _debug_printf("_texcoord");
320 break;
321 case SVGA3D_DECLUSAGE_TANGENT:
322 _debug_printf("_tangent");
323 break;
324 case SVGA3D_DECLUSAGE_BINORMAL:
325 _debug_printf("_binormal");
326 break;
327 case SVGA3D_DECLUSAGE_TESSFACTOR:
328 _debug_printf("_tessfactor");
329 break;
330 case SVGA3D_DECLUSAGE_POSITIONT:
331 _debug_printf("_positiont");
332 break;
333 case SVGA3D_DECLUSAGE_COLOR:
334 _debug_printf("_color");
335 break;
336 case SVGA3D_DECLUSAGE_FOG:
337 _debug_printf("_fog");
338 break;
339 case SVGA3D_DECLUSAGE_DEPTH:
340 _debug_printf("_depth");
341 break;
342 case SVGA3D_DECLUSAGE_SAMPLE:
343 _debug_printf("_sample");
344 break;
345 default:
346 assert(!"Unknown usage");
347 _debug_printf("_???");
348 }
349
350 if (usage_index) {
351 _debug_printf("%u", usage_index);
352 }
353 }
354
355 static void
356 dump_dstreg(struct sh_dstreg dstreg,
357 struct sh_srcreg *indreg,
358 const struct dump_info *di)
359 {
360 union {
361 struct sh_reg reg;
362 struct sh_dstreg dstreg;
363 } u;
364
365 assert( (dstreg.modifier & (SVGA3DDSTMOD_SATURATE | SVGA3DDSTMOD_PARTIALPRECISION)) == dstreg.modifier );
366
367 if (dstreg.modifier & SVGA3DDSTMOD_SATURATE)
368 _debug_printf( "_sat" );
369 if (dstreg.modifier & SVGA3DDSTMOD_PARTIALPRECISION)
370 _debug_printf( "_pp" );
371 switch (dstreg.shift_scale) {
372 case 0:
373 break;
374 case 1:
375 _debug_printf( "_x2" );
376 break;
377 case 2:
378 _debug_printf( "_x4" );
379 break;
380 case 3:
381 _debug_printf( "_x8" );
382 break;
383 case 13:
384 _debug_printf( "_d8" );
385 break;
386 case 14:
387 _debug_printf( "_d4" );
388 break;
389 case 15:
390 _debug_printf( "_d2" );
391 break;
392 default:
393 assert( 0 );
394 }
395 _debug_printf( " " );
396
397 u.dstreg = dstreg;
398 dump_reg( u.reg, indreg, di);
399 if (dstreg.write_mask != SVGA3DWRITEMASK_ALL) {
400 _debug_printf( "." );
401 if (dstreg.write_mask & SVGA3DWRITEMASK_0)
402 _debug_printf( "x" );
403 if (dstreg.write_mask & SVGA3DWRITEMASK_1)
404 _debug_printf( "y" );
405 if (dstreg.write_mask & SVGA3DWRITEMASK_2)
406 _debug_printf( "z" );
407 if (dstreg.write_mask & SVGA3DWRITEMASK_3)
408 _debug_printf( "w" );
409 }
410 }
411
412 static void dump_srcreg( struct sh_srcreg srcreg, struct sh_srcreg *indreg, const struct dump_info *di )
413 {
414 switch (srcreg.modifier) {
415 case SVGA3DSRCMOD_NEG:
416 case SVGA3DSRCMOD_BIASNEG:
417 case SVGA3DSRCMOD_SIGNNEG:
418 case SVGA3DSRCMOD_X2NEG:
419 case SVGA3DSRCMOD_ABSNEG:
420 _debug_printf( "-" );
421 break;
422 case SVGA3DSRCMOD_COMP:
423 _debug_printf( "1-" );
424 break;
425 case SVGA3DSRCMOD_NOT:
426 _debug_printf( "!" );
427 }
428 dump_reg( *(struct sh_reg *) &srcreg, indreg, di );
429 switch (srcreg.modifier) {
430 case SVGA3DSRCMOD_NONE:
431 case SVGA3DSRCMOD_NEG:
432 case SVGA3DSRCMOD_COMP:
433 case SVGA3DSRCMOD_NOT:
434 break;
435 case SVGA3DSRCMOD_BIAS:
436 case SVGA3DSRCMOD_BIASNEG:
437 _debug_printf( "_bias" );
438 break;
439 case SVGA3DSRCMOD_SIGN:
440 case SVGA3DSRCMOD_SIGNNEG:
441 _debug_printf( "_bx2" );
442 break;
443 case SVGA3DSRCMOD_X2:
444 case SVGA3DSRCMOD_X2NEG:
445 _debug_printf( "_x2" );
446 break;
447 case SVGA3DSRCMOD_DZ:
448 _debug_printf( "_dz" );
449 break;
450 case SVGA3DSRCMOD_DW:
451 _debug_printf( "_dw" );
452 break;
453 case SVGA3DSRCMOD_ABS:
454 case SVGA3DSRCMOD_ABSNEG:
455 _debug_printf("_abs");
456 break;
457 default:
458 assert( 0 );
459 }
460 if (srcreg.swizzle_x != 0 || srcreg.swizzle_y != 1 || srcreg.swizzle_z != 2 || srcreg.swizzle_w != 3) {
461 _debug_printf( "." );
462 if (srcreg.swizzle_x == srcreg.swizzle_y && srcreg.swizzle_y == srcreg.swizzle_z && srcreg.swizzle_z == srcreg.swizzle_w) {
463 _debug_printf( "%c", "xyzw"[srcreg.swizzle_x] );
464 }
465 else {
466 _debug_printf( "%c", "xyzw"[srcreg.swizzle_x] );
467 _debug_printf( "%c", "xyzw"[srcreg.swizzle_y] );
468 _debug_printf( "%c", "xyzw"[srcreg.swizzle_z] );
469 _debug_printf( "%c", "xyzw"[srcreg.swizzle_w] );
470 }
471 }
472 }
473
474 static void
475 parse_op(struct dump_info *di,
476 const uint **token,
477 struct dump_op *op,
478 uint num_dst,
479 uint num_src)
480 {
481 uint i;
482
483 assert(num_dst <= 1);
484 assert(num_src <= DUMP_MAX_OP_SRC);
485
486 op->op = *(struct sh_op *)*token;
487 *token += sizeof(struct sh_op) / sizeof(uint);
488
489 if (num_dst >= 1) {
490 op->dst = *(struct sh_dstreg *)*token;
491 *token += sizeof(struct sh_dstreg) / sizeof(uint);
492 if (op->dst.relative &&
493 (!di->is_ps && di->version >= SVGA3D_VS_30)) {
494 op->dstind = *(struct sh_srcreg *)*token;
495 *token += sizeof(struct sh_srcreg) / sizeof(uint);
496 }
497 }
498
499 if (op->op.predicated) {
500 op->p0 = *(struct sh_srcreg *)*token;
501 *token += sizeof(struct sh_srcreg) / sizeof(uint);
502 }
503
504 for (i = 0; i < num_src; ++i) {
505 op->src[i] = *(struct sh_srcreg *)*token;
506 *token += sizeof(struct sh_srcreg) / sizeof(uint);
507 if (op->src[i].relative &&
508 ((!di->is_ps && di->version >= SVGA3D_VS_20) ||
509 (di->is_ps && di->version >= SVGA3D_PS_30))) {
510 op->srcind[i] = *(struct sh_srcreg *)*token;
511 *token += sizeof(struct sh_srcreg) / sizeof(uint);
512 }
513 }
514 }
515
516 static void
517 dump_inst(struct dump_info *di,
518 const unsigned **assem,
519 struct sh_op op,
520 const struct sh_opcode_info *info)
521 {
522 struct dump_op dop;
523 boolean not_first_arg = FALSE;
524 uint i;
525
526 assert(info->num_dst <= 1);
527
528 di->indent -= info->pre_dedent;
529 dump_indent(di->indent);
530 di->indent += info->post_indent;
531
532 dump_op(op, info->mnemonic);
533
534 parse_op(di, assem, &dop, info->num_dst, info->num_src);
535 if (info->num_dst > 0) {
536 dump_dstreg(dop.dst, &dop.dstind, di);
537 not_first_arg = TRUE;
538 }
539
540 for (i = 0; i < info->num_src; i++) {
541 if (not_first_arg) {
542 _debug_printf(", ");
543 } else {
544 _debug_printf(" ");
545 }
546 dump_srcreg(dop.src[i], &dop.srcind[i], di);
547 not_first_arg = TRUE;
548 }
549
550 _debug_printf("\n");
551 }
552
553 void
554 svga_shader_dump(
555 const unsigned *assem,
556 unsigned dwords,
557 unsigned do_binary )
558 {
559 boolean finished = FALSE;
560 struct dump_info di;
561
562 di.version = *assem++;
563 di.is_ps = (di.version & 0xFFFF0000) == 0xFFFF0000;
564 di.indent = 0;
565
566 _debug_printf(
567 "%s_%u_%u\n",
568 di.is_ps ? "ps" : "vs",
569 (di.version >> 8) & 0xff,
570 di.version & 0xff );
571
572 while (!finished) {
573 struct sh_op op = *(struct sh_op *) assem;
574
575 switch (op.opcode) {
576 case SVGA3DOP_DCL:
577 {
578 struct sh_dcl dcl = *(struct sh_dcl *) assem;
579
580 _debug_printf( "dcl" );
581 switch (sh_dstreg_type(dcl.reg)) {
582 case SVGA3DREG_INPUT:
583 if ((di.is_ps && di.version >= SVGA3D_PS_30) ||
584 (!di.is_ps && di.version >= SVGA3D_VS_30)) {
585 dump_semantic(dcl.u.semantic.usage,
586 dcl.u.semantic.usage_index);
587 }
588 break;
589 case SVGA3DREG_TEXCRDOUT:
590 if (!di.is_ps && di.version >= SVGA3D_VS_30) {
591 dump_semantic(dcl.u.semantic.usage,
592 dcl.u.semantic.usage_index);
593 }
594 break;
595 case SVGA3DREG_SAMPLER:
596 dump_sampleinfo( dcl.u.sampleinfo );
597 break;
598 }
599 dump_dstreg(dcl.reg, NULL, &di);
600 _debug_printf( "\n" );
601 assem += sizeof( struct sh_dcl ) / sizeof( unsigned );
602 }
603 break;
604
605 case SVGA3DOP_DEFB:
606 {
607 struct sh_defb defb = *(struct sh_defb *) assem;
608
609 _debug_printf( "defb " );
610 dump_reg( defb.reg, NULL, &di );
611 _debug_printf( ", " );
612 dump_bdata( defb.data );
613 _debug_printf( "\n" );
614 assem += sizeof( struct sh_defb ) / sizeof( unsigned );
615 }
616 break;
617
618 case SVGA3DOP_DEFI:
619 {
620 struct sh_defi defi = *(struct sh_defi *) assem;
621
622 _debug_printf( "defi " );
623 dump_reg( defi.reg, NULL, &di );
624 _debug_printf( ", " );
625 dump_idata( defi.idata );
626 _debug_printf( "\n" );
627 assem += sizeof( struct sh_defi ) / sizeof( unsigned );
628 }
629 break;
630
631 case SVGA3DOP_TEXCOORD:
632 {
633 struct sh_opcode_info info = *svga_opcode_info(op.opcode);
634
635 assert(di.is_ps);
636 if (di.version > SVGA3D_PS_13) {
637 assert(info.num_src == 0);
638
639 info.num_src = 1;
640 }
641
642 dump_inst(&di, &assem, op, &info);
643 }
644 break;
645
646 case SVGA3DOP_TEX:
647 {
648 struct sh_opcode_info info = *svga_opcode_info(op.opcode);
649
650 assert(di.is_ps);
651 if (di.version > SVGA3D_PS_13) {
652 assert(info.num_src == 0);
653
654 if (di.version > SVGA3D_PS_14) {
655 info.num_src = 2;
656 info.mnemonic = "texld";
657 } else {
658 info.num_src = 1;
659 }
660 }
661
662 dump_inst(&di, &assem, op, &info);
663 }
664 break;
665
666 case SVGA3DOP_DEF:
667 {
668 struct sh_def def = *(struct sh_def *) assem;
669
670 _debug_printf( "def " );
671 dump_reg( def.reg, NULL, &di );
672 _debug_printf( ", " );
673 dump_cdata( def.cdata );
674 _debug_printf( "\n" );
675 assem += sizeof( struct sh_def ) / sizeof( unsigned );
676 }
677 break;
678
679 case SVGA3DOP_SINCOS:
680 {
681 struct sh_opcode_info info = *svga_opcode_info(op.opcode);
682
683 if ((di.is_ps && di.version >= SVGA3D_PS_30) ||
684 (!di.is_ps && di.version >= SVGA3D_VS_30)) {
685 assert(info.num_src == 3);
686
687 info.num_src = 1;
688 }
689
690 dump_inst(&di, &assem, op, &info);
691 }
692 break;
693
694 case SVGA3DOP_PHASE:
695 _debug_printf( "phase\n" );
696 assem += sizeof( struct sh_op ) / sizeof( unsigned );
697 break;
698
699 case SVGA3DOP_COMMENT:
700 {
701 struct sh_comment comment = *(struct sh_comment *)assem;
702
703 /* Ignore comment contents. */
704 assem += sizeof(struct sh_comment) / sizeof(unsigned) + comment.size;
705 }
706 break;
707
708 case SVGA3DOP_END:
709 finished = TRUE;
710 break;
711
712 default:
713 {
714 const struct sh_opcode_info *info = svga_opcode_info(op.opcode);
715
716 dump_inst(&di, &assem, op, info);
717 }
718 }
719 }
720 }