2 * Copyright 2009 Corbin Simpson <MostAwesomeDude@gmail.com>
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:
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
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. */
25 static void r300_vs_declare(struct r300_vs_asm
* assembler
,
26 struct tgsi_full_declaration
* decl
)
28 switch (decl
->Declaration
.File
) {
31 case TGSI_FILE_OUTPUT
:
32 switch (decl
->Semantic
.SemanticName
) {
33 case TGSI_SEMANTIC_POSITION
:
34 assembler
->tab
[decl
->DeclarationRange
.First
] = 0;
36 case TGSI_SEMANTIC_COLOR
:
37 assembler
->tab
[decl
->DeclarationRange
.First
] =
38 (assembler
->point_size
? 1 : 0) +
39 assembler
->out_colors
;
41 case TGSI_SEMANTIC_FOG
:
42 case TGSI_SEMANTIC_GENERIC
:
44 assembler
->tab
[decl
->DeclarationRange
.First
] =
45 (assembler
->point_size
? 1 : 0) +
46 assembler
->out_colors
+
47 assembler
->out_texcoords
;
49 case TGSI_SEMANTIC_PSIZE
:
50 assembler
->tab
[decl
->DeclarationRange
.First
] = 1;
53 debug_printf("r300: vs: Bad semantic declaration %d\n",
54 decl
->Semantic
.SemanticName
);
58 case TGSI_FILE_CONSTANT
:
60 case TGSI_FILE_TEMPORARY
:
61 assembler
->temp_count
++;
64 debug_printf("r300: vs: Bad file %d\n", decl
->Declaration
.File
);
69 static INLINE
unsigned r300_vs_src_type(struct r300_vs_asm
* assembler
,
70 struct tgsi_src_register
* src
)
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
;
83 debug_printf("r300: vs: Unimplemented src type %d\n", src
->File
);
89 static INLINE
unsigned r300_vs_src(struct r300_vs_asm
* assembler
,
90 struct tgsi_src_register
* src
)
95 case TGSI_FILE_TEMPORARY
:
96 case TGSI_FILE_CONSTANT
:
98 case TGSI_FILE_IMMEDIATE
:
99 return src
->Index
+ assembler
->imm_offset
;
101 debug_printf("r300: vs: Unimplemented src type %d\n", src
->File
);
107 static INLINE
unsigned r300_vs_dst_type(struct r300_vs_asm
* assembler
,
108 struct tgsi_dst_register
* dst
)
111 case TGSI_FILE_TEMPORARY
:
112 return R300_PVS_DST_REG_TEMPORARY
;
113 case TGSI_FILE_OUTPUT
:
114 return R300_PVS_DST_REG_OUT
;
116 debug_printf("r300: vs: Unimplemented dst type %d\n", dst
->File
);
122 static INLINE
unsigned r300_vs_dst(struct r300_vs_asm
* assembler
,
123 struct tgsi_dst_register
* dst
)
126 case TGSI_FILE_TEMPORARY
:
128 case TGSI_FILE_OUTPUT
:
129 return assembler
->tab
[dst
->Index
];
131 debug_printf("r300: vs: Unimplemented dst %d\n", dst
->File
);
137 static uint32_t r300_vs_op(unsigned 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
:
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
;
164 static uint32_t r300_vs_swiz(struct tgsi_full_src_register
* reg
)
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);
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);
181 /* XXX icky icky icky icky */
182 static uint32_t r300_vs_scalar_swiz(struct tgsi_full_src_register
* reg
)
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);
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);
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
,
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
);
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]));
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]));
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]));
241 vs
->instruction_count
++;
244 static void r300_vs_instruction(struct r300_vertex_shader
* vs
,
245 struct r300_vs_asm
* assembler
,
246 struct tgsi_full_instruction
* inst
)
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
,
254 case TGSI_OPCODE_SUB
:
255 inst
->FullSrcRegisters
[1].SrcRegister
.Negate
=
256 !inst
->FullSrcRegisters
[1].SrcRegister
.Negate
;
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
,
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
;
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
;
288 inst
->FullSrcRegisters
[1].SrcRegisterExtSwz
.ExtSwizzleW
=
289 TGSI_EXTSWIZZLE_ZERO
;
291 case TGSI_OPCODE_DP4
:
292 r300_vs_emit_inst(vs
, assembler
, inst
->FullSrcRegisters
,
293 &inst
->FullDstRegisters
[0], inst
->Instruction
.Opcode
,
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
,
303 case TGSI_OPCODE_MAD
:
304 r300_vs_emit_inst(vs
, assembler
, inst
->FullSrcRegisters
,
305 &inst
->FullDstRegisters
[0], inst
->Instruction
.Opcode
,
308 case TGSI_OPCODE_END
:
311 debug_printf("r300: vs: Bad opcode %d\n",
312 inst
->Instruction
.Opcode
);
317 static void r300_vs_init(struct r300_vertex_shader
* vs
,
318 struct r300_vs_asm
* assembler
)
320 struct tgsi_shader_info
* info
= &vs
->info
;
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
;
328 case TGSI_SEMANTIC_COLOR
:
329 assembler
->out_colors
++;
331 case TGSI_SEMANTIC_FOG
:
332 case TGSI_SEMANTIC_GENERIC
:
333 assembler
->out_texcoords
++;
338 vs
->instruction_count
= 0;
341 void r300_translate_vertex_shader(struct r300_context
* r300
,
342 struct r300_vertex_shader
* vs
)
344 struct tgsi_parse_context parser
;
346 struct r300_constant_buffer
* consts
=
347 &r300
->shader_constants
[PIPE_SHADER_VERTEX
];
349 struct r300_vs_asm
* assembler
= CALLOC_STRUCT(r300_vs_asm
);
350 if (assembler
== NULL
) {
354 /* Init assembler. */
355 r300_vs_init(vs
, assembler
);
357 /* Setup starting offset for immediates. */
358 assembler
->imm_offset
= consts
->user_count
;
360 tgsi_parse_init(&parser
, vs
->state
.tokens
);
362 while (!tgsi_parse_end_of_tokens(&parser
)) {
363 tgsi_parse_token(&parser
);
365 /* This is seriously the lamest way to create fragment programs ever.
367 switch (parser
.FullToken
.Token
.Type
) {
368 case TGSI_TOKEN_TYPE_DECLARATION
:
369 /* Allocated registers sitting at the beginning
371 r300_vs_declare(assembler
, &parser
.FullToken
.FullDeclaration
);
373 case TGSI_TOKEN_TYPE_IMMEDIATE
:
374 debug_printf("r300: Emitting immediate to constant buffer, "
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
[i
].Float
;
383 assembler
->imm_count
++;
385 case TGSI_TOKEN_TYPE_INSTRUCTION
:
386 r300_vs_instruction(vs
, assembler
,
387 &parser
.FullToken
.FullInstruction
);
392 debug_printf("r300: vs: %d texs and %d colors, first free reg is %d\n",
393 assembler
->tex_count
, assembler
->color_count
,
394 assembler
->tex_count
+ assembler
->color_count
);
396 consts
->count
= consts
->user_count
+ assembler
->imm_count
;
397 vs
->uses_imms
= assembler
->imm_count
;
398 debug_printf("r300: vs: %d total constants, "
399 "%d from user and %d from immediates\n", consts
->count
,
400 consts
->user_count
, assembler
->imm_count
);
402 debug_printf("r300: vs: tab: %d %d %d %d\n", assembler
->tab
[0],
403 assembler
->tab
[1], assembler
->tab
[2], assembler
->tab
[3]);
405 tgsi_dump(vs
->state
.tokens
, 0);
406 /* XXX finish r300 vertex shader dumper */
409 tgsi_parse_free(&parser
);
412 /* And, finally... */
413 vs
->translated
= TRUE
;