r300-gallium: vs: Moar vert shaders.
[mesa.git] / src / gallium / drivers / r300 / r300_state_tcl.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_state_tcl.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 switch (decl->Semantic.SemanticName) {
31 case TGSI_SEMANTIC_COLOR:
32 assembler->color_count++;
33 break;
34 case TGSI_SEMANTIC_GENERIC:
35 assembler->tex_count++;
36 break;
37 default:
38 debug_printf("r300: vs: Bad semantic declaration %d\n",
39 decl->Semantic.SemanticName);
40 break;
41 }
42 break;
43 case TGSI_FILE_OUTPUT:
44 case TGSI_FILE_CONSTANT:
45 break;
46 case TGSI_FILE_TEMPORARY:
47 assembler->temp_count++;
48 break;
49 default:
50 debug_printf("r300: vs: Bad file %d\n", decl->Declaration.File);
51 break;
52 }
53
54 assembler->temp_offset = assembler->color_count + assembler->tex_count;
55 }
56
57 static INLINE unsigned r300_vs_src_type(struct r300_vs_asm* assembler,
58 struct tgsi_src_register* src)
59 {
60 switch (src->File) {
61 case TGSI_FILE_INPUT:
62 return R300_PVS_SRC_REG_INPUT;
63 break;
64 case TGSI_FILE_TEMPORARY:
65 return R300_PVS_SRC_REG_TEMPORARY;
66 break;
67 default:
68 debug_printf("r300: vs: Unimplemented src type %d\n", src->File);
69 break;
70 }
71 return 0;
72 }
73
74 static INLINE unsigned r300_vs_dst_type(struct r300_vs_asm* assembler,
75 struct tgsi_dst_register* dst)
76 {
77 switch (dst->File) {
78 case TGSI_FILE_TEMPORARY:
79 return R300_PVS_DST_REG_TEMPORARY;
80 break;
81 case TGSI_FILE_OUTPUT:
82 return R300_PVS_DST_REG_OUT;
83 break;
84 default:
85 debug_printf("r300: vs: Unimplemented dst type %d\n", dst->File);
86 break;
87 }
88 return 0;
89 }
90
91 static INLINE unsigned r300_vs_src(struct r300_vs_asm* assembler,
92 struct tgsi_src_register* src)
93 {
94 switch (src->File) {
95 case TGSI_FILE_NULL:
96 return 0;
97 case TGSI_FILE_INPUT:
98 /* XXX may be wrong */
99 return src->Index;
100 break;
101 case TGSI_FILE_TEMPORARY:
102 return src->Index + assembler->temp_offset;
103 break;
104 case TGSI_FILE_IMMEDIATE:
105 return (src->Index + assembler->imm_offset) | (1 << 8);
106 break;
107 case TGSI_FILE_CONSTANT:
108 /* XXX magic */
109 return src->Index | (1 << 8);
110 break;
111 default:
112 debug_printf("r300: vs: Unimplemented src %d\n", src->File);
113 break;
114 }
115 return 0;
116 }
117
118 static INLINE unsigned r300_vs_dst(struct r300_vs_asm* assembler,
119 struct tgsi_dst_register* dst)
120 {
121 switch (dst->File) {
122 case TGSI_FILE_NULL:
123 /* This happens during KIL instructions. */
124 return 0;
125 break;
126 case TGSI_FILE_OUTPUT:
127 return 0;
128 break;
129 case TGSI_FILE_TEMPORARY:
130 return dst->Index + assembler->temp_offset;
131 break;
132 default:
133 debug_printf("r300: vs: Unimplemented dst %d\n", dst->File);
134 break;
135 }
136 return 0;
137 }
138
139 static uint32_t r300_vs_swiz(struct tgsi_full_src_register* reg)
140 {
141 if (reg->SrcRegister.Extended) {
142 return reg->SrcRegisterExtSwz.ExtSwizzleX |
143 (reg->SrcRegisterExtSwz.ExtSwizzleY << 3) |
144 (reg->SrcRegisterExtSwz.ExtSwizzleZ << 6) |
145 (reg->SrcRegisterExtSwz.ExtSwizzleW << 9);
146 } else {
147 return reg->SrcRegister.SwizzleX |
148 (reg->SrcRegister.SwizzleY << 3) |
149 (reg->SrcRegister.SwizzleZ << 6) |
150 (reg->SrcRegister.SwizzleW << 9);
151 }
152 }
153
154 static void r300_vs_emit_inst(struct r300_vertex_shader* vs,
155 struct r300_vs_asm* assembler,
156 struct tgsi_full_src_register* src,
157 struct tgsi_full_dst_register* dst,
158 unsigned op,
159 unsigned count)
160 {
161 int i = vs->instruction_count;
162 vs->instructions[i].inst0 = R300_PVS_DST_OPCODE(R300_VE_ADD) |
163 R300_PVS_DST_REG_TYPE(r300_vs_dst_type(assembler, &dst->DstRegister)) |
164 R300_PVS_DST_OFFSET(dst->DstRegister.Index);
165 switch (count) {
166 case 3:
167 vs->instructions[i].inst3 =
168 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
169 &src[2].SrcRegister)) |
170 R300_PVS_SRC_OFFSET(src[2].SrcRegister.Index) |
171 R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[2]));
172 /* Fall through */
173 case 2:
174 vs->instructions[i].inst2 =
175 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
176 &src[1].SrcRegister)) |
177 R300_PVS_SRC_OFFSET(src[1].SrcRegister.Index) |
178 R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[1]));
179 /* Fall through */
180 case 1:
181 vs->instructions[i].inst1 =
182 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler,
183 &src[0].SrcRegister)) |
184 R300_PVS_SRC_OFFSET(src[0].SrcRegister.Index) |
185 R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src[0]));
186 break;
187 }
188 }
189
190 static void r300_vs_instruction(struct r300_vertex_shader* vs,
191 struct r300_vs_asm* assembler,
192 struct tgsi_full_instruction* inst)
193 {
194 switch (inst->Instruction.Opcode) {
195 case TGSI_OPCODE_MOV:
196 case TGSI_OPCODE_SWZ:
197 inst->FullSrcRegisters[1] = r300_constant_zero;
198 r300_vs_emit_inst(vs, assembler, inst->FullSrcRegisters,
199 &inst->FullDstRegisters[0], inst->Instruction.Opcode,
200 2);
201 break;
202 case TGSI_OPCODE_END:
203 break;
204 default:
205 debug_printf("r300: vs: Bad opcode %d\n",
206 inst->Instruction.Opcode);
207 break;
208 }
209 }
210
211 void r300_translate_vertex_shader(struct r300_context* r300,
212 struct r300_vertex_shader* vs)
213 {
214 struct tgsi_parse_context parser;
215 int i;
216 struct r300_constant_buffer* consts =
217 &r300->shader_constants[PIPE_SHADER_VERTEX];
218
219 struct r300_vs_asm* assembler = CALLOC_STRUCT(r300_vs_asm);
220 if (assembler == NULL) {
221 return;
222 }
223 /* Setup starting offset for immediates. */
224 assembler->imm_offset = consts->user_count;
225
226 tgsi_parse_init(&parser, vs->state.tokens);
227
228 while (!tgsi_parse_end_of_tokens(&parser)) {
229 tgsi_parse_token(&parser);
230
231 /* This is seriously the lamest way to create fragment programs ever.
232 * I blame TGSI. */
233 switch (parser.FullToken.Token.Type) {
234 case TGSI_TOKEN_TYPE_DECLARATION:
235 /* Allocated registers sitting at the beginning
236 * of the program. */
237 r300_vs_declare(assembler, &parser.FullToken.FullDeclaration);
238 break;
239 case TGSI_TOKEN_TYPE_IMMEDIATE:
240 debug_printf("r300: Emitting immediate to constant buffer, "
241 "position %d\n",
242 assembler->imm_offset + assembler->imm_count);
243 /* I am not amused by the length of these. */
244 for (i = 0; i < 4; i++) {
245 consts->constants[assembler->imm_offset +
246 assembler->imm_count][i] =
247 parser.FullToken.FullImmediate.u.ImmediateFloat32[i]
248 .Float;
249 }
250 assembler->imm_count++;
251 break;
252 case TGSI_TOKEN_TYPE_INSTRUCTION:
253 r300_vs_instruction(vs, assembler,
254 &parser.FullToken.FullInstruction);
255 break;
256 }
257 }
258
259 debug_printf("r300: vs: %d texs and %d colors, first free reg is %d\n",
260 assembler->tex_count, assembler->color_count,
261 assembler->tex_count + assembler->color_count);
262
263 consts->count = consts->user_count + assembler->imm_count;
264 debug_printf("r300: vs: %d total constants, "
265 "%d from user and %d from immediates\n", consts->count,
266 consts->user_count, assembler->imm_count);
267
268 tgsi_dump(vs->state.tokens);
269 /* XXX finish r300 vertex shader dumper */
270
271 tgsi_parse_free(&parser);
272 FREE(assembler);
273 }