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
] = 2;
39 case TGSI_SEMANTIC_GENERIC
:
41 assembler
->tab
[decl
->DeclarationRange
.First
] = 6;
44 debug_printf("r300: vs: Bad semantic declaration %d\n",
45 decl
->Semantic
.SemanticName
);
49 case TGSI_FILE_CONSTANT
:
51 case TGSI_FILE_TEMPORARY
:
52 assembler
->temp_count
++;
55 debug_printf("r300: vs: Bad file %d\n", decl
->Declaration
.File
);
60 static INLINE
unsigned r300_vs_src_type(struct r300_vs_asm
* assembler
,
61 struct tgsi_src_register
* src
)
65 /* Probably a zero or one swizzle */
66 return R300_PVS_SRC_REG_INPUT
;
69 return R300_PVS_SRC_REG_INPUT
;
71 case TGSI_FILE_TEMPORARY
:
72 return R300_PVS_SRC_REG_TEMPORARY
;
75 debug_printf("r300: vs: Unimplemented src type %d\n", src
->File
);
81 static INLINE
unsigned r300_vs_dst_type(struct r300_vs_asm
* assembler
,
82 struct tgsi_dst_register
* dst
)
85 case TGSI_FILE_TEMPORARY
:
86 return R300_PVS_DST_REG_TEMPORARY
;
88 case TGSI_FILE_OUTPUT
:
89 return R300_PVS_DST_REG_OUT
;
92 debug_printf("r300: vs: Unimplemented dst type %d\n", dst
->File
);
98 static INLINE
unsigned r300_vs_dst(struct r300_vs_asm
* assembler
,
99 struct tgsi_dst_register
* dst
)
102 case TGSI_FILE_TEMPORARY
:
105 case TGSI_FILE_OUTPUT
:
106 return assembler
->tab
[dst
->Index
];
109 debug_printf("r300: vs: Unimplemented dst %d\n", dst
->File
);
115 static uint32_t r300_vs_op(unsigned op
)
118 case TGSI_OPCODE_MUL
:
119 return R300_VE_MULTIPLY
;
120 case TGSI_OPCODE_ADD
:
121 case TGSI_OPCODE_MOV
:
122 case TGSI_OPCODE_SWZ
:
124 case TGSI_OPCODE_MAD
:
125 return R300_PVS_DST_MACRO_INST
| R300_PVS_MACRO_OP_2CLK_MADD
;
132 static uint32_t r300_vs_swiz(struct tgsi_full_src_register
* reg
)
134 if (reg
->SrcRegister
.Extended
) {
135 return reg
->SrcRegisterExtSwz
.ExtSwizzleX
|
136 (reg
->SrcRegisterExtSwz
.ExtSwizzleY
<< 3) |
137 (reg
->SrcRegisterExtSwz
.ExtSwizzleZ
<< 6) |
138 (reg
->SrcRegisterExtSwz
.ExtSwizzleW
<< 9);
140 return reg
->SrcRegister
.SwizzleX
|
141 (reg
->SrcRegister
.SwizzleY
<< 3) |
142 (reg
->SrcRegister
.SwizzleZ
<< 6) |
143 (reg
->SrcRegister
.SwizzleW
<< 9);
147 static void r300_vs_emit_inst(struct r300_vertex_shader
* vs
,
148 struct r300_vs_asm
* assembler
,
149 struct tgsi_full_src_register
* src
,
150 struct tgsi_full_dst_register
* dst
,
154 int i
= vs
->instruction_count
;
155 vs
->instructions
[i
].inst0
= R300_PVS_DST_OPCODE(r300_vs_op(op
)) |
156 R300_PVS_DST_REG_TYPE(r300_vs_dst_type(assembler
, &dst
->DstRegister
)) |
157 R300_PVS_DST_OFFSET(r300_vs_dst(assembler
, &dst
->DstRegister
)) |
158 R300_PVS_DST_WE_XYZW
;
161 vs
->instructions
[i
].inst3
=
162 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler
,
163 &src
[2].SrcRegister
)) |
164 R300_PVS_SRC_OFFSET(src
[2].SrcRegister
.Index
) |
165 R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src
[2]));
168 vs
->instructions
[i
].inst2
=
169 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler
,
170 &src
[1].SrcRegister
)) |
171 R300_PVS_SRC_OFFSET(src
[1].SrcRegister
.Index
) |
172 R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src
[1]));
175 vs
->instructions
[i
].inst1
=
176 R300_PVS_SRC_REG_TYPE(r300_vs_src_type(assembler
,
177 &src
[0].SrcRegister
)) |
178 R300_PVS_SRC_OFFSET(src
[0].SrcRegister
.Index
) |
179 R300_PVS_SRC_SWIZZLE(r300_vs_swiz(&src
[0]));
182 vs
->instruction_count
++;
185 static void r300_vs_instruction(struct r300_vertex_shader
* vs
,
186 struct r300_vs_asm
* assembler
,
187 struct tgsi_full_instruction
* inst
)
189 switch (inst
->Instruction
.Opcode
) {
190 case TGSI_OPCODE_ADD
:
191 case TGSI_OPCODE_MUL
:
192 r300_vs_emit_inst(vs
, assembler
, inst
->FullSrcRegisters
,
193 &inst
->FullDstRegisters
[0], inst
->Instruction
.Opcode
,
196 case TGSI_OPCODE_MOV
:
197 case TGSI_OPCODE_SWZ
:
198 inst
->FullSrcRegisters
[1] = r300_constant_zero
;
199 r300_vs_emit_inst(vs
, assembler
, inst
->FullSrcRegisters
,
200 &inst
->FullDstRegisters
[0], inst
->Instruction
.Opcode
,
203 case TGSI_OPCODE_MAD
:
204 r300_vs_emit_inst(vs
, assembler
, inst
->FullSrcRegisters
,
205 &inst
->FullDstRegisters
[0], inst
->Instruction
.Opcode
,
208 case TGSI_OPCODE_END
:
211 debug_printf("r300: vs: Bad opcode %d\n",
212 inst
->Instruction
.Opcode
);
217 void r300_translate_vertex_shader(struct r300_context
* r300
,
218 struct r300_vertex_shader
* vs
)
220 struct tgsi_parse_context parser
;
222 struct r300_constant_buffer
* consts
=
223 &r300
->shader_constants
[PIPE_SHADER_VERTEX
];
225 struct r300_vs_asm
* assembler
= CALLOC_STRUCT(r300_vs_asm
);
226 if (assembler
== NULL
) {
229 /* Setup starting offset for immediates. */
230 assembler
->imm_offset
= consts
->user_count
;
232 tgsi_parse_init(&parser
, vs
->state
.tokens
);
234 while (!tgsi_parse_end_of_tokens(&parser
)) {
235 tgsi_parse_token(&parser
);
237 /* This is seriously the lamest way to create fragment programs ever.
239 switch (parser
.FullToken
.Token
.Type
) {
240 case TGSI_TOKEN_TYPE_DECLARATION
:
241 /* Allocated registers sitting at the beginning
243 r300_vs_declare(assembler
, &parser
.FullToken
.FullDeclaration
);
245 case TGSI_TOKEN_TYPE_IMMEDIATE
:
246 debug_printf("r300: Emitting immediate to constant buffer, "
248 assembler
->imm_offset
+ assembler
->imm_count
);
249 /* I am not amused by the length of these. */
250 for (i
= 0; i
< 4; i
++) {
251 consts
->constants
[assembler
->imm_offset
+
252 assembler
->imm_count
][i
] =
253 parser
.FullToken
.FullImmediate
.u
.ImmediateFloat32
[i
]
256 assembler
->imm_count
++;
258 case TGSI_TOKEN_TYPE_INSTRUCTION
:
259 r300_vs_instruction(vs
, assembler
,
260 &parser
.FullToken
.FullInstruction
);
265 debug_printf("r300: vs: %d texs and %d colors, first free reg is %d\n",
266 assembler
->tex_count
, assembler
->color_count
,
267 assembler
->tex_count
+ assembler
->color_count
);
269 consts
->count
= consts
->user_count
+ assembler
->imm_count
;
270 debug_printf("r300: vs: %d total constants, "
271 "%d from user and %d from immediates\n", consts
->count
,
272 consts
->user_count
, assembler
->imm_count
);
274 debug_printf("r300: vs: tab: %d %d %d %d\n", assembler
->tab
[0],
275 assembler
->tab
[1], assembler
->tab
[2], assembler
->tab
[3]);
277 tgsi_dump(vs
->state
.tokens
);
278 /* XXX finish r300 vertex shader dumper */
281 tgsi_parse_free(&parser
);