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