r300: Remove all Mesa dependencies from the shader compiler
[mesa.git] / src / mesa / drivers / dri / r300 / compiler / radeon_program.c
1 /*
2 * Copyright (C) 2008 Nicolai Haehnle.
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 "radeon_program.h"
29
30 #include <stdio.h>
31
32 #include "radeon_compiler.h"
33
34
35 /**
36 * Transform the given clause in the following way:
37 * 1. Replace it with an empty clause
38 * 2. For every instruction in the original clause, try the given
39 * transformations in order.
40 * 3. If one of the transformations returns GL_TRUE, assume that it
41 * has emitted the appropriate instruction(s) into the new clause;
42 * otherwise, copy the instruction verbatim.
43 *
44 * \note The transformation is currently not recursive; in other words,
45 * instructions emitted by transformations are not transformed.
46 *
47 * \note The transform is called 'local' because it can only look at
48 * one instruction at a time.
49 */
50 void radeonLocalTransform(
51 struct radeon_compiler * c,
52 int num_transformations,
53 struct radeon_program_transformation* transformations)
54 {
55 struct rc_instruction * inst = c->Program.Instructions.Next;
56
57 while(inst != &c->Program.Instructions) {
58 struct rc_instruction * current = inst;
59 int i;
60
61 inst = inst->Next;
62
63 for(i = 0; i < num_transformations; ++i) {
64 struct radeon_program_transformation* t = transformations + i;
65
66 if (t->function(c, current, t->userData))
67 break;
68 }
69 }
70 }
71
72 /**
73 * Left multiplication of a register with a swizzle
74 */
75 struct rc_src_register lmul_swizzle(unsigned int swizzle, struct rc_src_register srcreg)
76 {
77 struct rc_src_register tmp = srcreg;
78 int i;
79 tmp.Swizzle = 0;
80 tmp.Negate = 0;
81 for(i = 0; i < 4; ++i) {
82 rc_swizzle swz = GET_SWZ(swizzle, i);
83 if (swz < 4) {
84 tmp.Swizzle |= GET_SWZ(srcreg.Swizzle, swz) << (i*3);
85 tmp.Negate |= GET_BIT(srcreg.Negate, swz) << i;
86 } else {
87 tmp.Swizzle |= swz << (i*3);
88 }
89 }
90 return tmp;
91 }
92
93 unsigned int rc_find_free_temporary(struct radeon_compiler * c)
94 {
95 char used[RC_REGISTER_MAX_INDEX];
96 unsigned int i;
97
98 memset(used, 0, sizeof(used));
99
100 for (struct rc_instruction * rcinst = c->Program.Instructions.Next; rcinst != &c->Program.Instructions; rcinst = rcinst->Next) {
101 const struct rc_sub_instruction *inst = &rcinst->I;
102 const struct rc_opcode_info *opcode = rc_get_opcode_info(inst->Opcode);
103 unsigned int k;
104
105 for (k = 0; k < opcode->NumSrcRegs; k++) {
106 if (inst->SrcReg[k].File == RC_FILE_TEMPORARY)
107 used[inst->SrcReg[k].Index] = 1;
108 }
109
110 if (opcode->HasDstReg) {
111 if (inst->DstReg.File == RC_FILE_TEMPORARY)
112 used[inst->DstReg.Index] = 1;
113 }
114 }
115
116 for (i = 0; i < RC_REGISTER_MAX_INDEX; i++) {
117 if (!used[i])
118 return i;
119 }
120
121 rc_error(c, "Ran out of temporary registers\n");
122 return 0;
123 }
124
125
126 struct rc_instruction *rc_alloc_instruction(struct radeon_compiler * c)
127 {
128 struct rc_instruction * inst = memory_pool_malloc(&c->Pool, sizeof(struct rc_instruction));
129
130 memset(inst, 0, sizeof(struct rc_instruction));
131
132 inst->I.Opcode = RC_OPCODE_ILLEGAL_OPCODE;
133 inst->I.DstReg.WriteMask = RC_MASK_XYZW;
134 inst->I.SrcReg[0].Swizzle = RC_SWIZZLE_XYZW;
135 inst->I.SrcReg[1].Swizzle = RC_SWIZZLE_XYZW;
136 inst->I.SrcReg[2].Swizzle = RC_SWIZZLE_XYZW;
137
138 return inst;
139 }
140
141
142 struct rc_instruction *rc_insert_new_instruction(struct radeon_compiler * c, struct rc_instruction * after)
143 {
144 struct rc_instruction * inst = rc_alloc_instruction(c);
145
146 inst->Prev = after;
147 inst->Next = after->Next;
148
149 inst->Prev->Next = inst;
150 inst->Next->Prev = inst;
151
152 return inst;
153 }
154
155 void rc_remove_instruction(struct rc_instruction * inst)
156 {
157 inst->Prev->Next = inst->Next;
158 inst->Next->Prev = inst->Prev;
159 }
160
161 static const char * textarget_to_string(rc_texture_target target)
162 {
163 switch(target) {
164 case RC_TEXTURE_2D_ARRAY: return "2D_ARRAY";
165 case RC_TEXTURE_1D_ARRAY: return "1D_ARRAY";
166 case RC_TEXTURE_CUBE: return "CUBE";
167 case RC_TEXTURE_3D: return "3D";
168 case RC_TEXTURE_RECT: return "RECT";
169 case RC_TEXTURE_2D: return "2D";
170 case RC_TEXTURE_1D: return "1D";
171 default: return "BAD_TEXTURE_TARGET";
172 }
173 }
174
175 static void rc_print_register(FILE * f, rc_register_file file, int index, unsigned int reladdr)
176 {
177 if (file == RC_FILE_NONE) {
178 fprintf(f, "none");
179 } else {
180 const char * filename;
181 switch(file) {
182 case RC_FILE_TEMPORARY: filename = "temp"; break;
183 case RC_FILE_INPUT: filename = "input"; break;
184 case RC_FILE_OUTPUT: filename = "output"; break;
185 case RC_FILE_ADDRESS: filename = "addr"; break;
186 case RC_FILE_CONSTANT: filename = "const"; break;
187 default: filename = "BAD FILE"; break;
188 }
189 fprintf(f, "%s[%i%s]", filename, index, reladdr ? " + addr[0]" : "");
190 }
191 }
192
193 static void rc_print_mask(FILE * f, unsigned int mask)
194 {
195 if (mask & RC_MASK_X) fprintf(f, "x");
196 if (mask & RC_MASK_Y) fprintf(f, "y");
197 if (mask & RC_MASK_Z) fprintf(f, "z");
198 if (mask & RC_MASK_W) fprintf(f, "w");
199 }
200
201 static void rc_print_dst_register(FILE * f, struct rc_dst_register dst)
202 {
203 rc_print_register(f, dst.File, dst.Index, dst.RelAddr);
204 if (dst.WriteMask != RC_MASK_XYZW) {
205 fprintf(f, ".");
206 rc_print_mask(f, dst.WriteMask);
207 }
208 }
209
210 static void rc_print_swizzle(FILE * f, unsigned int swizzle, unsigned int negate)
211 {
212 unsigned int comp;
213 for(comp = 0; comp < 4; ++comp) {
214 rc_swizzle swz = GET_SWZ(swizzle, comp);
215 if (GET_BIT(negate, comp))
216 fprintf(f, "-");
217 switch(swz) {
218 case RC_SWIZZLE_X: fprintf(f, "x"); break;
219 case RC_SWIZZLE_Y: fprintf(f, "y"); break;
220 case RC_SWIZZLE_Z: fprintf(f, "z"); break;
221 case RC_SWIZZLE_W: fprintf(f, "w"); break;
222 case RC_SWIZZLE_ZERO: fprintf(f, "0"); break;
223 case RC_SWIZZLE_ONE: fprintf(f, "1"); break;
224 case RC_SWIZZLE_HALF: fprintf(f, "H"); break;
225 case RC_SWIZZLE_UNUSED: fprintf(f, "_"); break;
226 }
227 }
228 }
229
230 static void rc_print_src_register(FILE * f, struct rc_src_register src)
231 {
232 int trivial_negate = (src.Negate == RC_MASK_NONE || src.Negate == RC_MASK_XYZW);
233
234 if (src.Negate == RC_MASK_XYZW)
235 fprintf(f, "-");
236 if (src.Abs)
237 fprintf(f, "|");
238
239 rc_print_register(f, src.File, src.Index, src.RelAddr);
240
241 if (src.Abs && !trivial_negate)
242 fprintf(f, "|");
243
244 if (src.Swizzle != RC_SWIZZLE_XYZW || !trivial_negate) {
245 fprintf(f, ".");
246 rc_print_swizzle(f, src.Swizzle, trivial_negate ? 0 : src.Negate);
247 }
248
249 if (src.Abs && trivial_negate)
250 fprintf(f, "|");
251 }
252
253 static void rc_print_instruction(FILE * f, struct rc_instruction * inst)
254 {
255 const struct rc_opcode_info * opcode = rc_get_opcode_info(inst->I.Opcode);
256 unsigned int reg;
257
258 fprintf(f, "%s", opcode->Name);
259
260 switch(inst->I.SaturateMode) {
261 case RC_SATURATE_NONE: break;
262 case RC_SATURATE_ZERO_ONE: fprintf(f, "_SAT"); break;
263 case RC_SATURATE_MINUS_PLUS_ONE: fprintf(f, "_SAT2"); break;
264 default: fprintf(f, "_BAD_SAT"); break;
265 }
266
267 if (opcode->HasDstReg) {
268 fprintf(f, " ");
269 rc_print_dst_register(f, inst->I.DstReg);
270 if (opcode->NumSrcRegs)
271 fprintf(f, ",");
272 }
273
274 for(reg = 0; reg < opcode->NumSrcRegs; ++reg) {
275 if (reg > 0)
276 fprintf(f, ",");
277 fprintf(f, " ");
278 rc_print_src_register(f, inst->I.SrcReg[reg]);
279 }
280
281 if (opcode->HasTexture) {
282 fprintf(f, ", %s%s[%u]",
283 textarget_to_string(inst->I.TexSrcTarget),
284 inst->I.TexShadow ? "SHADOW" : "",
285 inst->I.TexSrcUnit);
286 }
287
288 fprintf(f, ";\n");
289 }
290
291 /**
292 * Print program to stderr, default options.
293 */
294 void rc_print_program(const struct rc_program *prog)
295 {
296 unsigned int linenum = 0;
297 struct rc_instruction *inst;
298
299 fprintf(stderr, "# Radeon Compiler Program\n");
300
301 for(inst = prog->Instructions.Next; inst != &prog->Instructions; inst = inst->Next) {
302 fprintf(stderr, "%3d: ", linenum);
303
304 rc_print_instruction(stderr, inst);
305
306 linenum++;
307 }
308 }