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"
40 #include "shader/arbprogparse.h"
42 #include "nouveau_context.h"
43 #include "nouveau_shader.h"
45 /*****************************************************************************
49 nouveauBindProgram(GLcontext *ctx, GLenum target, struct gl_program *prog)
53 static struct gl_program *
54 nouveauNewProgram(GLcontext *ctx, GLenum target, GLuint id)
58 nvs = CALLOC_STRUCT(_nouveauShader);
60 case GL_VERTEX_PROGRAM_ARB:
61 return _mesa_init_vertex_program(ctx, &nvs->mesa.vp, target, id);
62 case GL_FRAGMENT_PROGRAM_ARB:
63 return _mesa_init_fragment_program(ctx, &nvs->mesa.fp, target, id);
65 _mesa_problem(ctx, "Unsupported shader target");
74 nouveauDeleteProgram(GLcontext *ctx, struct gl_program *prog)
76 nouveauShader *nvs = (nouveauShader *)prog;
80 _mesa_delete_program(ctx, prog);
84 nouveauProgramStringNotify(GLcontext *ctx, GLenum target,
85 struct gl_program *prog)
87 nouveauShader *nvs = (nouveauShader *)prog;
93 _tnl_program_string(ctx, target, prog);
97 nouveauIsProgramNative(GLcontext * ctx, GLenum target, struct gl_program *prog)
99 nouveauShader *nvs = (nouveauShader *)prog;
101 return nvs->translated;
105 nvsUpdateShader(GLcontext *ctx, nouveauShader *nvs)
107 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
108 struct gl_program_parameter_list *plist;
111 /* Translate to HW format now if necessary */
112 if (!nvs->translated) {
113 /* Mesa ASM shader -> nouveauShader */
114 if (!nouveau_shader_pass0_arb(ctx, nvs))
116 /* Basic dead code elimination + register usage info */
117 if (!nouveau_shader_pass1(nvs))
119 /* nouveauShader -> HW bytecode, HW register alloc */
120 if (!nouveau_shader_pass2(nvs))
122 assert(nvs->translated);
123 assert(nvs->program);
126 /* Update state parameters */
127 plist = nvs->mesa.vp.Base.Parameters;
128 _mesa_load_state_parameters(ctx, plist);
129 for (i=0; i<plist->NumParameters; i++) {
130 if (!nvs->on_hardware) {
131 /* if we've been kicked off the hardware there's no guarantee our
132 * consts are still there.. reupload them all
134 nvs->func->UpdateConst(ctx, nvs, i);
135 } else if (plist->Parameters[i].Type == PROGRAM_STATE_VAR) {
136 if (!nvs->params[i].source_val) /* this is a workaround when consts aren't alloc'd from id=0.. */
138 /* update any changed state parameters */
139 if (!TEST_EQ_4V(nvs->params[i].val, nvs->params[i].source_val))
140 nvs->func->UpdateConst(ctx, nvs, i);
144 /* Upload program to hardware, this must come after state param update
145 * as >=NV30 fragprogs inline consts into the bytecode.
147 if (!nvs->on_hardware) {
148 nouveauShader **current;
150 if (nvs->mesa.vp.Base.Target == GL_VERTEX_PROGRAM_ARB)
151 current = &nmesa->current_vertprog;
153 current = &nmesa->current_fragprog;
154 if (*current) (*current)->on_hardware = 0;
156 nvs->func->UploadToHW(ctx, nvs);
157 nvs->on_hardware = 1;
166 nvsBuildTextShader(GLcontext *ctx, GLenum target, const char *text)
170 nvs = CALLOC_STRUCT(_nouveauShader);
174 if (target == GL_VERTEX_PROGRAM_ARB) {
175 _mesa_init_vertex_program(ctx, &nvs->mesa.vp, GL_VERTEX_PROGRAM_ARB, 0);
176 _mesa_parse_arb_vertex_program(ctx,
177 GL_VERTEX_PROGRAM_ARB,
181 } else if (target == GL_FRAGMENT_PROGRAM_ARB) {
182 _mesa_init_fragment_program(ctx, &nvs->mesa.fp, GL_VERTEX_PROGRAM_ARB, 0);
183 _mesa_parse_arb_fragment_program(ctx,
184 GL_FRAGMENT_PROGRAM_ARB,
190 nouveau_shader_pass0_arb(ctx, nvs);
191 nouveau_shader_pass1(nvs);
192 nouveau_shader_pass2(nvs);
198 nvsBuildPassthroughVP(GLcontext *ctx)
200 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
202 const char *vp_text =
204 "OPTION ARB_position_invariant;"
206 "MOV result.color, vertex.color;\n"
207 "MOV result.texcoord[0], vertex.texcoord[0];\n"
208 "MOV result.texcoord[1], vertex.texcoord[1];\n"
209 "MOV result.texcoord[2], vertex.texcoord[2];\n"
210 "MOV result.texcoord[3], vertex.texcoord[3];\n"
211 "MOV result.texcoord[4], vertex.texcoord[4];\n"
212 "MOV result.texcoord[5], vertex.texcoord[5];\n"
213 "MOV result.texcoord[6], vertex.texcoord[6];\n"
214 "MOV result.texcoord[7], vertex.texcoord[7];\n"
217 nmesa->passthrough_vp = nvsBuildTextShader(ctx,
218 GL_VERTEX_PROGRAM_ARB,
223 nouveauShaderInitFuncs(GLcontext * ctx)
225 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
227 switch (nmesa->screen->card->type) {
229 NV20VPInitShaderFuncs(&nmesa->VPfunc);
232 NV30VPInitShaderFuncs(&nmesa->VPfunc);
233 NV30FPInitShaderFuncs(&nmesa->FPfunc);
237 NV40VPInitShaderFuncs(&nmesa->VPfunc);
238 NV40FPInitShaderFuncs(&nmesa->FPfunc);
245 /* Build a vertex program that simply passes through all attribs.
246 * Needed to do swtcl on nv40
248 if (nmesa->screen->card->type >= NV_40)
249 nvsBuildPassthroughVP(ctx);
251 ctx->Const.VertexProgram.MaxNativeInstructions = nmesa->VPfunc.MaxInst;
252 ctx->Const.VertexProgram.MaxNativeAluInstructions = nmesa->VPfunc.MaxInst;
253 ctx->Const.VertexProgram.MaxNativeTexInstructions = nmesa->VPfunc.MaxInst;
254 ctx->Const.VertexProgram.MaxNativeTexIndirections =
255 ctx->Const.VertexProgram.MaxNativeTexInstructions;
256 ctx->Const.VertexProgram.MaxNativeAttribs = nmesa->VPfunc.MaxAttrib;
257 ctx->Const.VertexProgram.MaxNativeTemps = nmesa->VPfunc.MaxTemp;
258 ctx->Const.VertexProgram.MaxNativeAddressRegs = nmesa->VPfunc.MaxAddress;
259 ctx->Const.VertexProgram.MaxNativeParameters = nmesa->VPfunc.MaxConst;
261 if (nmesa->screen->card->type >= NV_30) {
262 ctx->Const.FragmentProgram.MaxNativeInstructions = nmesa->FPfunc.MaxInst;
263 ctx->Const.FragmentProgram.MaxNativeAluInstructions = nmesa->FPfunc.MaxInst;
264 ctx->Const.FragmentProgram.MaxNativeTexInstructions = nmesa->FPfunc.MaxInst;
265 ctx->Const.FragmentProgram.MaxNativeTexIndirections =
266 ctx->Const.FragmentProgram.MaxNativeTexInstructions;
267 ctx->Const.FragmentProgram.MaxNativeAttribs = nmesa->FPfunc.MaxAttrib;
268 ctx->Const.FragmentProgram.MaxNativeTemps = nmesa->FPfunc.MaxTemp;
269 ctx->Const.FragmentProgram.MaxNativeAddressRegs = nmesa->FPfunc.MaxAddress;
270 ctx->Const.FragmentProgram.MaxNativeParameters = nmesa->FPfunc.MaxConst;
273 ctx->Driver.NewProgram = nouveauNewProgram;
274 ctx->Driver.BindProgram = nouveauBindProgram;
275 ctx->Driver.DeleteProgram = nouveauDeleteProgram;
276 ctx->Driver.ProgramStringNotify = nouveauProgramStringNotify;
277 ctx->Driver.IsProgramNative = nouveauIsProgramNative;
281 /*****************************************************************************
282 * Disassembly support structs
284 #define CHECK_RANGE(idx, arr) ((idx)<sizeof(_##arr)/sizeof(const char *)) \
285 ? _##arr[(idx)] : #arr"_OOB"
288 #define BRANCH_TR (1<<1)
289 #define BRANCH_EL (1<<2)
290 #define BRANCH_EN (1<<3)
291 #define BRANCH_RE (1<<4)
292 #define BRANCH_ALL (BRANCH_TR|BRANCH_EL|BRANCH_EN)
293 #define COUNT_INC (1<<4)
294 #define COUNT_IND (1<<5)
295 #define COUNT_NUM (1<<6)
296 #define COUNT_ALL (COUNT_INC|COUNT_IND|COUNT_NUM)
297 #define TI_UNIT (1<<7)
305 static struct _opcode_info ops[] = {
306 [NVS_OP_ABS] = {"ABS", 1, 0},
307 [NVS_OP_ADD] = {"ADD", 2, 0},
308 [NVS_OP_ARA] = {"ARA", 1, 0},
309 [NVS_OP_ARL] = {"ARL", 1, 0},
310 [NVS_OP_ARR] = {"ARR", 1, 0},
311 [NVS_OP_BRA] = {"BRA", 0, NODS | BRANCH_TR},
312 [NVS_OP_BRK] = {"BRK", 0, NODS},
313 [NVS_OP_CAL] = {"CAL", 0, NODS | BRANCH_TR},
314 [NVS_OP_CMP] = {"CMP", 2, 0},
315 [NVS_OP_COS] = {"COS", 1, 0},
316 [NVS_OP_DIV] = {"DIV", 2, 0},
317 [NVS_OP_DDX] = {"DDX", 1, 0},
318 [NVS_OP_DDY] = {"DDY", 1, 0},
319 [NVS_OP_DP2] = {"DP2", 2, 0},
320 [NVS_OP_DP2A] = {"DP2A", 3, 0},
321 [NVS_OP_DP3] = {"DP3", 2, 0},
322 [NVS_OP_DP4] = {"DP4", 2, 0},
323 [NVS_OP_DPH] = {"DPH", 2, 0},
324 [NVS_OP_DST] = {"DST", 2, 0},
325 [NVS_OP_EX2] = {"EX2", 1, 0},
326 [NVS_OP_EXP] = {"EXP", 1, 0},
327 [NVS_OP_FLR] = {"FLR", 1, 0},
328 [NVS_OP_FRC] = {"FRC", 1, 0},
329 [NVS_OP_IF] = {"IF", 0, NODS | BRANCH_EL | BRANCH_EN},
330 [NVS_OP_KIL] = {"KIL", 1, 0},
331 [NVS_OP_LG2] = {"LG2", 1, 0},
332 [NVS_OP_LIT] = {"LIT", 1, 0},
333 [NVS_OP_LOG] = {"LOG", 1, 0},
334 [NVS_OP_LOOP] = {"LOOP", 0, NODS | COUNT_ALL | BRANCH_EN},
335 [NVS_OP_LRP] = {"LRP", 3, 0},
336 [NVS_OP_MAD] = {"MAD", 3, 0},
337 [NVS_OP_MAX] = {"MAX", 2, 0},
338 [NVS_OP_MIN] = {"MIN", 2, 0},
339 [NVS_OP_MOV] = {"MOV", 1, 0},
340 [NVS_OP_MUL] = {"MUL", 2, 0},
341 [NVS_OP_NRM] = {"NRM", 1, 0},
342 [NVS_OP_PK2H] = {"PK2H", 1, 0},
343 [NVS_OP_PK2US] = {"PK2US", 1, 0},
344 [NVS_OP_PK4B] = {"PK4B", 1, 0},
345 [NVS_OP_PK4UB] = {"PK4UB", 1, 0},
346 [NVS_OP_POW] = {"POW", 2, 0},
347 [NVS_OP_POPA] = {"POPA", 0, 0},
348 [NVS_OP_PUSHA] = {"PUSHA", 1, NODS},
349 [NVS_OP_RCC] = {"RCC", 1, 0},
350 [NVS_OP_RCP] = {"RCP", 1, 0},
351 [NVS_OP_REP] = {"REP", 0, NODS | BRANCH_EN | COUNT_NUM},
352 [NVS_OP_RET] = {"RET", 0, NODS},
353 [NVS_OP_RFL] = {"RFL", 1, 0},
354 [NVS_OP_RSQ] = {"RSQ", 1, 0},
355 [NVS_OP_SCS] = {"SCS", 1, 0},
356 [NVS_OP_SEQ] = {"SEQ", 2, 0},
357 [NVS_OP_SFL] = {"SFL", 2, 0},
358 [NVS_OP_SGE] = {"SGE", 2, 0},
359 [NVS_OP_SGT] = {"SGT", 2, 0},
360 [NVS_OP_SIN] = {"SIN", 1, 0},
361 [NVS_OP_SLE] = {"SLE", 2, 0},
362 [NVS_OP_SLT] = {"SLT", 2, 0},
363 [NVS_OP_SNE] = {"SNE", 2, 0},
364 [NVS_OP_SSG] = {"SSG", 1, 0},
365 [NVS_OP_STR] = {"STR", 2, 0},
366 [NVS_OP_SUB] = {"SUB", 2, 0},
367 [NVS_OP_TEX] = {"TEX", 1, TI_UNIT},
368 [NVS_OP_TXB] = {"TXB", 1, TI_UNIT},
369 [NVS_OP_TXD] = {"TXD", 3, TI_UNIT},
370 [NVS_OP_TXL] = {"TXL", 1, TI_UNIT},
371 [NVS_OP_TXP] = {"TXP", 1, TI_UNIT},
372 [NVS_OP_UP2H] = {"UP2H", 1, 0},
373 [NVS_OP_UP2US] = {"UP2US", 1, 0},
374 [NVS_OP_UP4B] = {"UP4B", 1, 0},
375 [NVS_OP_UP4UB] = {"UP4UB", 1, 0},
376 [NVS_OP_X2D] = {"X2D", 3, 0},
377 [NVS_OP_XPD] = {"XPD", 2, 0},
378 [NVS_OP_NOP] = {"NOP", 0, NODS},
381 static struct _opcode_info *
384 if (op >= (sizeof(ops) / sizeof(struct _opcode_info)))
386 if (ops[op].name == NULL)
391 static const char *_SFR_STRING[] = {
392 [NVS_FR_POSITION] = "position",
393 [NVS_FR_WEIGHT] = "weight",
394 [NVS_FR_NORMAL] = "normal",
395 [NVS_FR_COL0] = "color",
396 [NVS_FR_COL1] = "color.secondary",
397 [NVS_FR_BFC0] = "bfc",
398 [NVS_FR_BFC1] = "bfc.secondary",
399 [NVS_FR_FOGCOORD] = "fogcoord",
400 [NVS_FR_POINTSZ] = "pointsize",
401 [NVS_FR_TEXCOORD0] = "texcoord[0]",
402 [NVS_FR_TEXCOORD1] = "texcoord[1]",
403 [NVS_FR_TEXCOORD2] = "texcoord[2]",
404 [NVS_FR_TEXCOORD3] = "texcoord[3]",
405 [NVS_FR_TEXCOORD4] = "texcoord[4]",
406 [NVS_FR_TEXCOORD5] = "texcoord[5]",
407 [NVS_FR_TEXCOORD6] = "texcoord[6]",
408 [NVS_FR_TEXCOORD7] = "texcoord[7]",
409 [NVS_FR_FRAGDATA0] = "data[0]",
410 [NVS_FR_FRAGDATA1] = "data[1]",
411 [NVS_FR_FRAGDATA2] = "data[2]",
412 [NVS_FR_FRAGDATA3] = "data[3]",
413 [NVS_FR_CLIP0] = "clip_plane[0]",
414 [NVS_FR_CLIP1] = "clip_plane[1]",
415 [NVS_FR_CLIP2] = "clip_plane[2]",
416 [NVS_FR_CLIP3] = "clip_plane[3]",
417 [NVS_FR_CLIP4] = "clip_plane[4]",
418 [NVS_FR_CLIP5] = "clip_plane[5]",
419 [NVS_FR_CLIP6] = "clip_plane[6]",
420 [NVS_FR_FACING] = "facing",
423 #define SFR_STRING(idx) CHECK_RANGE((idx), SFR_STRING)
425 static const char *_SWZ_STRING[] = {
432 #define SWZ_STRING(idx) CHECK_RANGE((idx), SWZ_STRING)
434 static const char *_NVS_PREC_STRING[] = {
435 [NVS_PREC_FLOAT32] = "R",
436 [NVS_PREC_FLOAT16] = "H",
437 [NVS_PREC_FIXED12] = "X",
438 [NVS_PREC_UNKNOWN] = "?"
441 #define NVS_PREC_STRING(idx) CHECK_RANGE((idx), NVS_PREC_STRING)
443 static const char *_NVS_COND_STRING[] = {
444 [NVS_COND_FL] = "FL",
445 [NVS_COND_LT] = "LT",
446 [NVS_COND_EQ] = "EQ",
447 [NVS_COND_LE] = "LE",
448 [NVS_COND_GT] = "GT",
449 [NVS_COND_NE] = "NE",
450 [NVS_COND_GE] = "GE",
451 [NVS_COND_TR] = "TR",
452 [NVS_COND_UNKNOWN] = "??"
455 #define NVS_COND_STRING(idx) CHECK_RANGE((idx), NVS_COND_STRING)
457 /*****************************************************************************
458 * ShaderFragment dumping
461 nvsDumpIndent(int lvl)
468 nvsDumpSwizzle(nvsSwzComp *swz)
472 SWZ_STRING(swz[1]), SWZ_STRING(swz[2]), SWZ_STRING(swz[3])
477 nvsDumpReg(nvsInstruction * inst, nvsRegister * reg)
486 printf("R%d", reg->index);
487 nvsDumpSwizzle(reg->swizzle);
489 case NVS_FILE_ATTRIB:
490 printf("attrib.%s", SFR_STRING(reg->index));
491 nvsDumpSwizzle(reg->swizzle);
493 case NVS_FILE_ADDRESS:
494 printf("A%d", reg->index);
498 printf("const[A%d.%s + %d]",
499 reg->addr_reg, SWZ_STRING(reg->addr_comp), reg->index);
501 printf("const[%d]", reg->index);
502 nvsDumpSwizzle(reg->swizzle);
505 printf("UNKNOWN_FILE");
514 nvsDumpInstruction(nvsInstruction * inst, int slot, int lvl)
516 struct _opcode_info *opr = &ops[inst->op];
520 printf("%s ", opr->name);
522 if (!opr->flags & NODS) {
523 switch (inst->dest.file) {
524 case NVS_FILE_RESULT:
525 printf("result.%s", SFR_STRING(inst->dest.index));
528 printf("R%d", inst->dest.index);
530 case NVS_FILE_ADDRESS:
531 printf("A%d", inst->dest.index);
534 printf("UNKNOWN_DST_FILE");
538 if (inst->mask != SMASK_ALL) {
540 if (inst->mask & SMASK_X)
542 if (inst->mask & SMASK_Y)
544 if (inst->mask & SMASK_Z)
546 if (inst->mask & SMASK_W)
554 for (i = 0; i < opr->numsrc; i++) {
555 nvsDumpReg(inst, &inst->src[i]);
556 if (i != opr->numsrc - 1)
559 if (opr->flags & TI_UNIT)
560 printf(", texture[%d]", inst->tex_unit);
566 nvsDumpFragmentList(nvsFragmentList *f, int lvl)
569 switch (f->fragment->type) {
570 case NVS_INSTRUCTION:
571 nvsDumpInstruction((nvsInstruction*)f->fragment, 0, lvl);
574 fprintf(stderr, "%s: Only NVS_INSTRUCTION fragments can be in"
575 "nvsFragmentList!\n", __func__);
582 /*****************************************************************************
583 * HW shader disassembly
586 nvsDisasmHWShaderOp(nvsFunc * shader, int merged)
588 struct _opcode_info *opi;
594 op = shader->GetOpcode(shader, merged);
595 opi = _get_op_info(op);
597 printf("NO OPINFO!");
601 printf("%s", opi->name);
602 if (shader->GetPrecision &&
603 (!(opi->flags & BRANCH_ALL)) && (!(opi->flags * NODS)) &&
605 printf("%s", NVS_PREC_STRING(shader->GetPrecision(shader)));
606 if (shader->SupportsConditional && shader->SupportsConditional(shader)) {
607 if (shader->GetConditionUpdate(shader)) {
608 printf("C%d", shader->GetCondRegID(shader));
611 if (shader->GetSaturate && shader->GetSaturate(shader))
614 if (!(opi->flags & NODS)) {
615 int mask = shader->GetDestMask(shader, merged);
617 switch (shader->GetDestFile(shader, merged)) {
618 case NVS_FILE_ADDRESS:
619 printf(" A%d", shader->GetDestID(shader, merged));
622 printf(" R%d", shader->GetDestID(shader, merged));
624 case NVS_FILE_RESULT:
625 printf(" result.%s", (SFR_STRING(shader->GetDestID(shader, merged))));
628 printf(" BAD_RESULT_FILE");
632 if (mask != SMASK_ALL) {
634 if (mask & SMASK_X) printf("x");
635 if (mask & SMASK_Y) printf("y");
636 if (mask & SMASK_Z) printf("z");
637 if (mask & SMASK_W) printf("w");
641 if (shader->SupportsConditional && shader->SupportsConditional(shader) &&
642 shader->GetConditionTest(shader)) {
643 shader->GetCondRegSwizzle(shader, swz);
645 printf(" (%s%d.%s%s%s%s)",
646 NVS_COND_STRING(shader->GetCondition(shader)),
647 shader->GetCondRegID(shader),
648 SWZ_STRING(swz[NVS_SWZ_X]),
649 SWZ_STRING(swz[NVS_SWZ_Y]),
650 SWZ_STRING(swz[NVS_SWZ_Z]),
651 SWZ_STRING(swz[NVS_SWZ_W])
656 if (opi->flags & COUNT_ALL) {
658 if (opi->flags & COUNT_NUM) {
659 printf("%d", shader->GetLoopCount(shader));
661 if (opi->flags & COUNT_IND) {
662 printf(", %d", shader->GetLoopInitial(shader));
664 if (opi->flags & COUNT_INC) {
665 printf(", %d", shader->GetLoopIncrement(shader));
671 if (opi->flags & BRANCH_TR)
672 printf(" %d", shader->GetBranch(shader));
673 if (opi->flags & BRANCH_EL)
674 printf(" ELSE %d", shader->GetBranchElse(shader));
675 if (opi->flags & BRANCH_EN)
676 printf(" END %d", shader->GetBranchEnd(shader));
678 if (!(opi->flags & NODS) && opi->numsrc)
682 for (i = 0; i < opi->numsrc; i++) {
683 if (shader->GetSourceAbs(shader, merged, i))
685 if (shader->GetSourceNegate(shader, merged, i))
688 file = shader->GetSourceFile(shader, merged, i);
691 printf("R%d", shader->GetSourceID(shader, merged, i));
694 if (shader->GetSourceIndexed(shader, merged, i)) {
695 printf("c[A%d.%s + 0x%x]",
696 shader->GetRelAddressRegID(shader),
697 SWZ_STRING(shader->GetRelAddressSwizzle(shader)),
698 shader->GetSourceID(shader, merged, i)
703 if (shader->GetSourceConstVal) {
704 shader->GetSourceConstVal(shader, merged, i, val);
705 printf("{ %.02f, %.02f, %.02f, %.02f }",
706 val[0], val[1], val[2], val[3]);
708 printf("c[0x%x]", shader->GetSourceID(shader, merged, i));
712 case NVS_FILE_ATTRIB:
713 if (shader->GetSourceIndexed(shader, merged, i)) {
714 printf("attrib[A%d.%s + %d]",
715 shader->GetRelAddressRegID(shader),
716 SWZ_STRING(shader->GetRelAddressSwizzle(shader)),
717 shader->GetSourceID(shader, merged, i)
722 SFR_STRING(shader->GetSourceID(shader, merged, i))
726 case NVS_FILE_ADDRESS:
727 printf("A%d", shader->GetRelAddressRegID(shader));
730 printf("UNKNOWN_SRC_FILE");
734 shader->GetSourceSwizzle(shader, merged, i, swz);
735 if (file != NVS_FILE_ADDRESS &&
736 (swz[NVS_SWZ_X] != NVS_SWZ_X || swz[NVS_SWZ_Y] != NVS_SWZ_Y ||
737 swz[NVS_SWZ_Z] != NVS_SWZ_Z || swz[NVS_SWZ_W] != NVS_SWZ_W)) {
738 printf(".%s%s%s%s", SWZ_STRING(swz[NVS_SWZ_X]),
739 SWZ_STRING(swz[NVS_SWZ_Y]),
740 SWZ_STRING(swz[NVS_SWZ_Z]),
741 SWZ_STRING(swz[NVS_SWZ_W]));
744 if (shader->GetSourceAbs(shader, merged, i))
746 if (shader->GetSourceScale) {
747 int scale = shader->GetSourceScale(shader, merged, i);
749 printf("{scaled %dx}", scale);
751 if (i < (opi->numsrc - 1))
755 if (shader->IsLastInst(shader))
760 nvsDisasmHWShader(nvsPtr nvs)
762 nvsFunc *shader = nvs->func;
763 unsigned int iaddr = 0;
766 fprintf(stderr, "No HW program present");
770 shader->inst = nvs->program;
772 if (shader->inst >= (nvs->program + nvs->program_size)) {
773 fprintf(stderr, "Reached end of program, but HW inst has no END");
777 printf("\t0x%08x:\n", shader->inst[0]);
778 printf("\t0x%08x:\n", shader->inst[1]);
779 printf("\t0x%08x:\n", shader->inst[2]);
780 printf("\t0x%08x:", shader->inst[3]);
782 printf("\n\t\tINST %d.0: ", iaddr);
783 nvsDisasmHWShaderOp(shader, 0);
784 if (shader->HasMergedInst(shader)) {
785 printf("\n\t\tINST %d.1: ", iaddr);
786 nvsDisasmHWShaderOp(shader, 1);
790 if (shader->IsLastInst(shader))
793 shader->inst += shader->GetOffsetNext(shader);