Merge branch 'mesa_7_5_branch'
[mesa.git] / src / gallium / drivers / r300 / r300_vs.c
1 /*
2 * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
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 AUTHOR(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 "r300_vs.h"
24
25 static void r300_vs_declare(struct r300_vs_asm* assembler,
26 struct tgsi_full_declaration* decl)
27 {
28 switch (decl->Declaration.File) {
29 case TGSI_FILE_INPUT:
30 break;
31 case TGSI_FILE_OUTPUT:
32 switch (decl->Semantic.SemanticName) {
33 case TGSI_SEMANTIC_POSITION:
34 assembler->tab[decl->DeclarationRange.First] = 0;
35 break;
36 case TGSI_SEMANTIC_COLOR:
37 assembler->tab[decl->DeclarationRange.First] =
38 (assembler->point_size ? 1 : 0) +
39 assembler->out_colors;
40 break;
41 case TGSI_SEMANTIC_FOG:
42 case TGSI_SEMANTIC_GENERIC:
43 /* XXX multiple? */
44 assembler->tab[decl->DeclarationRange.First] =
45 (assembler->point_size ? 1 : 0) +
46 assembler->out_colors +
47 assembler->out_texcoords;
48 break;
49 case TGSI_SEMANTIC_PSIZE:
50 assembler->tab[decl->DeclarationRange.First] = 1;
51 break;
52 default:
53 debug_printf("r300: vs: Bad semantic declaration %d\n",
54 decl->Semantic.SemanticName);
55 break;
56 }
57 break;
58 case TGSI_FILE_CONSTANT:
59 break;
60 case TGSI_FILE_TEMPORARY:
61 assembler->temp_count++;
62 break;
63 default:
64 debug_printf("r300: vs: Bad file %d\n", decl->Declaration.File);
65 break;
66 }
67 }
68
69 static INLINE unsigned r300_vs_src_type(struct r300_vs_asm* assembler,
70 struct tgsi_src_register* src)
71 {
72 switch (src->File) {
73 case TGSI_FILE_NULL:
74 case TGSI_FILE_INPUT:
75 /* Probably a zero or one swizzle */
76 return R300_PVS_SRC_REG_INPUT;
77 case TGSI_FILE_TEMPORARY:
78 return R300_PVS_SRC_REG_TEMPORARY;
79 case TGSI_FILE_CONSTANT:
80 case TGSI_FILE_IMMEDIATE:
81 return R300_PVS_SRC_REG_CONSTANT;
82 default:
83 debug_printf("r300: vs: Unimplemented src type %d\n", src->File);
84 break;
85 }
86 return 0;
87 }
88
89 static INLINE unsigned r300_vs_src(struct r300_vs_asm* assembler,
90 struct tgsi_src_register* src)
91 {
92 switch (src->File) {
93 case TGSI_FILE_NULL:
94 case TGSI_FILE_INPUT:
95 case TGSI_FILE_TEMPORARY:
96 case TGSI_FILE_CONSTANT:
97 return src->Index;
98 case TGSI_FILE_IMMEDIATE:
99 return src->Index + assembler->imm_offset;
100 default:
101 debug_printf("r300: vs: Unimplemented src type %d\n", src->File);
102 break;
103 }
104 return 0;
105 }
106
107 static INLINE unsigned r300_vs_dst_type(struct r300_vs_asm* assembler,
108 struct tgsi_dst_register* dst)
109 {
110 switch (dst->File) {
111 case TGSI_FILE_TEMPORARY:
112 return R300_PVS_DST_REG_TEMPORARY;
113 case TGSI_FILE_OUTPUT:
114 return R300_PVS_DST_REG_OUT;
115 default:
116 debug_printf("r300: vs: Unimplemented dst type %d\n", dst->File);
117 break;
118 }
119 return 0;
120 }
121
122 static INLINE unsigned r300_vs_dst(struct r300_vs_asm* assembler,
123 struct tgsi_dst_register* dst)
124 {
125 switch (dst->File) {
126 case TGSI_FILE_TEMPORARY:
127 return dst->Index;
128 case TGSI_FILE_OUTPUT:
129 return assembler->tab[dst->Index];
130 default:
131 debug_printf("r300: vs: Unimplemented dst %d\n", dst->File);
132 break;
133 }
134 return 0;
135 }
136
137 static uint32_t r300_vs_op(unsigned op)
138 {
139 switch (op) {
140 case TGSI_OPCODE_DP3:
141 case TGSI_OPCODE_DP4:
142 return R300_VE_DOT_PRODUCT;
143 case TGSI_OPCODE_MUL:
144 return R300_VE_MULTIPLY;
145 case TGSI_OPCODE_ADD:
146 case TGSI_OPCODE_MOV:
147 case TGSI_OPCODE_SUB:
148 case TGSI_OPCODE_SWZ:
149 return R300_VE_ADD;
150 case TGSI_OPCODE_MAX:
151 return R300_VE_MAXIMUM;
152 case TGSI_OPCODE_SLT:
153 return R300_VE_SET_LESS_THAN;
154 case TGSI_OPCODE_RSQ:
155 return R300_PVS_DST_MATH_INST | R300_ME_RECIP_DX;
156 case TGSI_OPCODE_MAD:
157 return R300_PVS_DST_MACRO_INST | R300_PVS_MACRO_OP_2CLK_MADD;
158 default:
159 break;
160 }
161 return 0;
162 }
163
164 static uint32_t r300_vs_swiz(struct tgsi_full_src_register* reg)
165 {
166 if (reg->SrcRegister.Extended) {
167 return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
168 reg->SrcRegisterExtSwz.ExtSwizzleX |
169 (reg->SrcRegisterExtSwz.ExtSwizzleY << 3) |
170 (reg->SrcRegisterExtSwz.ExtSwizzleZ << 6) |
171 (reg->SrcRegisterExtSwz.ExtSwizzleW << 9);
172 } else {
173 return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
174 reg->SrcRegister.SwizzleX |
175 (reg->SrcRegister.SwizzleY << 3) |
176 (reg->SrcRegister.SwizzleZ << 6) |
177 (reg->SrcRegister.SwizzleW << 9);
178 }
179 }
180
181 /* XXX icky icky icky icky */
182 static uint32_t r300_vs_scalar_swiz(struct tgsi_full_src_register* reg)
183 {
184 if (reg->SrcRegister.Extended) {
185 return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
186 reg->SrcRegisterExtSwz.ExtSwizzleX |
187 (reg->SrcRegisterExtSwz.ExtSwizzleX << 3) |
188 (reg->SrcRegisterExtSwz.ExtSwizzleX << 6) |
189 (reg->SrcRegisterExtSwz.ExtSwizzleX << 9);
190 } else {
191 return (reg->SrcRegister.Negate ? (0xf << 12) : 0) |
192 reg->SrcRegister.SwizzleX |
193 (reg->SrcRegister.SwizzleX << 3) |
194 (reg->SrcRegister.SwizzleX << 6) |
195 (reg->SrcRegister.SwizzleX << 9);
196 }
197 }
198
199 /* XXX scalar stupidity */
200 static void r300_vs_emit_inst(struct r300_vertex_shader* vs,
201 struct r300_vs_asm* assembler,
202 struct tgsi_full_src_register* src,
203 struct tgsi_full_dst_register* dst,
204 unsigned op,
205 unsigned count,
206 boolean is_scalar)
207 {
208 int i = vs->instruction_count;
209 vs->instructions[i].inst0 = R300_PVS_DST_OPCODE(r300_vs_op(op)) |
210 R300_PVS_DST_REG_TYPE(r300_vs_dst_type(assembler, &dst->DstRegister)) |
211 R300_PVS_DST_OFFSET(r300_vs_dst(assembler, &dst->DstRegister)) |
212 R300_PVS_DST_WE(dst->DstRegister.WriteMask);
213 switch (count) {
214 case 3:
215 vs->instructions[i].inst3 =
216 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
217 &src[2].SrcRegister)) |
218 R300_PVS_SRC_OFFSET(r300_vs_src(assembler,
219 &src[2].SrcRegister)) |
220 R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[2]));
221 /* Fall through */
222 case 2:
223 vs->instructions[i].inst2 =
224 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
225 &src[1].SrcRegister)) |
226 R300_PVS_SRC_OFFSET(r300_vs_src(assembler,
227 &src[1].SrcRegister)) |
228 R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[1]));
229 /* Fall through */
230 case 1:
231 vs->instructions[i].inst1 =
232 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
233 &src[0].SrcRegister)) |
234 R300_PVS_SRC_OFFSET(r300_vs_src(assembler,
235 &src[0].SrcRegister)) |
236 /* XXX the icky, it burns */
237 R300_PVS_SRC_SWIZZLE(is_scalar ? r300_vs_scalar_swiz(&src[0])
238 : r300_vs_swiz(&src[0]));
239 break;
240 }
241 vs->instruction_count++;
242 }
243
244 static void r300_vs_instruction(struct r300_vertex_shader* vs,
245 struct r300_vs_asm* assembler,
246 struct tgsi_full_instruction* inst)
247 {
248 switch (inst->Instruction.Opcode) {
249 case TGSI_OPCODE_RSQ:
250 r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
251 &inst->FullDstRegisters[0], inst->Instruction.Opcode,
252 1, TRUE);
253 break;
254 case TGSI_OPCODE_SUB:
255 inst->FullSrcRegisters[1].SrcRegister.Negate =
256 !inst->FullSrcRegisters[1].SrcRegister.Negate;
257 /* Fall through */
258 case TGSI_OPCODE_ADD:
259 case TGSI_OPCODE_MUL:
260 case TGSI_OPCODE_MAX:
261 case TGSI_OPCODE_SLT:
262 r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
263 &inst->FullDstRegisters[0], inst->Instruction.Opcode,
264 2, FALSE);
265 break;
266 case TGSI_OPCODE_DP3:
267 /* Set alpha swizzle to zero for src0 and src1 */
268 if (!inst->FullSrcRegisters[0].SrcRegister.Extended) {
269 inst->FullSrcRegisters[0].SrcRegister.Extended = TRUE;
270 inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleX =
271 inst->FullSrcRegisters[0].SrcRegister.SwizzleX;
272 inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleY =
273 inst->FullSrcRegisters[0].SrcRegister.SwizzleY;
274 inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleZ =
275 inst->FullSrcRegisters[0].SrcRegister.SwizzleZ;
276 }
277 inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtSwizzleW =
278 TGSI_EXTSWIZZLE_ZERO;
279 if (!inst->FullSrcRegisters[1].SrcRegister.Extended) {
280 inst->FullSrcRegisters[1].SrcRegister.Extended = TRUE;
281 inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleX =
282 inst->FullSrcRegisters[1].SrcRegister.SwizzleX;
283 inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleY =
284 inst->FullSrcRegisters[1].SrcRegister.SwizzleY;
285 inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleZ =
286 inst->FullSrcRegisters[1].SrcRegister.SwizzleZ;
287 }
288 inst->FullSrcRegisters[1].SrcRegisterExtSwz.ExtSwizzleW =
289 TGSI_EXTSWIZZLE_ZERO;
290 /* Fall through */
291 case TGSI_OPCODE_DP4:
292 r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
293 &inst->FullDstRegisters[0], inst->Instruction.Opcode,
294 2, FALSE);
295 break;
296 case TGSI_OPCODE_MOV:
297 case TGSI_OPCODE_SWZ:
298 inst->FullSrcRegisters[1] = r300_constant_zero;
299 r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
300 &inst->FullDstRegisters[0], inst->Instruction.Opcode,
301 2, FALSE);
302 break;
303 case TGSI_OPCODE_MAD:
304 r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
305 &inst->FullDstRegisters[0], inst->Instruction.Opcode,
306 3, FALSE);
307 break;
308 case TGSI_OPCODE_END:
309 break;
310 default:
311 debug_printf("r300: vs: Bad opcode %d\n",
312 inst->Instruction.Opcode);
313 break;
314 }
315 }
316
317 static void r300_vs_init(struct r300_vertex_shader* vs,
318 struct r300_vs_asm* assembler)
319 {
320 struct tgsi_shader_info* info = &vs->info;
321 int i;
322
323 for (i = 0; i < info->num_outputs; i++) {
324 switch (info->output_semantic_name[i]) {
325 case TGSI_SEMANTIC_PSIZE:
326 assembler->point_size = TRUE;
327 break;
328 case TGSI_SEMANTIC_COLOR:
329 assembler->out_colors++;
330 break;
331 case TGSI_SEMANTIC_FOG:
332 case TGSI_SEMANTIC_GENERIC:
333 assembler->out_texcoords++;
334 break;
335 }
336 }
337
338 vs->instruction_count = 0;
339 }
340
341 void r300_translate_vertex_shader(struct r300_context* r300,
342 struct r300_vertex_shader* vs)
343 {
344 struct tgsi_parse_context parser;
345 int i;
346 struct r300_constant_buffer* consts =
347 &r300->shader_constants[PIPE_SHADER_VERTEX];
348
349 struct r300_vs_asm* assembler = CALLOC_STRUCT(r300_vs_asm);
350 if (assembler == NULL) {
351 return;
352 }
353
354 /* Init assembler. */
355 r300_vs_init(vs, assembler);
356
357 /* Setup starting offset for immediates. */
358 assembler->imm_offset = consts->user_count;
359
360 tgsi_parse_init(&parser, vs->state.tokens);
361
362 while (!tgsi_parse_end_of_tokens(&parser)) {
363 tgsi_parse_token(&parser);
364
365 /* This is seriously the lamest way to create fragment programs ever.
366 * I blame TGSI. */
367 switch (parser.FullToken.Token.Type) {
368 case TGSI_TOKEN_TYPE_DECLARATION:
369 /* Allocated registers sitting at the beginning
370 * of the program. */
371 r300_vs_declare(assembler, &parser.FullToken.FullDeclaration);
372 break;
373 case TGSI_TOKEN_TYPE_IMMEDIATE:
374 debug_printf("r300: Emitting immediate to constant buffer, "
375 "position %d\n",
376 assembler->imm_offset + assembler->imm_count);
377 /* I am not amused by the length of these. */
378 for (i = 0; i < 4; i++) {
379 consts->constants[assembler->imm_offset +
380 assembler->imm_count][i] =
381 parser.FullToken.FullImmediate.u.ImmediateFloat32[i]
382 .Float;
383 }
384 assembler->imm_count++;
385 break;
386 case TGSI_TOKEN_TYPE_INSTRUCTION:
387 r300_vs_instruction(vs, assembler,
388 &parser.FullToken.FullInstruction);
389 break;
390 }
391 }
392
393 debug_printf("r300: vs: %d texs and %d colors, first free reg is %d\n",
394 assembler->tex_count, assembler->color_count,
395 assembler->tex_count + assembler->color_count);
396
397 consts->count = consts->user_count + assembler->imm_count;
398 vs->uses_imms = assembler->imm_count;
399 debug_printf("r300: vs: %d total constants, "
400 "%d from user and %d from immediates\n", consts->count,
401 consts->user_count, assembler->imm_count);
402
403 debug_printf("r300: vs: tab: %d %d %d %d\n", assembler->tab[0],
404 assembler->tab[1], assembler->tab[2], assembler->tab[3]);
405
406 tgsi_dump(vs->state.tokens, 0);
407 /* XXX finish r300 vertex shader dumper */
408 r300_vs_dump(vs);
409
410 tgsi_parse_free(&parser);
411 FREE(assembler);
412 }