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. */
23 #include "r300_state_tcl.h"
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
)
74 /* Probably a zero or one swizzle */
75 return R300_PVS_SRC_REG_INPUT
;
78 return R300_PVS_SRC_REG_INPUT
;
80 case TGSI_FILE_TEMPORARY
:
81 return R300_PVS_SRC_REG_TEMPORARY
;
83 case TGSI_FILE_CONSTANT
:
84 return R300_PVS_SRC_REG_CONSTANT
;
86 debug_printf("r300: vs: Unimplemented src type %d\n", src
->File
);
92 static INLINE
unsigned r300_vs_dst_type(struct r300_vs_asm
* assembler
,
93 struct tgsi_dst_register
* dst
)
96 case TGSI_FILE_TEMPORARY
:
97 return R300_PVS_DST_REG_TEMPORARY
;
99 case TGSI_FILE_OUTPUT
:
100 return R300_PVS_DST_REG_OUT
;
103 debug_printf("r300: vs: Unimplemented dst type %d\n", dst
->File
);
109 static INLINE
unsigned r300_vs_dst(struct r300_vs_asm
* assembler
,
110 struct tgsi_dst_register
* dst
)
113 case TGSI_FILE_TEMPORARY
:
116 case TGSI_FILE_OUTPUT
:
117 return assembler
->tab
[dst
->Index
];
120 debug_printf("r300: vs: Unimplemented dst %d\n", dst
->File
);
126 static uint32_t r300_vs_op(unsigned op
)
129 case TGSI_OPCODE_DP3
:
130 case TGSI_OPCODE_DP4
:
131 return R300_VE_DOT_PRODUCT
;
132 case TGSI_OPCODE_MUL
:
133 return R300_VE_MULTIPLY
;
134 case TGSI_OPCODE_ADD
:
135 case TGSI_OPCODE_MOV
:
136 case TGSI_OPCODE_SWZ
:
138 case TGSI_OPCODE_MAD
:
139 return R300_PVS_DST_MACRO_INST
| R300_PVS_MACRO_OP_2CLK_MADD
;
146 static uint32_t r300_vs_swiz(struct tgsi_full_src_register
* reg
)
148 if (reg
->SrcRegister
.Extended
) {
149 return reg
->SrcRegisterExtSwz
.ExtSwizzleX
|
150 (reg
->SrcRegisterExtSwz
.ExtSwizzleY
<< 3) |
151 (reg
->SrcRegisterExtSwz
.ExtSwizzleZ
<< 6) |
152 (reg
->SrcRegisterExtSwz
.ExtSwizzleW
<< 9);
154 return reg
->SrcRegister
.SwizzleX
|
155 (reg
->SrcRegister
.SwizzleY
<< 3) |
156 (reg
->SrcRegister
.SwizzleZ
<< 6) |
157 (reg
->SrcRegister
.SwizzleW
<< 9);
161 static void r300_vs_emit_inst(struct r300_vertex_shader
* vs
,
162 struct r300_vs_asm
* assembler
,
163 struct tgsi_full_src_register
* src
,
164 struct tgsi_full_dst_register
* dst
,
168 int i
= vs
->instruction_count
;
169 vs
->instructions
[i
].inst0
= R300_PVS_DST_OPCODE(r300_vs_op(op
)) |
170 R300_PVS_DST_REG_TYPE(r300_vs_dst_type(assembler
, &dst
->DstRegister
)) |
171 R300_PVS_DST_OFFSET(r300_vs_dst(assembler
, &dst
->DstRegister
)) |
172 R300_PVS_DST_WE_XYZW
;
175 vs
->instructions
[i
].inst3
=
176 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler
,
177 &src
[2].SrcRegister
)) |
178 R300_PVS_SRC_OFFSET(src
[2].SrcRegister
.Index
) |
179 R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src
[2]));
182 vs
->instructions
[i
].inst2
=
183 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler
,
184 &src
[1].SrcRegister
)) |
185 R300_PVS_SRC_OFFSET(src
[1].SrcRegister
.Index
) |
186 R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src
[1]));
189 vs
->instructions
[i
].inst1
=
190 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler
,
191 &src
[0].SrcRegister
)) |
192 R300_PVS_SRC_OFFSET(src
[0].SrcRegister
.Index
) |
193 R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src
[0]));
196 vs
->instruction_count
++;
199 static void r300_vs_instruction(struct r300_vertex_shader
* vs
,
200 struct r300_vs_asm
* assembler
,
201 struct tgsi_full_instruction
* inst
)
203 switch (inst
->Instruction
.Opcode
) {
204 case TGSI_OPCODE_ADD
:
205 case TGSI_OPCODE_MUL
:
206 r300_vs_emit_inst(vs
, assembler
, inst
->FullSrcRegisters
,
207 &inst
->FullDstRegisters
[0], inst
->Instruction
.Opcode
,
210 case TGSI_OPCODE_DP3
:
211 /* Set alpha swizzle to zero for src0 and src1 */
212 if (!inst
->FullSrcRegisters
[0].SrcRegister
.Extended
) {
213 inst
->FullSrcRegisters
[0].SrcRegister
.Extended
= TRUE
;
214 inst
->FullSrcRegisters
[0].SrcRegisterExtSwz
.ExtSwizzleX
=
215 inst
->FullSrcRegisters
[0].SrcRegister
.SwizzleX
;
216 inst
->FullSrcRegisters
[0].SrcRegisterExtSwz
.ExtSwizzleY
=
217 inst
->FullSrcRegisters
[0].SrcRegister
.SwizzleY
;
218 inst
->FullSrcRegisters
[0].SrcRegisterExtSwz
.ExtSwizzleZ
=
219 inst
->FullSrcRegisters
[0].SrcRegister
.SwizzleZ
;
221 inst
->FullSrcRegisters
[0].SrcRegisterExtSwz
.ExtSwizzleW
=
222 TGSI_EXTSWIZZLE_ZERO
;
223 if (!inst
->FullSrcRegisters
[1].SrcRegister
.Extended
) {
224 inst
->FullSrcRegisters
[1].SrcRegister
.Extended
= TRUE
;
225 inst
->FullSrcRegisters
[1].SrcRegisterExtSwz
.ExtSwizzleX
=
226 inst
->FullSrcRegisters
[1].SrcRegister
.SwizzleX
;
227 inst
->FullSrcRegisters
[1].SrcRegisterExtSwz
.ExtSwizzleY
=
228 inst
->FullSrcRegisters
[1].SrcRegister
.SwizzleY
;
229 inst
->FullSrcRegisters
[1].SrcRegisterExtSwz
.ExtSwizzleZ
=
230 inst
->FullSrcRegisters
[1].SrcRegister
.SwizzleZ
;
232 inst
->FullSrcRegisters
[1].SrcRegisterExtSwz
.ExtSwizzleW
=
233 TGSI_EXTSWIZZLE_ZERO
;
235 case TGSI_OPCODE_DP4
:
236 r300_vs_emit_inst(vs
, assembler
, inst
->FullSrcRegisters
,
237 &inst
->FullDstRegisters
[0], inst
->Instruction
.Opcode
,
240 case TGSI_OPCODE_MOV
:
241 case TGSI_OPCODE_SWZ
:
242 inst
->FullSrcRegisters
[1] = r300_constant_zero
;
243 r300_vs_emit_inst(vs
, assembler
, inst
->FullSrcRegisters
,
244 &inst
->FullDstRegisters
[0], inst
->Instruction
.Opcode
,
247 case TGSI_OPCODE_MAD
:
248 r300_vs_emit_inst(vs
, assembler
, inst
->FullSrcRegisters
,
249 &inst
->FullDstRegisters
[0], inst
->Instruction
.Opcode
,
252 case TGSI_OPCODE_END
:
255 debug_printf("r300: vs: Bad opcode %d\n",
256 inst
->Instruction
.Opcode
);
261 static void r300_vs_init(struct r300_vertex_shader
* vs
,
262 struct r300_vs_asm
* assembler
)
264 struct tgsi_shader_info
* info
= &vs
->info
;
267 for (i
= 0; i
< info
->num_outputs
; i
++) {
268 switch (info
->output_semantic_name
[i
]) {
269 case TGSI_SEMANTIC_PSIZE
:
270 assembler
->point_size
= TRUE
;
272 case TGSI_SEMANTIC_COLOR
:
273 assembler
->out_colors
++;
275 case TGSI_SEMANTIC_FOG
:
276 case TGSI_SEMANTIC_GENERIC
:
277 assembler
->out_texcoords
++;
283 void r300_translate_vertex_shader(struct r300_context
* r300
,
284 struct r300_vertex_shader
* vs
)
286 struct tgsi_parse_context parser
;
288 struct r300_constant_buffer
* consts
=
289 &r300
->shader_constants
[PIPE_SHADER_VERTEX
];
291 struct r300_vs_asm
* assembler
= CALLOC_STRUCT(r300_vs_asm
);
292 if (assembler
== NULL
) {
296 /* Init assembler. */
297 r300_vs_init(vs
, assembler
);
299 /* Setup starting offset for immediates. */
300 assembler
->imm_offset
= consts
->user_count
;
302 tgsi_parse_init(&parser
, vs
->state
.tokens
);
304 while (!tgsi_parse_end_of_tokens(&parser
)) {
305 tgsi_parse_token(&parser
);
307 /* This is seriously the lamest way to create fragment programs ever.
309 switch (parser
.FullToken
.Token
.Type
) {
310 case TGSI_TOKEN_TYPE_DECLARATION
:
311 /* Allocated registers sitting at the beginning
313 r300_vs_declare(assembler
, &parser
.FullToken
.FullDeclaration
);
315 case TGSI_TOKEN_TYPE_IMMEDIATE
:
316 debug_printf("r300: Emitting immediate to constant buffer, "
318 assembler
->imm_offset
+ assembler
->imm_count
);
319 /* I am not amused by the length of these. */
320 for (i
= 0; i
< 4; i
++) {
321 consts
->constants
[assembler
->imm_offset
+
322 assembler
->imm_count
][i
] =
323 parser
.FullToken
.FullImmediate
.u
.ImmediateFloat32
[i
]
326 assembler
->imm_count
++;
328 case TGSI_TOKEN_TYPE_INSTRUCTION
:
329 r300_vs_instruction(vs
, assembler
,
330 &parser
.FullToken
.FullInstruction
);
335 debug_printf("r300: vs: %d texs and %d colors, first free reg is %d\n",
336 assembler
->tex_count
, assembler
->color_count
,
337 assembler
->tex_count
+ assembler
->color_count
);
339 consts
->count
= consts
->user_count
+ assembler
->imm_count
;
340 debug_printf("r300: vs: %d total constants, "
341 "%d from user and %d from immediates\n", consts
->count
,
342 consts
->user_count
, assembler
->imm_count
);
344 debug_printf("r300: vs: tab: %d %d %d %d\n", assembler
->tab
[0],
345 assembler
->tab
[1], assembler
->tab
[2], assembler
->tab
[3]);
347 tgsi_dump(vs
->state
.tokens
);
348 /* XXX finish r300 vertex shader dumper */
351 tgsi_parse_free(&parser
);