Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 1 | /* |
2 | * Copyright 2009 Nicolai Hähnle |
||
3 | * |
||
4 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
5 | * copy of this software and associated documentation files (the "Software"), |
||
6 | * to deal in the Software without restriction, including without limitation |
||
7 | * on the rights to use, copy, modify, merge, publish, distribute, sub |
||
8 | * license, and/or sell copies of the Software, and to permit persons to whom |
||
9 | * the Software is furnished to do so, subject to the following conditions: |
||
10 | * |
||
11 | * The above copyright notice and this permission notice (including the next |
||
12 | * paragraph) shall be included in all copies or substantial portions of the |
||
13 | * Software. |
||
14 | * |
||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
||
18 | * THE COPYRIGHT HOLDER(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
||
19 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
||
20 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
||
21 | * USE OR OTHER DEALINGS IN THE SOFTWARE. */ |
||
22 | |||
23 | #include |
||
24 | #include "r300_tgsi_to_rc.h" |
||
25 | |||
26 | #include "compiler/radeon_compiler.h" |
||
27 | |||
28 | #include "tgsi/tgsi_info.h" |
||
29 | #include "tgsi/tgsi_parse.h" |
||
30 | #include "tgsi/tgsi_scan.h" |
||
31 | #include "tgsi/tgsi_util.h" |
||
32 | |||
33 | static unsigned translate_opcode(unsigned opcode) |
||
34 | { |
||
35 | switch(opcode) { |
||
36 | case TGSI_OPCODE_ARL: return RC_OPCODE_ARL; |
||
37 | case TGSI_OPCODE_MOV: return RC_OPCODE_MOV; |
||
38 | case TGSI_OPCODE_LIT: return RC_OPCODE_LIT; |
||
39 | case TGSI_OPCODE_RCP: return RC_OPCODE_RCP; |
||
40 | case TGSI_OPCODE_RSQ: return RC_OPCODE_RSQ; |
||
41 | case TGSI_OPCODE_EXP: return RC_OPCODE_EXP; |
||
42 | case TGSI_OPCODE_LOG: return RC_OPCODE_LOG; |
||
43 | case TGSI_OPCODE_MUL: return RC_OPCODE_MUL; |
||
44 | case TGSI_OPCODE_ADD: return RC_OPCODE_ADD; |
||
45 | case TGSI_OPCODE_DP3: return RC_OPCODE_DP3; |
||
46 | case TGSI_OPCODE_DP4: return RC_OPCODE_DP4; |
||
47 | case TGSI_OPCODE_DST: return RC_OPCODE_DST; |
||
48 | case TGSI_OPCODE_MIN: return RC_OPCODE_MIN; |
||
49 | case TGSI_OPCODE_MAX: return RC_OPCODE_MAX; |
||
50 | case TGSI_OPCODE_SLT: return RC_OPCODE_SLT; |
||
51 | case TGSI_OPCODE_SGE: return RC_OPCODE_SGE; |
||
52 | case TGSI_OPCODE_MAD: return RC_OPCODE_MAD; |
||
53 | case TGSI_OPCODE_SUB: return RC_OPCODE_SUB; |
||
54 | case TGSI_OPCODE_LRP: return RC_OPCODE_LRP; |
||
55 | /* case TGSI_OPCODE_DP2A: return RC_OPCODE_DP2A; */ |
||
56 | case TGSI_OPCODE_FRC: return RC_OPCODE_FRC; |
||
57 | case TGSI_OPCODE_CLAMP: return RC_OPCODE_CLAMP; |
||
58 | case TGSI_OPCODE_FLR: return RC_OPCODE_FLR; |
||
59 | case TGSI_OPCODE_ROUND: return RC_OPCODE_ROUND; |
||
60 | case TGSI_OPCODE_EX2: return RC_OPCODE_EX2; |
||
61 | case TGSI_OPCODE_LG2: return RC_OPCODE_LG2; |
||
62 | case TGSI_OPCODE_POW: return RC_OPCODE_POW; |
||
63 | case TGSI_OPCODE_XPD: return RC_OPCODE_XPD; |
||
64 | case TGSI_OPCODE_ABS: return RC_OPCODE_ABS; |
||
65 | case TGSI_OPCODE_DPH: return RC_OPCODE_DPH; |
||
66 | case TGSI_OPCODE_COS: return RC_OPCODE_COS; |
||
67 | case TGSI_OPCODE_DDX: return RC_OPCODE_DDX; |
||
68 | case TGSI_OPCODE_DDY: return RC_OPCODE_DDY; |
||
69 | case TGSI_OPCODE_KILL: return RC_OPCODE_KILP; |
||
70 | /* case TGSI_OPCODE_PK2H: return RC_OPCODE_PK2H; */ |
||
71 | /* case TGSI_OPCODE_PK2US: return RC_OPCODE_PK2US; */ |
||
72 | /* case TGSI_OPCODE_PK4B: return RC_OPCODE_PK4B; */ |
||
73 | /* case TGSI_OPCODE_PK4UB: return RC_OPCODE_PK4UB; */ |
||
74 | case TGSI_OPCODE_SEQ: return RC_OPCODE_SEQ; |
||
75 | case TGSI_OPCODE_SGT: return RC_OPCODE_SGT; |
||
76 | case TGSI_OPCODE_SIN: return RC_OPCODE_SIN; |
||
77 | case TGSI_OPCODE_SLE: return RC_OPCODE_SLE; |
||
78 | case TGSI_OPCODE_SNE: return RC_OPCODE_SNE; |
||
79 | case TGSI_OPCODE_TEX: return RC_OPCODE_TEX; |
||
80 | case TGSI_OPCODE_TXD: return RC_OPCODE_TXD; |
||
81 | case TGSI_OPCODE_TXP: return RC_OPCODE_TXP; |
||
82 | /* case TGSI_OPCODE_UP2H: return RC_OPCODE_UP2H; */ |
||
83 | /* case TGSI_OPCODE_UP2US: return RC_OPCODE_UP2US; */ |
||
84 | /* case TGSI_OPCODE_UP4B: return RC_OPCODE_UP4B; */ |
||
85 | /* case TGSI_OPCODE_UP4UB: return RC_OPCODE_UP4UB; */ |
||
86 | case TGSI_OPCODE_ARR: return RC_OPCODE_ARR; |
||
87 | /* case TGSI_OPCODE_CAL: return RC_OPCODE_CAL; */ |
||
88 | /* case TGSI_OPCODE_RET: return RC_OPCODE_RET; */ |
||
89 | case TGSI_OPCODE_SSG: return RC_OPCODE_SSG; |
||
90 | case TGSI_OPCODE_CMP: return RC_OPCODE_CMP; |
||
91 | case TGSI_OPCODE_SCS: return RC_OPCODE_SCS; |
||
92 | case TGSI_OPCODE_TXB: return RC_OPCODE_TXB; |
||
93 | /* case TGSI_OPCODE_DIV: return RC_OPCODE_DIV; */ |
||
94 | case TGSI_OPCODE_DP2: return RC_OPCODE_DP2; |
||
95 | case TGSI_OPCODE_TXL: return RC_OPCODE_TXL; |
||
96 | case TGSI_OPCODE_BRK: return RC_OPCODE_BRK; |
||
97 | case TGSI_OPCODE_IF: return RC_OPCODE_IF; |
||
98 | case TGSI_OPCODE_BGNLOOP: return RC_OPCODE_BGNLOOP; |
||
99 | case TGSI_OPCODE_ELSE: return RC_OPCODE_ELSE; |
||
100 | case TGSI_OPCODE_ENDIF: return RC_OPCODE_ENDIF; |
||
101 | case TGSI_OPCODE_ENDLOOP: return RC_OPCODE_ENDLOOP; |
||
102 | /* case TGSI_OPCODE_PUSHA: return RC_OPCODE_PUSHA; */ |
||
103 | /* case TGSI_OPCODE_POPA: return RC_OPCODE_POPA; */ |
||
104 | case TGSI_OPCODE_CEIL: return RC_OPCODE_CEIL; |
||
105 | /* case TGSI_OPCODE_I2F: return RC_OPCODE_I2F; */ |
||
106 | /* case TGSI_OPCODE_NOT: return RC_OPCODE_NOT; */ |
||
107 | case TGSI_OPCODE_TRUNC: return RC_OPCODE_TRUNC; |
||
108 | /* case TGSI_OPCODE_SHL: return RC_OPCODE_SHL; */ |
||
109 | /* case TGSI_OPCODE_ISHR: return RC_OPCODE_SHR; */ |
||
110 | /* case TGSI_OPCODE_AND: return RC_OPCODE_AND; */ |
||
111 | /* case TGSI_OPCODE_OR: return RC_OPCODE_OR; */ |
||
112 | /* case TGSI_OPCODE_MOD: return RC_OPCODE_MOD; */ |
||
113 | /* case TGSI_OPCODE_XOR: return RC_OPCODE_XOR; */ |
||
114 | /* case TGSI_OPCODE_SAD: return RC_OPCODE_SAD; */ |
||
115 | /* case TGSI_OPCODE_TXF: return RC_OPCODE_TXF; */ |
||
116 | /* case TGSI_OPCODE_TXQ: return RC_OPCODE_TXQ; */ |
||
117 | case TGSI_OPCODE_CONT: return RC_OPCODE_CONT; |
||
118 | /* case TGSI_OPCODE_EMIT: return RC_OPCODE_EMIT; */ |
||
119 | /* case TGSI_OPCODE_ENDPRIM: return RC_OPCODE_ENDPRIM; */ |
||
120 | /* case TGSI_OPCODE_BGNLOOP2: return RC_OPCODE_BGNLOOP2; */ |
||
121 | /* case TGSI_OPCODE_BGNSUB: return RC_OPCODE_BGNSUB; */ |
||
122 | /* case TGSI_OPCODE_ENDLOOP2: return RC_OPCODE_ENDLOOP2; */ |
||
123 | /* case TGSI_OPCODE_ENDSUB: return RC_OPCODE_ENDSUB; */ |
||
124 | case TGSI_OPCODE_NOP: return RC_OPCODE_NOP; |
||
125 | /* case TGSI_OPCODE_CALLNZ: return RC_OPCODE_CALLNZ; */ |
||
126 | /* case TGSI_OPCODE_BREAKC: return RC_OPCODE_BREAKC; */ |
||
127 | case TGSI_OPCODE_KILL_IF: return RC_OPCODE_KIL; |
||
128 | } |
||
129 | |||
130 | fprintf(stderr, "r300: Unknown TGSI/RC opcode: %s\n", tgsi_get_opcode_name(opcode)); |
||
131 | return RC_OPCODE_ILLEGAL_OPCODE; |
||
132 | } |
||
133 | |||
134 | static unsigned translate_saturate(unsigned saturate) |
||
135 | { |
||
136 | switch(saturate) { |
||
137 | default: |
||
138 | fprintf(stderr, "Unknown saturate mode: %i\n", saturate); |
||
139 | /* fall-through */ |
||
140 | case TGSI_SAT_NONE: return RC_SATURATE_NONE; |
||
141 | case TGSI_SAT_ZERO_ONE: return RC_SATURATE_ZERO_ONE; |
||
142 | } |
||
143 | } |
||
144 | |||
145 | static unsigned translate_register_file(unsigned file) |
||
146 | { |
||
147 | switch(file) { |
||
148 | case TGSI_FILE_CONSTANT: return RC_FILE_CONSTANT; |
||
149 | case TGSI_FILE_IMMEDIATE: return RC_FILE_CONSTANT; |
||
150 | case TGSI_FILE_INPUT: return RC_FILE_INPUT; |
||
151 | case TGSI_FILE_OUTPUT: return RC_FILE_OUTPUT; |
||
152 | default: |
||
153 | fprintf(stderr, "Unhandled register file: %i\n", file); |
||
154 | /* fall-through */ |
||
155 | case TGSI_FILE_TEMPORARY: return RC_FILE_TEMPORARY; |
||
156 | case TGSI_FILE_ADDRESS: return RC_FILE_ADDRESS; |
||
157 | } |
||
158 | } |
||
159 | |||
160 | static int translate_register_index( |
||
161 | struct tgsi_to_rc * ttr, |
||
162 | unsigned file, |
||
163 | int index) |
||
164 | { |
||
165 | if (file == TGSI_FILE_IMMEDIATE) |
||
166 | return ttr->immediate_offset + index; |
||
167 | |||
168 | return index; |
||
169 | } |
||
170 | |||
171 | static void transform_dstreg( |
||
172 | struct tgsi_to_rc * ttr, |
||
173 | struct rc_dst_register * dst, |
||
174 | struct tgsi_full_dst_register * src) |
||
175 | { |
||
176 | dst->File = translate_register_file(src->Register.File); |
||
177 | dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index); |
||
178 | dst->WriteMask = src->Register.WriteMask; |
||
179 | |||
180 | if (src->Register.Indirect) { |
||
181 | ttr->error = TRUE; |
||
182 | fprintf(stderr, "r300: Relative addressing of destination operands " |
||
183 | "is unsupported.\n"); |
||
184 | } |
||
185 | } |
||
186 | |||
187 | static void transform_srcreg( |
||
188 | struct tgsi_to_rc * ttr, |
||
189 | struct rc_src_register * dst, |
||
190 | struct tgsi_full_src_register * src) |
||
191 | { |
||
192 | unsigned i, j; |
||
193 | |||
194 | dst->File = translate_register_file(src->Register.File); |
||
195 | dst->Index = translate_register_index(ttr, src->Register.File, src->Register.Index); |
||
196 | dst->RelAddr = src->Register.Indirect; |
||
197 | dst->Swizzle = tgsi_util_get_full_src_register_swizzle(src, 0); |
||
198 | dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 1) << 3; |
||
199 | dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 2) << 6; |
||
200 | dst->Swizzle |= tgsi_util_get_full_src_register_swizzle(src, 3) << 9; |
||
201 | dst->Abs = src->Register.Absolute; |
||
202 | dst->Negate = src->Register.Negate ? RC_MASK_XYZW : 0; |
||
203 | |||
204 | if (src->Register.File == TGSI_FILE_IMMEDIATE) { |
||
205 | for (i = 0; i < ttr->imms_to_swizzle_count; i++) { |
||
206 | if (ttr->imms_to_swizzle[i].index == src->Register.Index) { |
||
207 | dst->File = RC_FILE_TEMPORARY; |
||
208 | dst->Index = 0; |
||
209 | dst->Swizzle = 0; |
||
210 | for (j = 0; j < 4; j++) { |
||
211 | dst->Swizzle |= GET_SWZ(ttr->imms_to_swizzle[i].swizzle, |
||
212 | tgsi_util_get_full_src_register_swizzle(src, j)) << (j * 3); |
||
213 | } |
||
214 | break; |
||
215 | } |
||
216 | } |
||
217 | } |
||
218 | } |
||
219 | |||
220 | static void transform_texture(struct rc_instruction * dst, struct tgsi_instruction_texture src, |
||
221 | uint32_t *shadowSamplers) |
||
222 | { |
||
223 | switch(src.Texture) { |
||
224 | case TGSI_TEXTURE_1D: |
||
225 | dst->U.I.TexSrcTarget = RC_TEXTURE_1D; |
||
226 | break; |
||
227 | case TGSI_TEXTURE_2D: |
||
228 | dst->U.I.TexSrcTarget = RC_TEXTURE_2D; |
||
229 | break; |
||
230 | case TGSI_TEXTURE_3D: |
||
231 | dst->U.I.TexSrcTarget = RC_TEXTURE_3D; |
||
232 | break; |
||
233 | case TGSI_TEXTURE_CUBE: |
||
234 | dst->U.I.TexSrcTarget = RC_TEXTURE_CUBE; |
||
235 | break; |
||
236 | case TGSI_TEXTURE_RECT: |
||
237 | dst->U.I.TexSrcTarget = RC_TEXTURE_RECT; |
||
238 | break; |
||
239 | case TGSI_TEXTURE_SHADOW1D: |
||
240 | dst->U.I.TexSrcTarget = RC_TEXTURE_1D; |
||
241 | dst->U.I.TexShadow = 1; |
||
242 | *shadowSamplers |= 1 << dst->U.I.TexSrcUnit; |
||
243 | break; |
||
244 | case TGSI_TEXTURE_SHADOW2D: |
||
245 | dst->U.I.TexSrcTarget = RC_TEXTURE_2D; |
||
246 | dst->U.I.TexShadow = 1; |
||
247 | *shadowSamplers |= 1 << dst->U.I.TexSrcUnit; |
||
248 | break; |
||
249 | case TGSI_TEXTURE_SHADOWRECT: |
||
250 | dst->U.I.TexSrcTarget = RC_TEXTURE_RECT; |
||
251 | dst->U.I.TexShadow = 1; |
||
252 | *shadowSamplers |= 1 << dst->U.I.TexSrcUnit; |
||
253 | break; |
||
254 | } |
||
255 | dst->U.I.TexSwizzle = RC_SWIZZLE_XYZW; |
||
256 | } |
||
257 | |||
258 | static void transform_instruction(struct tgsi_to_rc * ttr, struct tgsi_full_instruction * src) |
||
259 | { |
||
260 | struct rc_instruction * dst; |
||
261 | int i; |
||
262 | |||
263 | dst = rc_insert_new_instruction(ttr->compiler, ttr->compiler->Program.Instructions.Prev); |
||
264 | dst->U.I.Opcode = translate_opcode(src->Instruction.Opcode); |
||
265 | dst->U.I.SaturateMode = translate_saturate(src->Instruction.Saturate); |
||
266 | |||
267 | if (src->Instruction.NumDstRegs) |
||
268 | transform_dstreg(ttr, &dst->U.I.DstReg, &src->Dst[0]); |
||
269 | |||
270 | for(i = 0; i < src->Instruction.NumSrcRegs; ++i) { |
||
271 | if (src->Src[i].Register.File == TGSI_FILE_SAMPLER) |
||
272 | dst->U.I.TexSrcUnit = src->Src[i].Register.Index; |
||
273 | else |
||
274 | transform_srcreg(ttr, &dst->U.I.SrcReg[i], &src->Src[i]); |
||
275 | } |
||
276 | |||
277 | /* Texturing. */ |
||
278 | if (src->Instruction.Texture) |
||
279 | transform_texture(dst, src->Texture, |
||
280 | &ttr->compiler->Program.ShadowSamplers); |
||
281 | } |
||
282 | |||
283 | static void handle_immediate(struct tgsi_to_rc * ttr, |
||
284 | struct tgsi_full_immediate * imm, |
||
285 | unsigned index) |
||
286 | { |
||
287 | struct rc_constant constant; |
||
288 | unsigned swizzle = 0; |
||
289 | boolean can_swizzle = TRUE; |
||
290 | unsigned i; |
||
291 | |||
292 | for (i = 0; i < 4; i++) { |
||
293 | if (imm->u[i].Float == 0.0f) { |
||
294 | swizzle |= RC_SWIZZLE_ZERO << (i * 3); |
||
295 | } else if (imm->u[i].Float == 0.5f && ttr->use_half_swizzles) { |
||
296 | swizzle |= RC_SWIZZLE_HALF << (i * 3); |
||
297 | } else if (imm->u[i].Float == 1.0f) { |
||
298 | swizzle |= RC_SWIZZLE_ONE << (i * 3); |
||
299 | } else { |
||
300 | can_swizzle = FALSE; |
||
301 | break; |
||
302 | } |
||
303 | } |
||
304 | |||
305 | if (can_swizzle) { |
||
306 | ttr->imms_to_swizzle[ttr->imms_to_swizzle_count].index = index; |
||
307 | ttr->imms_to_swizzle[ttr->imms_to_swizzle_count].swizzle = swizzle; |
||
308 | ttr->imms_to_swizzle_count++; |
||
309 | } else { |
||
310 | constant.Type = RC_CONSTANT_IMMEDIATE; |
||
311 | constant.Size = 4; |
||
312 | for(i = 0; i < 4; ++i) |
||
313 | constant.u.Immediate[i] = imm->u[i].Float; |
||
314 | rc_constants_add(&ttr->compiler->Program.Constants, &constant); |
||
315 | } |
||
316 | } |
||
317 | |||
318 | void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, |
||
319 | const struct tgsi_token * tokens) |
||
320 | { |
||
321 | struct tgsi_full_instruction *inst; |
||
322 | struct tgsi_parse_context parser; |
||
323 | unsigned imm_index = 0; |
||
324 | int i; |
||
325 | |||
326 | ttr->error = FALSE; |
||
327 | |||
328 | /* Allocate constants placeholders. |
||
329 | * |
||
330 | * Note: What if declared constants are not contiguous? */ |
||
331 | for(i = 0; i <= ttr->info->file_max[TGSI_FILE_CONSTANT]; ++i) { |
||
332 | struct rc_constant constant; |
||
333 | memset(&constant, 0, sizeof(constant)); |
||
334 | constant.Type = RC_CONSTANT_EXTERNAL; |
||
335 | constant.Size = 4; |
||
336 | constant.u.External = i; |
||
337 | rc_constants_add(&ttr->compiler->Program.Constants, &constant); |
||
338 | } |
||
339 | |||
340 | ttr->immediate_offset = ttr->compiler->Program.Constants.Count; |
||
341 | |||
342 | ttr->imms_to_swizzle = malloc(ttr->info->immediate_count * sizeof(struct swizzled_imms)); |
||
343 | ttr->imms_to_swizzle_count = 0; |
||
344 | |||
345 | tgsi_parse_init(&parser, tokens); |
||
346 | |||
347 | while (!tgsi_parse_end_of_tokens(&parser)) { |
||
348 | tgsi_parse_token(&parser); |
||
349 | |||
350 | switch (parser.FullToken.Token.Type) { |
||
351 | case TGSI_TOKEN_TYPE_DECLARATION: |
||
352 | break; |
||
353 | case TGSI_TOKEN_TYPE_IMMEDIATE: |
||
354 | handle_immediate(ttr, &parser.FullToken.FullImmediate, imm_index); |
||
355 | imm_index++; |
||
356 | break; |
||
357 | case TGSI_TOKEN_TYPE_INSTRUCTION: |
||
358 | inst = &parser.FullToken.FullInstruction; |
||
359 | if (inst->Instruction.Opcode == TGSI_OPCODE_END) { |
||
360 | break; |
||
361 | } |
||
362 | |||
363 | transform_instruction(ttr, inst); |
||
364 | break; |
||
365 | } |
||
366 | } |
||
367 | |||
368 | tgsi_parse_free(&parser); |
||
369 | |||
370 | free(ttr->imms_to_swizzle); |
||
371 | |||
372 | rc_calculate_inputs_outputs(ttr->compiler); |
||
373 | }=>>><>><>><>>>><>><>><>><>>>><>><>><> |