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
) {
30 switch (decl
->Semantic
.SemanticName
) {
31 case TGSI_SEMANTIC_COLOR
:
32 assembler
->color_count
++;
34 case TGSI_SEMANTIC_GENERIC
:
35 assembler
->tex_count
++;
38 debug_printf("r300: vs: Bad semantic declaration %d\n",
39 decl
->Semantic
.SemanticName
);
43 case TGSI_FILE_OUTPUT
:
44 case TGSI_FILE_CONSTANT
:
46 case TGSI_FILE_TEMPORARY
:
47 assembler
->temp_count
++;
50 debug_printf("r300: vs: Bad file %d\n", decl
->Declaration
.File
);
54 assembler
->temp_offset
= assembler
->color_count
+ assembler
->tex_count
;
57 static INLINE
unsigned r300_vs_src_type(struct r300_vs_asm
* assembler
,
58 struct tgsi_src_register
* src
)
62 return R300_PVS_SRC_REG_INPUT
;
64 case TGSI_FILE_TEMPORARY
:
65 return R300_PVS_SRC_REG_TEMPORARY
;
68 debug_printf("r300: vs: Unimplemented src type %d\n", src
->File
);
74 static INLINE
unsigned r300_vs_dst_type(struct r300_vs_asm
* assembler
,
75 struct tgsi_dst_register
* dst
)
78 case TGSI_FILE_TEMPORARY
:
79 return R300_PVS_DST_REG_TEMPORARY
;
81 case TGSI_FILE_OUTPUT
:
82 return R300_PVS_DST_REG_OUT
;
85 debug_printf("r300: vs: Unimplemented dst type %d\n", dst
->File
);
91 static INLINE
unsigned r300_vs_src(struct r300_vs_asm
* assembler
,
92 struct tgsi_src_register
* src
)
98 /* XXX may be wrong */
101 case TGSI_FILE_TEMPORARY
:
102 return src
->Index
+ assembler
->temp_offset
;
104 case TGSI_FILE_IMMEDIATE
:
105 return (src
->Index
+ assembler
->imm_offset
) | (1 << 8);
107 case TGSI_FILE_CONSTANT
:
109 return src
->Index
| (1 << 8);
112 debug_printf("r300: vs: Unimplemented src %d\n", src
->File
);
118 static INLINE
unsigned r300_vs_dst(struct r300_vs_asm
* assembler
,
119 struct tgsi_dst_register
* dst
)
123 /* This happens during KIL instructions. */
126 case TGSI_FILE_OUTPUT
:
129 case TGSI_FILE_TEMPORARY
:
130 return dst
->Index
+ assembler
->temp_offset
;
133 debug_printf("r300: vs: Unimplemented dst %d\n", dst
->File
);
139 static uint32_t r300_vs_swiz(struct tgsi_full_src_register
* reg
)
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);
147 return reg
->SrcRegister
.SwizzleX
|
148 (reg
->SrcRegister
.SwizzleY
<< 3) |
149 (reg
->SrcRegister
.SwizzleZ
<< 6) |
150 (reg
->SrcRegister
.SwizzleW
<< 9);
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
,
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
);
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]));
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]));
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]));
190 static void r300_vs_instruction(struct r300_vertex_shader
* vs
,
191 struct r300_vs_asm
* assembler
,
192 struct tgsi_full_instruction
* inst
)
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
,
202 case TGSI_OPCODE_END
:
205 debug_printf("r300: vs: Bad opcode %d\n",
206 inst
->Instruction
.Opcode
);
211 void r300_translate_vertex_shader(struct r300_context
* r300
,
212 struct r300_vertex_shader
* vs
)
214 struct tgsi_parse_context parser
;
216 struct r300_constant_buffer
* consts
=
217 &r300
->shader_constants
[PIPE_SHADER_VERTEX
];
219 struct r300_vs_asm
* assembler
= CALLOC_STRUCT(r300_vs_asm
);
220 if (assembler
== NULL
) {
223 /* Setup starting offset for immediates. */
224 assembler
->imm_offset
= consts
->user_count
;
226 tgsi_parse_init(&parser
, vs
->state
.tokens
);
228 while (!tgsi_parse_end_of_tokens(&parser
)) {
229 tgsi_parse_token(&parser
);
231 /* This is seriously the lamest way to create fragment programs ever.
233 switch (parser
.FullToken
.Token
.Type
) {
234 case TGSI_TOKEN_TYPE_DECLARATION
:
235 /* Allocated registers sitting at the beginning
237 r300_vs_declare(assembler
, &parser
.FullToken
.FullDeclaration
);
239 case TGSI_TOKEN_TYPE_IMMEDIATE
:
240 debug_printf("r300: Emitting immediate to constant buffer, "
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
]
250 assembler
->imm_count
++;
252 case TGSI_TOKEN_TYPE_INSTRUCTION
:
253 r300_vs_instruction(vs
, assembler
,
254 &parser
.FullToken
.FullInstruction
);
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
);
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
);
268 tgsi_dump(vs
->state
.tokens
);
269 /* XXX finish r300 vertex shader dumper */
271 tgsi_parse_free(&parser
);