2 * Copyright (C) 2006 Ben Skeggs.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a 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, sublicense, 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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 * Ben Skeggs <darktama@iinet.net.au>
36 #include "extensions.h"
38 #include "shader/program.h"
39 #include "shader/prog_instruction.h"
40 /*#include "shader/arbprogparse.h"*/
43 #include "nouveau_context.h"
44 #include "nouveau_shader.h"
46 /*****************************************************************************
50 nouveauBindProgram(GLcontext
*ctx
, GLenum target
, struct gl_program
*prog
)
52 NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target
), prog
);
55 static struct gl_program
*
56 nouveauNewProgram(GLcontext
*ctx
, GLenum target
, GLuint id
)
60 NVSDBG("target=%s, id=%d\n", _mesa_lookup_enum_by_nr(target
), id
);
62 nvs
= CALLOC_STRUCT(_nouveauShader
);
63 NVSDBG("prog=%p\n", nvs
);
65 case GL_VERTEX_PROGRAM_ARB
:
66 return _mesa_init_vertex_program(ctx
, &nvs
->mesa
.vp
, target
, id
);
67 case GL_FRAGMENT_PROGRAM_ARB
:
68 return _mesa_init_fragment_program(ctx
, &nvs
->mesa
.fp
, target
, id
);
70 _mesa_problem(ctx
, "Unsupported shader target");
79 nouveauDeleteProgram(GLcontext
*ctx
, struct gl_program
*prog
)
81 nouveauShader
*nvs
= (nouveauShader
*)prog
;
83 NVSDBG("prog=%p\n", prog
);
87 _mesa_delete_program(ctx
, prog
);
91 nouveauProgramStringNotify(GLcontext
*ctx
, GLenum target
,
92 struct gl_program
*prog
)
94 nouveauShader
*nvs
= (nouveauShader
*)prog
;
96 NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target
), prog
);
101 nvs
->error
= GL_FALSE
;
102 nvs
->translated
= GL_FALSE
;
104 _tnl_program_string(ctx
, target
, prog
);
108 nouveauIsProgramNative(GLcontext
* ctx
, GLenum target
, struct gl_program
*prog
)
110 nouveauShader
*nvs
= (nouveauShader
*)prog
;
112 NVSDBG("target=%s, prog=%p\n", _mesa_lookup_enum_by_nr(target
), prog
);
114 return nvs
->translated
;
118 nvsUpdateShader(GLcontext
*ctx
, nouveauShader
*nvs
)
120 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
121 struct gl_program_parameter_list
*plist
;
124 NVSDBG("prog=%p\n", nvs
);
126 /* Translate to HW format now if necessary */
127 if (!nvs
->translated
) {
128 /* Mesa ASM shader -> nouveauShader */
129 if (!nouveau_shader_pass0(ctx
, nvs
))
131 /* Basic dead code elimination + register usage info */
132 if (!nouveau_shader_pass1(nvs
))
134 /* nouveauShader -> HW bytecode, HW register alloc */
135 if (!nouveau_shader_pass2(nvs
))
137 assert(nvs
->translated
);
138 assert(nvs
->program
);
141 /* Update state parameters */
142 plist
= nvs
->mesa
.vp
.Base
.Parameters
;
143 _mesa_load_state_parameters(ctx
, plist
);
144 for (i
=0; i
<nvs
->param_high
; i
++) {
145 if (!nvs
->params
[i
].in_use
)
148 if (!nvs
->on_hardware
) {
149 /* if we've been kicked off the hardware there's no guarantee our
150 * consts are still there.. reupload them all
152 nvs
->func
->UpdateConst(ctx
, nvs
, i
);
153 } else if (nvs
->params
[i
].source_val
) {
154 /* update any changed state parameters */
155 if (!TEST_EQ_4V(nvs
->params
[i
].val
, nvs
->params
[i
].source_val
))
156 nvs
->func
->UpdateConst(ctx
, nvs
, i
);
160 /* Upload program to hardware, this must come after state param update
161 * as >=NV30 fragprogs inline consts into the bytecode.
163 if (!nvs
->on_hardware
) {
164 nouveauShader
**current
;
166 if (nvs
->mesa
.vp
.Base
.Target
== GL_VERTEX_PROGRAM_ARB
)
167 current
= &nmesa
->current_vertprog
;
169 current
= &nmesa
->current_fragprog
;
170 if (*current
) (*current
)->on_hardware
= 0;
172 nvs
->func
->UploadToHW(ctx
, nvs
);
173 nvs
->on_hardware
= 1;
182 nvsBuildTextShader(GLcontext
*ctx
, GLenum target
, const char *text
)
186 nvs
= CALLOC_STRUCT(_nouveauShader
);
190 if (target
== GL_VERTEX_PROGRAM_ARB
) {
191 _mesa_init_vertex_program(ctx
, &nvs
->mesa
.vp
, GL_VERTEX_PROGRAM_ARB
, 0);
192 _mesa_parse_arb_vertex_program(ctx
,
193 GL_VERTEX_PROGRAM_ARB
,
197 } else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
198 _mesa_init_fragment_program(ctx
, &nvs
->mesa
.fp
, GL_FRAGMENT_PROGRAM_ARB
, 0);
199 _mesa_parse_arb_fragment_program(ctx
,
200 GL_FRAGMENT_PROGRAM_ARB
,
206 nouveau_shader_pass0(ctx
, nvs
);
207 nouveau_shader_pass1(nvs
);
208 nouveau_shader_pass2(nvs
);
214 nvsBuildPassthroughVP(GLcontext
*ctx
)
216 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
218 const char *vp_text
=
220 "OPTION ARB_position_invariant;"
222 "MOV result.color, vertex.color;\n"
223 "MOV result.texcoord[0], vertex.texcoord[0];\n"
224 "MOV result.texcoord[1], vertex.texcoord[1];\n"
225 "MOV result.texcoord[2], vertex.texcoord[2];\n"
226 "MOV result.texcoord[3], vertex.texcoord[3];\n"
227 "MOV result.texcoord[4], vertex.texcoord[4];\n"
228 "MOV result.texcoord[5], vertex.texcoord[5];\n"
229 "MOV result.texcoord[6], vertex.texcoord[6];\n"
230 "MOV result.texcoord[7], vertex.texcoord[7];\n"
233 nmesa
->passthrough_vp
= nvsBuildTextShader(ctx
,
234 GL_VERTEX_PROGRAM_ARB
,
239 nvsBuildPassthroughFP(GLcontext
*ctx
)
241 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
243 const char *fp_text
=
245 "MOV result.color, fragment.color;\n"
248 nmesa
->passthrough_fp
= nvsBuildTextShader(ctx
,
249 GL_FRAGMENT_PROGRAM_ARB
,
254 nouveauShaderInitFuncs(GLcontext
* ctx
)
256 nouveauContextPtr nmesa
= NOUVEAU_CONTEXT(ctx
);
258 switch (nmesa
->screen
->card
->type
) {
260 NV20VPInitShaderFuncs(&nmesa
->VPfunc
);
263 NV30VPInitShaderFuncs(&nmesa
->VPfunc
);
264 NV30FPInitShaderFuncs(&nmesa
->FPfunc
);
268 NV40VPInitShaderFuncs(&nmesa
->VPfunc
);
269 NV40FPInitShaderFuncs(&nmesa
->FPfunc
);
276 /* Build a vertex program that simply passes through all attribs.
277 * Needed to do swtcl on nv40
279 if (nmesa
->screen
->card
->type
>= NV_40
)
280 nvsBuildPassthroughVP(ctx
);
282 /* Needed on NV30, even when using swtcl, if you want to get colours */
283 if (nmesa
->screen
->card
->type
>= NV_30
)
284 nvsBuildPassthroughFP(ctx
);
286 ctx
->Const
.VertexProgram
.MaxNativeInstructions
= nmesa
->VPfunc
.MaxInst
;
287 ctx
->Const
.VertexProgram
.MaxNativeAluInstructions
= nmesa
->VPfunc
.MaxInst
;
288 ctx
->Const
.VertexProgram
.MaxNativeTexInstructions
= nmesa
->VPfunc
.MaxInst
;
289 ctx
->Const
.VertexProgram
.MaxNativeTexIndirections
=
290 ctx
->Const
.VertexProgram
.MaxNativeTexInstructions
;
291 ctx
->Const
.VertexProgram
.MaxNativeAttribs
= nmesa
->VPfunc
.MaxAttrib
;
292 ctx
->Const
.VertexProgram
.MaxNativeTemps
= nmesa
->VPfunc
.MaxTemp
;
293 ctx
->Const
.VertexProgram
.MaxNativeAddressRegs
= nmesa
->VPfunc
.MaxAddress
;
294 ctx
->Const
.VertexProgram
.MaxNativeParameters
= nmesa
->VPfunc
.MaxConst
;
296 if (nmesa
->screen
->card
->type
>= NV_30
) {
297 ctx
->Const
.FragmentProgram
.MaxNativeInstructions
= nmesa
->FPfunc
.MaxInst
;
298 ctx
->Const
.FragmentProgram
.MaxNativeAluInstructions
= nmesa
->FPfunc
.MaxInst
;
299 ctx
->Const
.FragmentProgram
.MaxNativeTexInstructions
= nmesa
->FPfunc
.MaxInst
;
300 ctx
->Const
.FragmentProgram
.MaxNativeTexIndirections
=
301 ctx
->Const
.FragmentProgram
.MaxNativeTexInstructions
;
302 ctx
->Const
.FragmentProgram
.MaxNativeAttribs
= nmesa
->FPfunc
.MaxAttrib
;
303 ctx
->Const
.FragmentProgram
.MaxNativeTemps
= nmesa
->FPfunc
.MaxTemp
;
304 ctx
->Const
.FragmentProgram
.MaxNativeAddressRegs
= nmesa
->FPfunc
.MaxAddress
;
305 ctx
->Const
.FragmentProgram
.MaxNativeParameters
= nmesa
->FPfunc
.MaxConst
;
308 ctx
->Driver
.NewProgram
= nouveauNewProgram
;
309 ctx
->Driver
.BindProgram
= nouveauBindProgram
;
310 ctx
->Driver
.DeleteProgram
= nouveauDeleteProgram
;
311 ctx
->Driver
.ProgramStringNotify
= nouveauProgramStringNotify
;
312 ctx
->Driver
.IsProgramNative
= nouveauIsProgramNative
;
316 /*****************************************************************************
317 * Disassembly support structs
319 #define CHECK_RANGE(idx, arr) ((idx)<sizeof(_##arr)/sizeof(const char *)) \
320 ? _##arr[(idx)] : #arr"_OOB"
323 #define BRANCH_TR (1<<1)
324 #define BRANCH_EL (1<<2)
325 #define BRANCH_EN (1<<3)
326 #define BRANCH_RE (1<<4)
327 #define BRANCH_ALL (BRANCH_TR|BRANCH_EL|BRANCH_EN)
328 #define COUNT_INC (1<<4)
329 #define COUNT_IND (1<<5)
330 #define COUNT_NUM (1<<6)
331 #define COUNT_ALL (COUNT_INC|COUNT_IND|COUNT_NUM)
332 #define TI_UNIT (1<<7)
340 static struct _opcode_info ops
[] = {
341 [NVS_OP_ABS
] = {"ABS", 1, 0},
342 [NVS_OP_ADD
] = {"ADD", 2, 0},
343 [NVS_OP_ARA
] = {"ARA", 1, 0},
344 [NVS_OP_ARL
] = {"ARL", 1, 0},
345 [NVS_OP_ARR
] = {"ARR", 1, 0},
346 [NVS_OP_BRA
] = {"BRA", 0, NODS
| BRANCH_TR
},
347 [NVS_OP_BRK
] = {"BRK", 0, NODS
},
348 [NVS_OP_CAL
] = {"CAL", 0, NODS
| BRANCH_TR
},
349 [NVS_OP_CMP
] = {"CMP", 2, 0},
350 [NVS_OP_COS
] = {"COS", 1, 0},
351 [NVS_OP_DIV
] = {"DIV", 2, 0},
352 [NVS_OP_DDX
] = {"DDX", 1, 0},
353 [NVS_OP_DDY
] = {"DDY", 1, 0},
354 [NVS_OP_DP2
] = {"DP2", 2, 0},
355 [NVS_OP_DP2A
] = {"DP2A", 3, 0},
356 [NVS_OP_DP3
] = {"DP3", 2, 0},
357 [NVS_OP_DP4
] = {"DP4", 2, 0},
358 [NVS_OP_DPH
] = {"DPH", 2, 0},
359 [NVS_OP_DST
] = {"DST", 2, 0},
360 [NVS_OP_EX2
] = {"EX2", 1, 0},
361 [NVS_OP_EXP
] = {"EXP", 1, 0},
362 [NVS_OP_FLR
] = {"FLR", 1, 0},
363 [NVS_OP_FRC
] = {"FRC", 1, 0},
364 [NVS_OP_IF
] = {"IF", 0, NODS
| BRANCH_EL
| BRANCH_EN
},
365 [NVS_OP_KIL
] = {"KIL", 1, 0},
366 [NVS_OP_LG2
] = {"LG2", 1, 0},
367 [NVS_OP_LIT
] = {"LIT", 1, 0},
368 [NVS_OP_LOG
] = {"LOG", 1, 0},
369 [NVS_OP_LOOP
] = {"LOOP", 0, NODS
| COUNT_ALL
| BRANCH_EN
},
370 [NVS_OP_LRP
] = {"LRP", 3, 0},
371 [NVS_OP_MAD
] = {"MAD", 3, 0},
372 [NVS_OP_MAX
] = {"MAX", 2, 0},
373 [NVS_OP_MIN
] = {"MIN", 2, 0},
374 [NVS_OP_MOV
] = {"MOV", 1, 0},
375 [NVS_OP_MUL
] = {"MUL", 2, 0},
376 [NVS_OP_NRM
] = {"NRM", 1, 0},
377 [NVS_OP_PK2H
] = {"PK2H", 1, 0},
378 [NVS_OP_PK2US
] = {"PK2US", 1, 0},
379 [NVS_OP_PK4B
] = {"PK4B", 1, 0},
380 [NVS_OP_PK4UB
] = {"PK4UB", 1, 0},
381 [NVS_OP_POW
] = {"POW", 2, 0},
382 [NVS_OP_POPA
] = {"POPA", 0, 0},
383 [NVS_OP_PUSHA
] = {"PUSHA", 1, NODS
},
384 [NVS_OP_RCC
] = {"RCC", 1, 0},
385 [NVS_OP_RCP
] = {"RCP", 1, 0},
386 [NVS_OP_REP
] = {"REP", 0, NODS
| BRANCH_EN
| COUNT_NUM
},
387 [NVS_OP_RET
] = {"RET", 0, NODS
},
388 [NVS_OP_RFL
] = {"RFL", 1, 0},
389 [NVS_OP_RSQ
] = {"RSQ", 1, 0},
390 [NVS_OP_SCS
] = {"SCS", 1, 0},
391 [NVS_OP_SEQ
] = {"SEQ", 2, 0},
392 [NVS_OP_SFL
] = {"SFL", 2, 0},
393 [NVS_OP_SGE
] = {"SGE", 2, 0},
394 [NVS_OP_SGT
] = {"SGT", 2, 0},
395 [NVS_OP_SIN
] = {"SIN", 1, 0},
396 [NVS_OP_SLE
] = {"SLE", 2, 0},
397 [NVS_OP_SLT
] = {"SLT", 2, 0},
398 [NVS_OP_SNE
] = {"SNE", 2, 0},
399 [NVS_OP_SSG
] = {"SSG", 1, 0},
400 [NVS_OP_STR
] = {"STR", 2, 0},
401 [NVS_OP_SUB
] = {"SUB", 2, 0},
402 [NVS_OP_TEX
] = {"TEX", 1, TI_UNIT
},
403 [NVS_OP_TXB
] = {"TXB", 1, TI_UNIT
},
404 [NVS_OP_TXD
] = {"TXD", 3, TI_UNIT
},
405 [NVS_OP_TXL
] = {"TXL", 1, TI_UNIT
},
406 [NVS_OP_TXP
] = {"TXP", 1, TI_UNIT
},
407 [NVS_OP_UP2H
] = {"UP2H", 1, 0},
408 [NVS_OP_UP2US
] = {"UP2US", 1, 0},
409 [NVS_OP_UP4B
] = {"UP4B", 1, 0},
410 [NVS_OP_UP4UB
] = {"UP4UB", 1, 0},
411 [NVS_OP_X2D
] = {"X2D", 3, 0},
412 [NVS_OP_XPD
] = {"XPD", 2, 0},
413 [NVS_OP_NOP
] = {"NOP", 0, NODS
},
416 static struct _opcode_info
*
419 if (op
>= (sizeof(ops
) / sizeof(struct _opcode_info
)))
421 if (ops
[op
].name
== NULL
)
426 static const char *_SFR_STRING
[] = {
427 [NVS_FR_POSITION
] = "position",
428 [NVS_FR_WEIGHT
] = "weight",
429 [NVS_FR_NORMAL
] = "normal",
430 [NVS_FR_COL0
] = "color",
431 [NVS_FR_COL1
] = "color.secondary",
432 [NVS_FR_BFC0
] = "bfc",
433 [NVS_FR_BFC1
] = "bfc.secondary",
434 [NVS_FR_FOGCOORD
] = "fogcoord",
435 [NVS_FR_POINTSZ
] = "pointsize",
436 [NVS_FR_TEXCOORD0
] = "texcoord[0]",
437 [NVS_FR_TEXCOORD1
] = "texcoord[1]",
438 [NVS_FR_TEXCOORD2
] = "texcoord[2]",
439 [NVS_FR_TEXCOORD3
] = "texcoord[3]",
440 [NVS_FR_TEXCOORD4
] = "texcoord[4]",
441 [NVS_FR_TEXCOORD5
] = "texcoord[5]",
442 [NVS_FR_TEXCOORD6
] = "texcoord[6]",
443 [NVS_FR_TEXCOORD7
] = "texcoord[7]",
444 [NVS_FR_FRAGDATA0
] = "data[0]",
445 [NVS_FR_FRAGDATA1
] = "data[1]",
446 [NVS_FR_FRAGDATA2
] = "data[2]",
447 [NVS_FR_FRAGDATA3
] = "data[3]",
448 [NVS_FR_CLIP0
] = "clip_plane[0]",
449 [NVS_FR_CLIP1
] = "clip_plane[1]",
450 [NVS_FR_CLIP2
] = "clip_plane[2]",
451 [NVS_FR_CLIP3
] = "clip_plane[3]",
452 [NVS_FR_CLIP4
] = "clip_plane[4]",
453 [NVS_FR_CLIP5
] = "clip_plane[5]",
454 [NVS_FR_CLIP6
] = "clip_plane[6]",
455 [NVS_FR_FACING
] = "facing",
458 #define SFR_STRING(idx) CHECK_RANGE((idx), SFR_STRING)
460 static const char *_SWZ_STRING
[] = {
467 #define SWZ_STRING(idx) CHECK_RANGE((idx), SWZ_STRING)
469 static const char *_NVS_PREC_STRING
[] = {
470 [NVS_PREC_FLOAT32
] = "R",
471 [NVS_PREC_FLOAT16
] = "H",
472 [NVS_PREC_FIXED12
] = "X",
473 [NVS_PREC_UNKNOWN
] = "?"
476 #define NVS_PREC_STRING(idx) CHECK_RANGE((idx), NVS_PREC_STRING)
478 static const char *_NVS_COND_STRING
[] = {
479 [NVS_COND_FL
] = "FL",
480 [NVS_COND_LT
] = "LT",
481 [NVS_COND_EQ
] = "EQ",
482 [NVS_COND_LE
] = "LE",
483 [NVS_COND_GT
] = "GT",
484 [NVS_COND_NE
] = "NE",
485 [NVS_COND_GE
] = "GE",
486 [NVS_COND_TR
] = "TR",
487 [NVS_COND_UNKNOWN
] = "??"
490 #define NVS_COND_STRING(idx) CHECK_RANGE((idx), NVS_COND_STRING)
492 /*****************************************************************************
493 * ShaderFragment dumping
496 nvsDumpIndent(int lvl
)
503 nvsDumpSwizzle(nvsSwzComp
*swz
)
507 SWZ_STRING(swz
[1]), SWZ_STRING(swz
[2]), SWZ_STRING(swz
[3])
512 nvsDumpReg(nvsInstruction
* inst
, nvsRegister
* reg
)
521 printf("R%d", reg
->index
);
522 nvsDumpSwizzle(reg
->swizzle
);
524 case NVS_FILE_ATTRIB
:
525 printf("attrib.%s", SFR_STRING(reg
->index
));
526 nvsDumpSwizzle(reg
->swizzle
);
528 case NVS_FILE_ADDRESS
:
529 printf("A%d", reg
->index
);
533 printf("const[A%d.%s + %d]",
534 reg
->addr_reg
, SWZ_STRING(reg
->addr_comp
), reg
->index
);
536 printf("const[%d]", reg
->index
);
537 nvsDumpSwizzle(reg
->swizzle
);
540 printf("UNKNOWN_FILE");
549 nvsDumpInstruction(nvsInstruction
* inst
, int slot
, int lvl
)
551 struct _opcode_info
*opr
= &ops
[inst
->op
];
555 printf("%s ", opr
->name
);
557 if (!opr
->flags
& NODS
) {
558 switch (inst
->dest
.file
) {
559 case NVS_FILE_RESULT
:
560 printf("result.%s", SFR_STRING(inst
->dest
.index
));
563 printf("R%d", inst
->dest
.index
);
565 case NVS_FILE_ADDRESS
:
566 printf("A%d", inst
->dest
.index
);
569 printf("UNKNOWN_DST_FILE");
573 if (inst
->mask
!= SMASK_ALL
) {
575 if (inst
->mask
& SMASK_X
)
577 if (inst
->mask
& SMASK_Y
)
579 if (inst
->mask
& SMASK_Z
)
581 if (inst
->mask
& SMASK_W
)
589 for (i
= 0; i
< opr
->numsrc
; i
++) {
590 nvsDumpReg(inst
, &inst
->src
[i
]);
591 if (i
!= opr
->numsrc
- 1)
594 if (opr
->flags
& TI_UNIT
)
595 printf(", texture[%d]", inst
->tex_unit
);
601 nvsDumpFragmentList(nvsFragmentHeader
*f
, int lvl
)
605 case NVS_INSTRUCTION
:
606 nvsDumpInstruction((nvsInstruction
*)f
, 0, lvl
);
609 fprintf(stderr
, "%s: Only NVS_INSTRUCTION fragments can be in"
610 "nvsFragmentList!\n", __func__
);
617 /*****************************************************************************
618 * HW shader disassembly
621 nvsDisasmHWShaderOp(nvsFunc
* shader
, int merged
)
623 struct _opcode_info
*opi
;
629 op
= shader
->GetOpcode(shader
, merged
);
630 opi
= _get_op_info(op
);
632 printf("NO OPINFO!");
636 printf("%s", opi
->name
);
637 if (shader
->GetPrecision
&&
638 (!(opi
->flags
& BRANCH_ALL
)) && (!(opi
->flags
* NODS
)) &&
640 printf("%s", NVS_PREC_STRING(shader
->GetPrecision(shader
)));
641 if (shader
->SupportsConditional
&& shader
->SupportsConditional(shader
)) {
642 if (shader
->GetConditionUpdate(shader
)) {
643 printf("C%d", shader
->GetCondRegID(shader
));
646 if (shader
->GetSaturate
&& shader
->GetSaturate(shader
))
649 if (!(opi
->flags
& NODS
)) {
650 int mask
= shader
->GetDestMask(shader
, merged
);
652 switch (shader
->GetDestFile(shader
, merged
)) {
653 case NVS_FILE_ADDRESS
:
654 printf(" A%d", shader
->GetDestID(shader
, merged
));
657 printf(" R%d", shader
->GetDestID(shader
, merged
));
659 case NVS_FILE_RESULT
:
660 printf(" result.%s", (SFR_STRING(shader
->GetDestID(shader
, merged
))));
663 printf(" BAD_RESULT_FILE");
667 if (mask
!= SMASK_ALL
) {
669 if (mask
& SMASK_X
) printf("x");
670 if (mask
& SMASK_Y
) printf("y");
671 if (mask
& SMASK_Z
) printf("z");
672 if (mask
& SMASK_W
) printf("w");
676 if (shader
->SupportsConditional
&& shader
->SupportsConditional(shader
) &&
677 shader
->GetConditionTest(shader
)) {
678 shader
->GetCondRegSwizzle(shader
, swz
);
680 printf(" (%s%d.%s%s%s%s)",
681 NVS_COND_STRING(shader
->GetCondition(shader
)),
682 shader
->GetCondRegID(shader
),
683 SWZ_STRING(swz
[NVS_SWZ_X
]),
684 SWZ_STRING(swz
[NVS_SWZ_Y
]),
685 SWZ_STRING(swz
[NVS_SWZ_Z
]),
686 SWZ_STRING(swz
[NVS_SWZ_W
])
691 if (opi
->flags
& COUNT_ALL
) {
693 if (opi
->flags
& COUNT_NUM
) {
694 printf("%d", shader
->GetLoopCount(shader
));
696 if (opi
->flags
& COUNT_IND
) {
697 printf(", %d", shader
->GetLoopInitial(shader
));
699 if (opi
->flags
& COUNT_INC
) {
700 printf(", %d", shader
->GetLoopIncrement(shader
));
706 if (opi
->flags
& BRANCH_TR
)
707 printf(" %d", shader
->GetBranch(shader
));
708 if (opi
->flags
& BRANCH_EL
)
709 printf(" ELSE %d", shader
->GetBranchElse(shader
));
710 if (opi
->flags
& BRANCH_EN
)
711 printf(" END %d", shader
->GetBranchEnd(shader
));
713 if (!(opi
->flags
& NODS
) && opi
->numsrc
)
717 for (i
= 0; i
< opi
->numsrc
; i
++) {
718 if (shader
->GetSourceAbs(shader
, merged
, i
))
720 if (shader
->GetSourceNegate(shader
, merged
, i
))
723 file
= shader
->GetSourceFile(shader
, merged
, i
);
726 printf("R%d", shader
->GetSourceID(shader
, merged
, i
));
729 if (shader
->GetSourceIndexed(shader
, merged
, i
)) {
730 printf("c[A%d.%s + 0x%x]",
731 shader
->GetRelAddressRegID(shader
),
732 SWZ_STRING(shader
->GetRelAddressSwizzle(shader
)),
733 shader
->GetSourceID(shader
, merged
, i
)
738 if (shader
->GetSourceConstVal
) {
739 shader
->GetSourceConstVal(shader
, merged
, i
, val
);
740 printf("{ %.02f, %.02f, %.02f, %.02f }",
741 val
[0], val
[1], val
[2], val
[3]);
743 printf("c[0x%x]", shader
->GetSourceID(shader
, merged
, i
));
747 case NVS_FILE_ATTRIB
:
748 if (shader
->GetSourceIndexed(shader
, merged
, i
)) {
749 printf("attrib[A%d.%s + %d]",
750 shader
->GetRelAddressRegID(shader
),
751 SWZ_STRING(shader
->GetRelAddressSwizzle(shader
)),
752 shader
->GetSourceID(shader
, merged
, i
)
757 SFR_STRING(shader
->GetSourceID(shader
, merged
, i
))
761 case NVS_FILE_ADDRESS
:
762 printf("A%d", shader
->GetRelAddressRegID(shader
));
765 printf("UNKNOWN_SRC_FILE");
769 shader
->GetSourceSwizzle(shader
, merged
, i
, swz
);
770 if (file
!= NVS_FILE_ADDRESS
&&
771 (swz
[NVS_SWZ_X
] != NVS_SWZ_X
|| swz
[NVS_SWZ_Y
] != NVS_SWZ_Y
||
772 swz
[NVS_SWZ_Z
] != NVS_SWZ_Z
|| swz
[NVS_SWZ_W
] != NVS_SWZ_W
)) {
773 printf(".%s%s%s%s", SWZ_STRING(swz
[NVS_SWZ_X
]),
774 SWZ_STRING(swz
[NVS_SWZ_Y
]),
775 SWZ_STRING(swz
[NVS_SWZ_Z
]),
776 SWZ_STRING(swz
[NVS_SWZ_W
]));
779 if (shader
->GetSourceAbs(shader
, merged
, i
))
781 if (shader
->GetSourceScale
) {
782 int scale
= shader
->GetSourceScale(shader
, merged
, i
);
784 printf("{scaled %dx}", scale
);
786 if (i
< (opi
->numsrc
- 1))
790 if (shader
->IsLastInst(shader
))
795 nvsDisasmHWShader(nvsPtr nvs
)
797 nvsFunc
*shader
= nvs
->func
;
798 unsigned int iaddr
= 0;
801 fprintf(stderr
, "No HW program present");
805 shader
->inst
= nvs
->program
;
807 if (shader
->inst
>= (nvs
->program
+ nvs
->program_size
)) {
808 fprintf(stderr
, "Reached end of program, but HW inst has no END");
812 printf("\t0x%08x:\n", shader
->inst
[0]);
813 printf("\t0x%08x:\n", shader
->inst
[1]);
814 printf("\t0x%08x:\n", shader
->inst
[2]);
815 printf("\t0x%08x:", shader
->inst
[3]);
817 printf("\n\t\tINST %d.0: ", iaddr
);
818 nvsDisasmHWShaderOp(shader
, 0);
819 if (shader
->HasMergedInst(shader
)) {
820 printf("\n\t\tINST %d.1: ", iaddr
);
821 nvsDisasmHWShaderOp(shader
, 1);
825 if (shader
->IsLastInst(shader
))
828 shader
->inst
+= shader
->GetOffsetNext(shader
);