r300compiler: Add MRT number to debugging output.
[mesa.git] / src / mesa / drivers / dri / r300 / compiler / r300_fragprog.c
1 /*
2 * Copyright (C) 2005 Ben Skeggs.
3 *
4 * All Rights Reserved.
5 *
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:
13 *
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.
17 *
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.
25 *
26 */
27
28 #include "r300_fragprog.h"
29
30 #include <stdio.h>
31
32 #include "../r300_reg.h"
33
34 static struct rc_src_register shadow_ambient(struct radeon_compiler * c, int tmu)
35 {
36 struct rc_src_register reg = { 0, };
37
38 reg.File = RC_FILE_CONSTANT;
39 reg.Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_SHADOW_AMBIENT, tmu);
40 reg.Swizzle = RC_SWIZZLE_WWWW;
41 return reg;
42 }
43
44 /**
45 * Transform TEX, TXP, TXB, and KIL instructions in the following way:
46 * - premultiply texture coordinates for RECT
47 * - extract operand swizzles
48 * - introduce a temporary register when write masks are needed
49 */
50 int r300_transform_TEX(
51 struct radeon_compiler * c,
52 struct rc_instruction* inst,
53 void* data)
54 {
55 struct r300_fragment_program_compiler *compiler =
56 (struct r300_fragment_program_compiler*)data;
57
58 if (inst->U.I.Opcode != RC_OPCODE_TEX &&
59 inst->U.I.Opcode != RC_OPCODE_TXB &&
60 inst->U.I.Opcode != RC_OPCODE_TXP &&
61 inst->U.I.Opcode != RC_OPCODE_KIL)
62 return 0;
63
64 /* ARB_shadow & EXT_shadow_funcs */
65 if (inst->U.I.Opcode != RC_OPCODE_KIL &&
66 c->Program.ShadowSamplers & (1 << inst->U.I.TexSrcUnit)) {
67 rc_compare_func comparefunc = compiler->state.unit[inst->U.I.TexSrcUnit].texture_compare_func;
68
69 if (comparefunc == RC_COMPARE_FUNC_NEVER || comparefunc == RC_COMPARE_FUNC_ALWAYS) {
70 inst->U.I.Opcode = RC_OPCODE_MOV;
71
72 if (comparefunc == RC_COMPARE_FUNC_ALWAYS) {
73 inst->U.I.SrcReg[0].File = RC_FILE_NONE;
74 inst->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_1111;
75 } else {
76 inst->U.I.SrcReg[0] = shadow_ambient(c, inst->U.I.TexSrcUnit);
77 }
78
79 return 1;
80 } else {
81 rc_compare_func comparefunc = compiler->state.unit[inst->U.I.TexSrcUnit].texture_compare_func;
82 unsigned int depthmode = compiler->state.unit[inst->U.I.TexSrcUnit].depth_texture_mode;
83 struct rc_instruction * inst_rcp = rc_insert_new_instruction(c, inst);
84 struct rc_instruction * inst_mad = rc_insert_new_instruction(c, inst_rcp);
85 struct rc_instruction * inst_cmp = rc_insert_new_instruction(c, inst_mad);
86 int pass, fail;
87
88 inst_rcp->U.I.Opcode = RC_OPCODE_RCP;
89 inst_rcp->U.I.DstReg.File = RC_FILE_TEMPORARY;
90 inst_rcp->U.I.DstReg.Index = rc_find_free_temporary(c);
91 inst_rcp->U.I.DstReg.WriteMask = RC_MASK_W;
92 inst_rcp->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
93 inst_rcp->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_WWWW;
94
95 inst_cmp->U.I.DstReg = inst->U.I.DstReg;
96 inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
97 inst->U.I.DstReg.Index = rc_find_free_temporary(c);
98 inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
99
100 inst_mad->U.I.Opcode = RC_OPCODE_MAD;
101 inst_mad->U.I.DstReg.File = RC_FILE_TEMPORARY;
102 inst_mad->U.I.DstReg.Index = rc_find_free_temporary(c);
103 inst_mad->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
104 inst_mad->U.I.SrcReg[0].Swizzle = RC_SWIZZLE_ZZZZ;
105 inst_mad->U.I.SrcReg[1].File = RC_FILE_TEMPORARY;
106 inst_mad->U.I.SrcReg[1].Index = inst_rcp->U.I.DstReg.Index;
107 inst_mad->U.I.SrcReg[1].Swizzle = RC_SWIZZLE_WWWW;
108 inst_mad->U.I.SrcReg[2].File = RC_FILE_TEMPORARY;
109 inst_mad->U.I.SrcReg[2].Index = inst->U.I.DstReg.Index;
110 if (depthmode == 0) /* GL_LUMINANCE */
111 inst_mad->U.I.SrcReg[2].Swizzle = RC_MAKE_SWIZZLE(RC_SWIZZLE_X, RC_SWIZZLE_Y, RC_SWIZZLE_Z, RC_SWIZZLE_Z);
112 else if (depthmode == 2) /* GL_ALPHA */
113 inst_mad->U.I.SrcReg[2].Swizzle = RC_SWIZZLE_WWWW;
114
115 /* Recall that SrcReg[0] is tex, SrcReg[2] is r and:
116 * r < tex <=> -tex+r < 0
117 * r >= tex <=> not (-tex+r < 0 */
118 if (comparefunc == RC_COMPARE_FUNC_LESS || comparefunc == RC_COMPARE_FUNC_GEQUAL)
119 inst_mad->U.I.SrcReg[2].Negate = inst_mad->U.I.SrcReg[2].Negate ^ RC_MASK_XYZW;
120 else
121 inst_mad->U.I.SrcReg[0].Negate = inst_mad->U.I.SrcReg[0].Negate ^ RC_MASK_XYZW;
122
123 inst_cmp->U.I.Opcode = RC_OPCODE_CMP;
124 /* DstReg has been filled out above */
125 inst_cmp->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
126 inst_cmp->U.I.SrcReg[0].Index = inst_mad->U.I.DstReg.Index;
127
128 if (comparefunc == RC_COMPARE_FUNC_LESS || comparefunc == RC_COMPARE_FUNC_GREATER) {
129 pass = 1;
130 fail = 2;
131 } else {
132 pass = 2;
133 fail = 1;
134 }
135
136 inst_cmp->U.I.SrcReg[pass].File = RC_FILE_NONE;
137 inst_cmp->U.I.SrcReg[pass].Swizzle = RC_SWIZZLE_1111;
138 inst_cmp->U.I.SrcReg[fail] = shadow_ambient(c, inst->U.I.TexSrcUnit);
139 }
140 }
141
142 /* Hardware uses [0..1]x[0..1] range for rectangle textures
143 * instead of [0..Width]x[0..Height].
144 * Add a scaling instruction.
145 */
146 if (inst->U.I.Opcode != RC_OPCODE_KIL && inst->U.I.TexSrcTarget == RC_TEXTURE_RECT) {
147 struct rc_instruction * inst_mul = rc_insert_new_instruction(c, inst->Prev);
148
149 inst_mul->U.I.Opcode = RC_OPCODE_MUL;
150 inst_mul->U.I.DstReg.File = RC_FILE_TEMPORARY;
151 inst_mul->U.I.DstReg.Index = rc_find_free_temporary(c);
152 inst_mul->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
153 inst_mul->U.I.SrcReg[1].File = RC_FILE_CONSTANT;
154 inst_mul->U.I.SrcReg[1].Index = rc_constants_add_state(&c->Program.Constants, RC_STATE_R300_TEXRECT_FACTOR, inst->U.I.TexSrcUnit);
155
156 reset_srcreg(&inst->U.I.SrcReg[0]);
157 inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
158 inst->U.I.SrcReg[0].Index = inst_mul->U.I.DstReg.Index;
159 }
160
161 /* Cannot write texture to output registers or with masks */
162 if (inst->U.I.Opcode != RC_OPCODE_KIL &&
163 (inst->U.I.DstReg.File != RC_FILE_TEMPORARY || inst->U.I.DstReg.WriteMask != RC_MASK_XYZW)) {
164 struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst);
165
166 inst_mov->U.I.Opcode = RC_OPCODE_MOV;
167 inst_mov->U.I.DstReg = inst->U.I.DstReg;
168 inst_mov->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
169 inst_mov->U.I.SrcReg[0].Index = rc_find_free_temporary(c);
170
171 inst->U.I.DstReg.File = RC_FILE_TEMPORARY;
172 inst->U.I.DstReg.Index = inst_mov->U.I.SrcReg[0].Index;
173 inst->U.I.DstReg.WriteMask = RC_MASK_XYZW;
174 }
175
176
177 /* Cannot read texture coordinate from constants file */
178 if (inst->U.I.SrcReg[0].File != RC_FILE_TEMPORARY && inst->U.I.SrcReg[0].File != RC_FILE_INPUT) {
179 struct rc_instruction * inst_mov = rc_insert_new_instruction(c, inst->Prev);
180
181 inst_mov->U.I.Opcode = RC_OPCODE_MOV;
182 inst_mov->U.I.DstReg.File = RC_FILE_TEMPORARY;
183 inst_mov->U.I.DstReg.Index = rc_find_free_temporary(c);
184 inst_mov->U.I.SrcReg[0] = inst->U.I.SrcReg[0];
185
186 reset_srcreg(&inst->U.I.SrcReg[0]);
187 inst->U.I.SrcReg[0].File = RC_FILE_TEMPORARY;
188 inst->U.I.SrcReg[0].Index = inst_mov->U.I.DstReg.Index;
189 }
190
191 return 1;
192 }
193
194 /* just some random things... */
195 void r300FragmentProgramDump(struct rX00_fragment_program_code *c)
196 {
197 struct r300_fragment_program_code *code = &c->code.r300;
198 int n, i, j;
199 static int pc = 0;
200
201 fprintf(stderr, "pc=%d*************************************\n", pc++);
202
203 fprintf(stderr, "Hardware program\n");
204 fprintf(stderr, "----------------\n");
205
206 for (n = 0; n <= (code->config & 3); n++) {
207 uint32_t code_addr = code->code_addr[3 - (code->config & 3) + n];
208 int alu_offset = (code_addr & R300_ALU_START_MASK) >> R300_ALU_START_SHIFT;
209 int alu_end = (code_addr & R300_ALU_SIZE_MASK) >> R300_ALU_SIZE_SHIFT;
210 int tex_offset = (code_addr & R300_TEX_START_MASK) >> R300_TEX_START_SHIFT;
211 int tex_end = (code_addr & R300_TEX_SIZE_MASK) >> R300_TEX_SIZE_SHIFT;
212
213 fprintf(stderr, "NODE %d: alu_offset: %d, tex_offset: %d, "
214 "alu_end: %d, tex_end: %d (code_addr: %08x)\n", n,
215 alu_offset, tex_offset, alu_end, tex_end, code_addr);
216
217 if (n > 0 || (code->config & R300_PFS_CNTL_FIRST_NODE_HAS_TEX)) {
218 fprintf(stderr, " TEX:\n");
219 for (i = tex_offset;
220 i <= tex_offset + tex_end;
221 ++i) {
222 const char *instr;
223
224 switch ((code->tex.
225 inst[i] >> R300_TEX_INST_SHIFT) &
226 15) {
227 case R300_TEX_OP_LD:
228 instr = "TEX";
229 break;
230 case R300_TEX_OP_KIL:
231 instr = "KIL";
232 break;
233 case R300_TEX_OP_TXP:
234 instr = "TXP";
235 break;
236 case R300_TEX_OP_TXB:
237 instr = "TXB";
238 break;
239 default:
240 instr = "UNKNOWN";
241 }
242
243 fprintf(stderr,
244 " %s t%i, %c%i, texture[%i] (%08x)\n",
245 instr,
246 (code->tex.
247 inst[i] >> R300_DST_ADDR_SHIFT) & 31,
248 't',
249 (code->tex.
250 inst[i] >> R300_SRC_ADDR_SHIFT) & 31,
251 (code->tex.
252 inst[i] & R300_TEX_ID_MASK) >>
253 R300_TEX_ID_SHIFT,
254 code->tex.inst[i]);
255 }
256 }
257
258 for (i = alu_offset;
259 i <= alu_offset + alu_end; ++i) {
260 char srcc[3][10], dstc[20];
261 char srca[3][10], dsta[20];
262 char argc[3][20];
263 char arga[3][20];
264 char flags[5], tmp[10];
265
266 for (j = 0; j < 3; ++j) {
267 int regc = code->alu.inst[i].rgb_addr >> (j * 6);
268 int rega = code->alu.inst[i].alpha_addr >> (j * 6);
269
270 sprintf(srcc[j], "%c%i",
271 (regc & 32) ? 'c' : 't', regc & 31);
272 sprintf(srca[j], "%c%i",
273 (rega & 32) ? 'c' : 't', rega & 31);
274 }
275
276 dstc[0] = 0;
277 sprintf(flags, "%s%s%s",
278 (code->alu.inst[i].
279 rgb_addr & R300_ALU_DSTC_REG_X) ? "x" : "",
280 (code->alu.inst[i].
281 rgb_addr & R300_ALU_DSTC_REG_Y) ? "y" : "",
282 (code->alu.inst[i].
283 rgb_addr & R300_ALU_DSTC_REG_Z) ? "z" : "");
284 if (flags[0] != 0) {
285 sprintf(dstc, "t%i.%s ",
286 (code->alu.inst[i].
287 rgb_addr >> R300_ALU_DSTC_SHIFT) & 31,
288 flags);
289 }
290 sprintf(flags, "%s%s%s",
291 (code->alu.inst[i].
292 rgb_addr & R300_ALU_DSTC_OUTPUT_X) ? "x" : "",
293 (code->alu.inst[i].
294 rgb_addr & R300_ALU_DSTC_OUTPUT_Y) ? "y" : "",
295 (code->alu.inst[i].
296 rgb_addr & R300_ALU_DSTC_OUTPUT_Z) ? "z" : "");
297 if (flags[0] != 0) {
298 sprintf(tmp, "o%i.%s",
299 (code->alu.inst[i].
300 rgb_addr >> 29) & 3,
301 flags);
302 strcat(dstc, tmp);
303 }
304
305 dsta[0] = 0;
306 if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_REG) {
307 sprintf(dsta, "t%i.w ",
308 (code->alu.inst[i].
309 alpha_addr >> R300_ALU_DSTA_SHIFT) & 31);
310 }
311 if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_OUTPUT) {
312 sprintf(tmp, "o%i.w ",
313 (code->alu.inst[i].
314 alpha_addr >> 25) & 3);
315 strcat(dsta, tmp);
316 }
317 if (code->alu.inst[i].alpha_addr & R300_ALU_DSTA_DEPTH) {
318 strcat(dsta, "Z");
319 }
320
321 fprintf(stderr,
322 "%3i: xyz: %3s %3s %3s -> %-20s (%08x)\n"
323 " w: %3s %3s %3s -> %-20s (%08x)\n", i,
324 srcc[0], srcc[1], srcc[2], dstc,
325 code->alu.inst[i].rgb_addr, srca[0], srca[1],
326 srca[2], dsta, code->alu.inst[i].alpha_addr);
327
328 for (j = 0; j < 3; ++j) {
329 int regc = code->alu.inst[i].rgb_inst >> (j * 7);
330 int rega = code->alu.inst[i].alpha_inst >> (j * 7);
331 int d;
332 char buf[20];
333
334 d = regc & 31;
335 if (d < 12) {
336 switch (d % 4) {
337 case R300_ALU_ARGC_SRC0C_XYZ:
338 sprintf(buf, "%s.xyz",
339 srcc[d / 4]);
340 break;
341 case R300_ALU_ARGC_SRC0C_XXX:
342 sprintf(buf, "%s.xxx",
343 srcc[d / 4]);
344 break;
345 case R300_ALU_ARGC_SRC0C_YYY:
346 sprintf(buf, "%s.yyy",
347 srcc[d / 4]);
348 break;
349 case R300_ALU_ARGC_SRC0C_ZZZ:
350 sprintf(buf, "%s.zzz",
351 srcc[d / 4]);
352 break;
353 }
354 } else if (d < 15) {
355 sprintf(buf, "%s.www", srca[d - 12]);
356 } else if (d == 20) {
357 sprintf(buf, "0.0");
358 } else if (d == 21) {
359 sprintf(buf, "1.0");
360 } else if (d == 22) {
361 sprintf(buf, "0.5");
362 } else if (d >= 23 && d < 32) {
363 d -= 23;
364 switch (d / 3) {
365 case 0:
366 sprintf(buf, "%s.yzx",
367 srcc[d % 3]);
368 break;
369 case 1:
370 sprintf(buf, "%s.zxy",
371 srcc[d % 3]);
372 break;
373 case 2:
374 sprintf(buf, "%s.Wzy",
375 srcc[d % 3]);
376 break;
377 }
378 } else {
379 sprintf(buf, "%i", d);
380 }
381
382 sprintf(argc[j], "%s%s%s%s",
383 (regc & 32) ? "-" : "",
384 (regc & 64) ? "|" : "",
385 buf, (regc & 64) ? "|" : "");
386
387 d = rega & 31;
388 if (d < 9) {
389 sprintf(buf, "%s.%c", srcc[d / 3],
390 'x' + (char)(d % 3));
391 } else if (d < 12) {
392 sprintf(buf, "%s.w", srca[d - 9]);
393 } else if (d == 16) {
394 sprintf(buf, "0.0");
395 } else if (d == 17) {
396 sprintf(buf, "1.0");
397 } else if (d == 18) {
398 sprintf(buf, "0.5");
399 } else {
400 sprintf(buf, "%i", d);
401 }
402
403 sprintf(arga[j], "%s%s%s%s",
404 (rega & 32) ? "-" : "",
405 (rega & 64) ? "|" : "",
406 buf, (rega & 64) ? "|" : "");
407 }
408
409 fprintf(stderr, " xyz: %8s %8s %8s op: %08x\n"
410 " w: %8s %8s %8s op: %08x\n",
411 argc[0], argc[1], argc[2],
412 code->alu.inst[i].rgb_inst, arga[0], arga[1],
413 arga[2], code->alu.inst[i].alpha_inst);
414 }
415 }
416 }