2 * Copyright (C) 2005 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.
28 #include "r300_fragprog.h"
30 #include "shader/prog_parameter.h"
32 #include "../r300_reg.h"
34 static struct prog_src_register
shadow_ambient(struct radeon_compiler
* c
, int tmu
)
36 struct prog_src_register reg
= { 0, };
38 reg
.File
= PROGRAM_STATE_VAR
;
39 reg
.Index
= rc_constants_add_state(&c
->Program
.Constants
, RC_STATE_SHADOW_AMBIENT
, tmu
);
40 reg
.Swizzle
= SWIZZLE_WWWW
;
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
50 GLboolean
r300_transform_TEX(
51 struct radeon_compiler
* c
,
52 struct rc_instruction
* inst
,
55 struct r300_fragment_program_compiler
*compiler
=
56 (struct r300_fragment_program_compiler
*)data
;
58 if (inst
->I
.Opcode
!= OPCODE_TEX
&&
59 inst
->I
.Opcode
!= OPCODE_TXB
&&
60 inst
->I
.Opcode
!= OPCODE_TXP
&&
61 inst
->I
.Opcode
!= OPCODE_KIL
)
64 /* ARB_shadow & EXT_shadow_funcs */
65 if (inst
->I
.Opcode
!= OPCODE_KIL
&&
66 c
->Program
.ShadowSamplers
& (1 << inst
->I
.TexSrcUnit
)) {
67 GLuint comparefunc
= GL_NEVER
+ compiler
->state
.unit
[inst
->I
.TexSrcUnit
].texture_compare_func
;
69 if (comparefunc
== GL_NEVER
|| comparefunc
== GL_ALWAYS
) {
70 inst
->I
.Opcode
= OPCODE_MOV
;
72 if (comparefunc
== GL_ALWAYS
) {
73 inst
->I
.SrcReg
[0].File
= PROGRAM_BUILTIN
;
74 inst
->I
.SrcReg
[0].Swizzle
= SWIZZLE_1111
;
76 inst
->I
.SrcReg
[0] = shadow_ambient(c
, inst
->I
.TexSrcUnit
);
81 GLuint comparefunc
= GL_NEVER
+ compiler
->state
.unit
[inst
->I
.TexSrcUnit
].texture_compare_func
;
82 GLuint depthmode
= compiler
->state
.unit
[inst
->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
);
88 inst_rcp
->I
.Opcode
= OPCODE_RCP
;
89 inst_rcp
->I
.DstReg
.File
= PROGRAM_TEMPORARY
;
90 inst_rcp
->I
.DstReg
.Index
= rc_find_free_temporary(c
);
91 inst_rcp
->I
.DstReg
.WriteMask
= WRITEMASK_W
;
92 inst_rcp
->I
.SrcReg
[0] = inst
->I
.SrcReg
[0];
93 inst_rcp
->I
.SrcReg
[0].Swizzle
= SWIZZLE_WWWW
;
95 inst_cmp
->I
.DstReg
= inst
->I
.DstReg
;
96 inst
->I
.DstReg
.File
= PROGRAM_TEMPORARY
;
97 inst
->I
.DstReg
.Index
= rc_find_free_temporary(c
);
98 inst
->I
.DstReg
.WriteMask
= WRITEMASK_XYZW
;
100 inst_mad
->I
.Opcode
= OPCODE_MAD
;
101 inst_mad
->I
.DstReg
.File
= PROGRAM_TEMPORARY
;
102 inst_mad
->I
.DstReg
.Index
= rc_find_free_temporary(c
);
103 inst_mad
->I
.SrcReg
[0] = inst
->I
.SrcReg
[0];
104 inst_mad
->I
.SrcReg
[0].Swizzle
= SWIZZLE_ZZZZ
;
105 inst_mad
->I
.SrcReg
[1].File
= PROGRAM_TEMPORARY
;
106 inst_mad
->I
.SrcReg
[1].Index
= inst_rcp
->I
.DstReg
.Index
;
107 inst_mad
->I
.SrcReg
[1].Swizzle
= SWIZZLE_WWWW
;
108 inst_mad
->I
.SrcReg
[2].File
= PROGRAM_TEMPORARY
;
109 inst_mad
->I
.SrcReg
[2].Index
= inst
->I
.DstReg
.Index
;
110 if (depthmode
== 0) /* GL_LUMINANCE */
111 inst_mad
->I
.SrcReg
[2].Swizzle
= MAKE_SWIZZLE4(SWIZZLE_X
, SWIZZLE_Y
, SWIZZLE_Z
, SWIZZLE_Z
);
112 else if (depthmode
== 2) /* GL_ALPHA */
113 inst_mad
->I
.SrcReg
[2].Swizzle
= SWIZZLE_WWWW
;
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
== GL_LESS
|| comparefunc
== GL_GEQUAL
)
119 inst_mad
->I
.SrcReg
[2].Negate
= inst_mad
->I
.SrcReg
[2].Negate
^ NEGATE_XYZW
;
121 inst_mad
->I
.SrcReg
[0].Negate
= inst_mad
->I
.SrcReg
[0].Negate
^ NEGATE_XYZW
;
123 inst_cmp
->I
.Opcode
= OPCODE_CMP
;
124 /* DstReg has been filled out above */
125 inst_cmp
->I
.SrcReg
[0].File
= PROGRAM_TEMPORARY
;
126 inst_cmp
->I
.SrcReg
[0].Index
= inst_mad
->I
.DstReg
.Index
;
128 if (comparefunc
== GL_LESS
|| comparefunc
== GL_GREATER
) {
136 inst_cmp
->I
.SrcReg
[pass
].File
= PROGRAM_BUILTIN
;
137 inst_cmp
->I
.SrcReg
[pass
].Swizzle
= SWIZZLE_1111
;
138 inst_cmp
->I
.SrcReg
[fail
] = shadow_ambient(c
, inst
->I
.TexSrcUnit
);
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.
146 if (inst
->I
.Opcode
!= OPCODE_KIL
&& inst
->I
.TexSrcTarget
== TEXTURE_RECT_INDEX
) {
147 struct rc_instruction
* inst_mul
= rc_insert_new_instruction(c
, inst
->Prev
);
149 inst_mul
->I
.Opcode
= OPCODE_MUL
;
150 inst_mul
->I
.DstReg
.File
= PROGRAM_TEMPORARY
;
151 inst_mul
->I
.DstReg
.Index
= rc_find_free_temporary(c
);
152 inst_mul
->I
.SrcReg
[0] = inst
->I
.SrcReg
[0];
153 inst_mul
->I
.SrcReg
[1].File
= PROGRAM_STATE_VAR
;
154 inst_mul
->I
.SrcReg
[1].Index
= rc_constants_add_state(&c
->Program
.Constants
, RC_STATE_R300_TEXRECT_FACTOR
, inst
->I
.TexSrcUnit
);
156 reset_srcreg(&inst
->I
.SrcReg
[0]);
157 inst
->I
.SrcReg
[0].File
= PROGRAM_TEMPORARY
;
158 inst
->I
.SrcReg
[0].Index
= inst_mul
->I
.DstReg
.Index
;
161 /* Cannot write texture to output registers or with masks */
162 if (inst
->I
.Opcode
!= OPCODE_KIL
&&
163 (inst
->I
.DstReg
.File
!= PROGRAM_TEMPORARY
|| inst
->I
.DstReg
.WriteMask
!= WRITEMASK_XYZW
)) {
164 struct rc_instruction
* inst_mov
= rc_insert_new_instruction(c
, inst
);
166 inst_mov
->I
.Opcode
= OPCODE_MOV
;
167 inst_mov
->I
.DstReg
= inst
->I
.DstReg
;
168 inst_mov
->I
.SrcReg
[0].File
= PROGRAM_TEMPORARY
;
169 inst_mov
->I
.SrcReg
[0].Index
= rc_find_free_temporary(c
);
171 inst
->I
.DstReg
.File
= PROGRAM_TEMPORARY
;
172 inst
->I
.DstReg
.Index
= inst_mov
->I
.SrcReg
[0].Index
;
173 inst
->I
.DstReg
.WriteMask
= WRITEMASK_XYZW
;
177 /* Cannot read texture coordinate from constants file */
178 if (inst
->I
.SrcReg
[0].File
!= PROGRAM_TEMPORARY
&& inst
->I
.SrcReg
[0].File
!= PROGRAM_INPUT
) {
179 struct rc_instruction
* inst_mov
= rc_insert_new_instruction(c
, inst
->Prev
);
181 inst_mov
->I
.Opcode
= OPCODE_MOV
;
182 inst_mov
->I
.DstReg
.File
= PROGRAM_TEMPORARY
;
183 inst_mov
->I
.DstReg
.Index
= rc_find_free_temporary(c
);
184 inst_mov
->I
.SrcReg
[0] = inst
->I
.SrcReg
[0];
186 reset_srcreg(&inst
->I
.SrcReg
[0]);
187 inst
->I
.SrcReg
[0].File
= PROGRAM_TEMPORARY
;
188 inst
->I
.SrcReg
[0].Index
= inst_mov
->I
.DstReg
.Index
;
194 /* just some random things... */
195 void r300FragmentProgramDump(struct rX00_fragment_program_code
*c
)
197 struct r300_fragment_program_code
*code
= &c
->code
.r300
;
201 fprintf(stderr
, "pc=%d*************************************\n", pc
++);
203 fprintf(stderr
, "Hardware program\n");
204 fprintf(stderr
, "----------------\n");
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
;
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
);
217 if (n
> 0 || (code
->config
& R300_PFS_CNTL_FIRST_NODE_HAS_TEX
)) {
218 fprintf(stderr
, " TEX:\n");
220 i
<= tex_offset
+ tex_end
;
225 inst
[i
] >> R300_TEX_INST_SHIFT
) &
230 case R300_TEX_OP_KIL
:
233 case R300_TEX_OP_TXP
:
236 case R300_TEX_OP_TXB
:
244 " %s t%i, %c%i, texture[%i] (%08x)\n",
247 inst
[i
] >> R300_DST_ADDR_SHIFT
) & 31,
250 inst
[i
] >> R300_SRC_ADDR_SHIFT
) & 31,
252 inst
[i
] & R300_TEX_ID_MASK
) >>
259 i
<= alu_offset
+ alu_end
; ++i
) {
260 char srcc
[3][10], dstc
[20];
261 char srca
[3][10], dsta
[20];
264 char flags
[5], tmp
[10];
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);
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);
277 sprintf(flags
, "%s%s%s",
279 rgb_addr
& R300_ALU_DSTC_REG_X
) ? "x" : "",
281 rgb_addr
& R300_ALU_DSTC_REG_Y
) ? "y" : "",
283 rgb_addr
& R300_ALU_DSTC_REG_Z
) ? "z" : "");
285 sprintf(dstc
, "t%i.%s ",
287 rgb_addr
>> R300_ALU_DSTC_SHIFT
) & 31,
290 sprintf(flags
, "%s%s%s",
292 rgb_addr
& R300_ALU_DSTC_OUTPUT_X
) ? "x" : "",
294 rgb_addr
& R300_ALU_DSTC_OUTPUT_Y
) ? "y" : "",
296 rgb_addr
& R300_ALU_DSTC_OUTPUT_Z
) ? "z" : "");
298 sprintf(tmp
, "o%i.%s",
300 rgb_addr
>> R300_ALU_DSTC_SHIFT
) & 31,
306 if (code
->alu
.inst
[i
].alpha_addr
& R300_ALU_DSTA_REG
) {
307 sprintf(dsta
, "t%i.w ",
309 alpha_addr
>> R300_ALU_DSTA_SHIFT
) & 31);
311 if (code
->alu
.inst
[i
].alpha_addr
& R300_ALU_DSTA_OUTPUT
) {
312 sprintf(tmp
, "o%i.w ",
314 alpha_addr
>> R300_ALU_DSTA_SHIFT
) & 31);
317 if (code
->alu
.inst
[i
].alpha_addr
& R300_ALU_DSTA_DEPTH
) {
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
);
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);
337 case R300_ALU_ARGC_SRC0C_XYZ
:
338 sprintf(buf
, "%s.xyz",
341 case R300_ALU_ARGC_SRC0C_XXX
:
342 sprintf(buf
, "%s.xxx",
345 case R300_ALU_ARGC_SRC0C_YYY
:
346 sprintf(buf
, "%s.yyy",
349 case R300_ALU_ARGC_SRC0C_ZZZ
:
350 sprintf(buf
, "%s.zzz",
355 sprintf(buf
, "%s.www", srca
[d
- 12]);
356 } else if (d
== 20) {
358 } else if (d
== 21) {
360 } else if (d
== 22) {
362 } else if (d
>= 23 && d
< 32) {
366 sprintf(buf
, "%s.yzx",
370 sprintf(buf
, "%s.zxy",
374 sprintf(buf
, "%s.Wzy",
379 sprintf(buf
, "%i", d
);
382 sprintf(argc
[j
], "%s%s%s%s",
383 (regc
& 32) ? "-" : "",
384 (regc
& 64) ? "|" : "",
385 buf
, (regc
& 64) ? "|" : "");
389 sprintf(buf
, "%s.%c", srcc
[d
/ 3],
390 'x' + (char)(d
% 3));
392 sprintf(buf
, "%s.w", srca
[d
- 9]);
393 } else if (d
== 16) {
395 } else if (d
== 17) {
397 } else if (d
== 18) {
400 sprintf(buf
, "%i", d
);
403 sprintf(arga
[j
], "%s%s%s%s",
404 (rega
& 32) ? "-" : "",
405 (rega
& 64) ? "|" : "",
406 buf
, (rega
& 64) ? "|" : "");
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
);