[D3DCOMPILER_43] Sync with Wine Staging 4.18. CORE-16441
[reactos.git] / dll / directx / wine / d3dcompiler_43 / asmparser.c
1 /*
2 * Direct3D asm shader parser
3 *
4 * Copyright 2008 Stefan Dösinger
5 * Copyright 2009 Matteo Bruni
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 *
21 */
22
23 #include "wine/debug.h"
24
25 #include "d3dcompiler_private.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
28 WINE_DECLARE_DEBUG_CHANNEL(parsed_shader);
29
30
31 /* How to map vs 1.0 and 2.0 varyings to 3.0 ones
32 * oTx is mapped to ox, which happens to be an
33 * identical mapping since BWRITERSPR_TEXCRDOUT == BWRITERSPR_OUTPUT
34 * oPos, oFog and point size are mapped to general output regs as well.
35 * the vs 1.x and 2.x parser functions add varying declarations
36 * to the shader, and the 1.x and 2.x output functions check those varyings
37 */
38 #define OT0_REG 0
39 #define OT1_REG 1
40 #define OT2_REG 2
41 #define OT3_REG 3
42 #define OT4_REG 4
43 #define OT5_REG 5
44 #define OT6_REG 6
45 #define OT7_REG 7
46 #define OPOS_REG 8
47 #define OFOG_REG 9
48 #define OFOG_WRITEMASK BWRITERSP_WRITEMASK_0
49 #define OPTS_REG 9
50 #define OPTS_WRITEMASK BWRITERSP_WRITEMASK_1
51 #define OD0_REG 10
52 #define OD1_REG 11
53
54 /* Input color registers 0-1 are identically mapped */
55 #define C0_VARYING 0
56 #define C1_VARYING 1
57 #define T0_VARYING 2
58 #define T1_VARYING 3
59 #define T2_VARYING 4
60 #define T3_VARYING 5
61 #define T4_VARYING 6
62 #define T5_VARYING 7
63 #define T6_VARYING 8
64 #define T7_VARYING 9
65
66 /****************************************************************
67 * Common(non-version specific) shader parser control code *
68 ****************************************************************/
69
70 static void asmparser_end(struct asm_parser *This) {
71 TRACE("Finalizing shader\n");
72 }
73
74 static void asmparser_constF(struct asm_parser *This, DWORD reg, float x, float y, float z, float w) {
75 if(!This->shader) return;
76 TRACE("Adding float constant %u at pos %u\n", reg, This->shader->num_cf);
77 TRACE_(parsed_shader)("def c%u, %f, %f, %f, %f\n", reg, x, y, z, w);
78 if(!add_constF(This->shader, reg, x, y, z, w)) {
79 ERR("Out of memory\n");
80 set_parse_status(&This->status, PARSE_ERR);
81 }
82 }
83
84 static void asmparser_constB(struct asm_parser *This, DWORD reg, BOOL x) {
85 if(!This->shader) return;
86 TRACE("Adding boolean constant %u at pos %u\n", reg, This->shader->num_cb);
87 TRACE_(parsed_shader)("def b%u, %s\n", reg, x ? "true" : "false");
88 if(!add_constB(This->shader, reg, x)) {
89 ERR("Out of memory\n");
90 set_parse_status(&This->status, PARSE_ERR);
91 }
92 }
93
94 static void asmparser_constI(struct asm_parser *This, DWORD reg, INT x, INT y, INT z, INT w) {
95 if(!This->shader) return;
96 TRACE("Adding integer constant %u at pos %u\n", reg, This->shader->num_ci);
97 TRACE_(parsed_shader)("def i%u, %d, %d, %d, %d\n", reg, x, y, z, w);
98 if(!add_constI(This->shader, reg, x, y, z, w)) {
99 ERR("Out of memory\n");
100 set_parse_status(&This->status, PARSE_ERR);
101 }
102 }
103
104 static void asmparser_dcl_output(struct asm_parser *This, DWORD usage, DWORD num,
105 const struct shader_reg *reg) {
106 if(!This->shader) return;
107 if(This->shader->type == ST_PIXEL) {
108 asmparser_message(This, "Line %u: Output register declared in a pixel shader\n", This->line_no);
109 set_parse_status(&This->status, PARSE_ERR);
110 }
111 if(!record_declaration(This->shader, usage, num, 0, TRUE, reg->regnum, reg->u.writemask, FALSE)) {
112 ERR("Out of memory\n");
113 set_parse_status(&This->status, PARSE_ERR);
114 }
115 }
116
117 static void asmparser_dcl_output_unsupported(struct asm_parser *This, DWORD usage, DWORD num,
118 const struct shader_reg *reg) {
119 asmparser_message(This, "Line %u: Output declaration unsupported in this shader version\n", This->line_no);
120 set_parse_status(&This->status, PARSE_ERR);
121 }
122
123 static void asmparser_dcl_input(struct asm_parser *This, DWORD usage, DWORD num,
124 DWORD mod, const struct shader_reg *reg) {
125 struct instruction instr;
126
127 if(!This->shader) return;
128 if(mod != 0 &&
129 (This->shader->version != BWRITERPS_VERSION(3, 0) ||
130 (mod != BWRITERSPDM_MSAMPCENTROID &&
131 mod != BWRITERSPDM_PARTIALPRECISION))) {
132 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
133 set_parse_status(&This->status, PARSE_ERR);
134 return;
135 }
136
137 /* Check register type and modifiers */
138 instr.dstmod = mod;
139 instr.shift = 0;
140 This->funcs->dstreg(This, &instr, reg);
141
142 if(!record_declaration(This->shader, usage, num, mod, FALSE, reg->regnum, reg->u.writemask, FALSE)) {
143 ERR("Out of memory\n");
144 set_parse_status(&This->status, PARSE_ERR);
145 }
146 }
147
148 static void asmparser_dcl_input_ps_2(struct asm_parser *This, DWORD usage, DWORD num,
149 DWORD mod, const struct shader_reg *reg) {
150 struct instruction instr;
151
152 if(!This->shader) return;
153 instr.dstmod = mod;
154 instr.shift = 0;
155 This->funcs->dstreg(This, &instr, reg);
156 if(!record_declaration(This->shader, usage, num, mod, FALSE, instr.dst.regnum, instr.dst.u.writemask, FALSE)) {
157 ERR("Out of memory\n");
158 set_parse_status(&This->status, PARSE_ERR);
159 }
160 }
161
162 static void asmparser_dcl_input_unsupported(struct asm_parser *This,
163 DWORD usage, DWORD num, DWORD mod, const struct shader_reg *reg)
164 {
165 asmparser_message(This, "Line %u: Input declaration unsupported in this shader version\n", This->line_no);
166 set_parse_status(&This->status, PARSE_ERR);
167 }
168
169 static void asmparser_dcl_sampler(struct asm_parser *This, DWORD samptype,
170 DWORD mod, DWORD regnum,
171 unsigned int line_no) {
172 if(!This->shader) return;
173 if(mod != 0 &&
174 (This->shader->version != BWRITERPS_VERSION(3, 0) ||
175 (mod != BWRITERSPDM_MSAMPCENTROID &&
176 mod != BWRITERSPDM_PARTIALPRECISION))) {
177 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
178 set_parse_status(&This->status, PARSE_ERR);
179 return;
180 }
181 if(!record_sampler(This->shader, samptype, mod, regnum)) {
182 ERR("Out of memory\n");
183 set_parse_status(&This->status, PARSE_ERR);
184 }
185 }
186
187 static void asmparser_dcl_sampler_unsupported(struct asm_parser *This,
188 DWORD samptype, DWORD mod, DWORD regnum, unsigned int line_no)
189 {
190 asmparser_message(This, "Line %u: Sampler declaration unsupported in this shader version\n", This->line_no);
191 set_parse_status(&This->status, PARSE_ERR);
192 }
193
194 static void asmparser_sincos(struct asm_parser *This, DWORD mod, DWORD shift,
195 const struct shader_reg *dst,
196 const struct src_regs *srcs) {
197 struct instruction *instr;
198
199 if(!srcs || srcs->count != 3) {
200 asmparser_message(This, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This->line_no);
201 set_parse_status(&This->status, PARSE_ERR);
202 return;
203 }
204
205 instr = alloc_instr(3);
206 if(!instr) {
207 ERR("Error allocating memory for the instruction\n");
208 set_parse_status(&This->status, PARSE_ERR);
209 return;
210 }
211
212 instr->opcode = BWRITERSIO_SINCOS;
213 instr->dstmod = mod;
214 instr->shift = shift;
215 instr->comptype = 0;
216
217 This->funcs->dstreg(This, instr, dst);
218 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
219 This->funcs->srcreg(This, instr, 1, &srcs->reg[1]);
220 This->funcs->srcreg(This, instr, 2, &srcs->reg[2]);
221
222 if(!add_instruction(This->shader, instr)) {
223 ERR("Out of memory\n");
224 set_parse_status(&This->status, PARSE_ERR);
225 }
226 }
227
228 static struct shader_reg map_oldps_register(const struct shader_reg *reg, BOOL tex_varying) {
229 struct shader_reg ret;
230 switch(reg->type) {
231 case BWRITERSPR_TEXTURE:
232 if(tex_varying) {
233 ret = *reg;
234 ret.type = BWRITERSPR_INPUT;
235 switch(reg->regnum) {
236 case 0: ret.regnum = T0_VARYING; break;
237 case 1: ret.regnum = T1_VARYING; break;
238 case 2: ret.regnum = T2_VARYING; break;
239 case 3: ret.regnum = T3_VARYING; break;
240 case 4: ret.regnum = T4_VARYING; break;
241 case 5: ret.regnum = T5_VARYING; break;
242 case 6: ret.regnum = T6_VARYING; break;
243 case 7: ret.regnum = T7_VARYING; break;
244 default:
245 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
246 return *reg;
247 }
248 return ret;
249 } else {
250 ret = *reg;
251 ret.type = BWRITERSPR_TEMP;
252 switch(reg->regnum) {
253 case 0: ret.regnum = T0_REG; break;
254 case 1: ret.regnum = T1_REG; break;
255 case 2: ret.regnum = T2_REG; break;
256 case 3: ret.regnum = T3_REG; break;
257 default:
258 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
259 return *reg;
260 }
261 return ret;
262 }
263
264 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
265 to 3.0 ones */
266
267 default: return *reg;
268 }
269 }
270
271 static void asmparser_texcoord(struct asm_parser *This, DWORD mod, DWORD shift,
272 const struct shader_reg *dst,
273 const struct src_regs *srcs) {
274 struct instruction *instr;
275
276 if(srcs) {
277 asmparser_message(This, "Line %u: Source registers in texcoord instruction\n", This->line_no);
278 set_parse_status(&This->status, PARSE_ERR);
279 return;
280 }
281
282 instr = alloc_instr(1);
283 if(!instr) {
284 ERR("Error allocating memory for the instruction\n");
285 set_parse_status(&This->status, PARSE_ERR);
286 return;
287 }
288
289 /* texcoord copies the texture coord data into a temporary register-like
290 * readable form. In newer shader models this equals a MOV from v0 to r0,
291 * record it as this.
292 */
293 instr->opcode = BWRITERSIO_MOV;
294 instr->dstmod = mod | BWRITERSPDM_SATURATE; /* texcoord clamps to [0;1] */
295 instr->shift = shift;
296 instr->comptype = 0;
297
298 This->funcs->dstreg(This, instr, dst);
299 /* The src reg needs special care */
300 instr->src[0] = map_oldps_register(dst, TRUE);
301
302 if(!add_instruction(This->shader, instr)) {
303 ERR("Out of memory\n");
304 set_parse_status(&This->status, PARSE_ERR);
305 }
306 }
307
308 static void asmparser_texcrd(struct asm_parser *This, DWORD mod, DWORD shift,
309 const struct shader_reg *dst,
310 const struct src_regs *srcs) {
311 struct instruction *instr;
312
313 if(!srcs || srcs->count != 1) {
314 asmparser_message(This, "Line %u: Wrong number of source registers in texcrd instruction\n", This->line_no);
315 set_parse_status(&This->status, PARSE_ERR);
316 return;
317 }
318
319 instr = alloc_instr(1);
320 if(!instr) {
321 ERR("Error allocating memory for the instruction\n");
322 set_parse_status(&This->status, PARSE_ERR);
323 return;
324 }
325
326 /* The job of texcrd is done by mov in later shader versions */
327 instr->opcode = BWRITERSIO_MOV;
328 instr->dstmod = mod;
329 instr->shift = shift;
330 instr->comptype = 0;
331
332 This->funcs->dstreg(This, instr, dst);
333 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
334
335 if(!add_instruction(This->shader, instr)) {
336 ERR("Out of memory\n");
337 set_parse_status(&This->status, PARSE_ERR);
338 }
339 }
340
341 static void asmparser_texkill(struct asm_parser *This,
342 const struct shader_reg *dst) {
343 struct instruction *instr = alloc_instr(0);
344
345 if(!instr) {
346 ERR("Error allocating memory for the instruction\n");
347 set_parse_status(&This->status, PARSE_ERR);
348 return;
349 }
350
351 instr->opcode = BWRITERSIO_TEXKILL;
352 instr->dstmod = 0;
353 instr->shift = 0;
354 instr->comptype = 0;
355
356 /* Do not run the dst register through the normal
357 * register conversion. If used with ps_1_0 to ps_1_3
358 * the texture coordinate from that register is used,
359 * not the temporary register value. In ps_1_4 and
360 * ps_2_0 t0 is always a varying and temporaries can
361 * be used with texkill.
362 */
363 instr->dst = map_oldps_register(dst, TRUE);
364 instr->has_dst = TRUE;
365
366 if(!add_instruction(This->shader, instr)) {
367 ERR("Out of memory\n");
368 set_parse_status(&This->status, PARSE_ERR);
369 }
370 }
371
372 static void asmparser_texhelper(struct asm_parser *This, DWORD mod, DWORD shift,
373 const struct shader_reg *dst,
374 const struct shader_reg *src0) {
375 struct instruction *instr = alloc_instr(2);
376
377 if(!instr) {
378 ERR("Error allocating memory for the instruction\n");
379 set_parse_status(&This->status, PARSE_ERR);
380 return;
381 }
382
383 instr->opcode = BWRITERSIO_TEX;
384 instr->dstmod = mod;
385 instr->shift = shift;
386 instr->comptype = 0;
387 /* The dest register can be mapped normally to a temporary register */
388 This->funcs->dstreg(This, instr, dst);
389 /* Use the src passed as parameter by the specific instruction handler */
390 instr->src[0] = *src0;
391
392 /* The 2nd source register is the sampler register with the
393 * destination's regnum
394 */
395 ZeroMemory(&instr->src[1], sizeof(instr->src[1]));
396 instr->src[1].type = BWRITERSPR_SAMPLER;
397 instr->src[1].regnum = dst->regnum;
398 instr->src[1].u.swizzle = BWRITERVS_NOSWIZZLE;
399 instr->src[1].srcmod = BWRITERSPSM_NONE;
400 instr->src[1].rel_reg = NULL;
401
402 if(!add_instruction(This->shader, instr)) {
403 ERR("Out of memory\n");
404 set_parse_status(&This->status, PARSE_ERR);
405 }
406 }
407
408 static void asmparser_tex(struct asm_parser *This, DWORD mod, DWORD shift,
409 const struct shader_reg *dst) {
410 struct shader_reg src;
411
412 /* The first source register is the varying containing the coordinate */
413 src = map_oldps_register(dst, TRUE);
414 asmparser_texhelper(This, mod, shift, dst, &src);
415 }
416
417 static void asmparser_texld14(struct asm_parser *This, DWORD mod, DWORD shift,
418 const struct shader_reg *dst,
419 const struct src_regs *srcs) {
420 struct instruction *instr;
421
422 if(!srcs || srcs->count != 1) {
423 asmparser_message(This, "Line %u: texld (PS 1.4) has a wrong number of source registers\n", This->line_no);
424 set_parse_status(&This->status, PARSE_ERR);
425 return;
426 }
427
428 instr = alloc_instr(2);
429 if(!instr) {
430 ERR("Error allocating memory for the instruction\n");
431 set_parse_status(&This->status, PARSE_ERR);
432 return;
433 }
434
435 /* This code is recording a texld instruction, not tex. However,
436 * texld borrows the opcode of tex
437 */
438 instr->opcode = BWRITERSIO_TEX;
439 instr->dstmod = mod;
440 instr->shift = shift;
441 instr->comptype = 0;
442
443 This->funcs->dstreg(This, instr, dst);
444 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
445
446 /* The 2nd source register is the sampler register with the
447 * destination's regnum
448 */
449 ZeroMemory(&instr->src[1], sizeof(instr->src[1]));
450 instr->src[1].type = BWRITERSPR_SAMPLER;
451 instr->src[1].regnum = dst->regnum;
452 instr->src[1].u.swizzle = BWRITERVS_NOSWIZZLE;
453 instr->src[1].srcmod = BWRITERSPSM_NONE;
454 instr->src[1].rel_reg = NULL;
455
456 if(!add_instruction(This->shader, instr)) {
457 ERR("Out of memory\n");
458 set_parse_status(&This->status, PARSE_ERR);
459 }
460 }
461
462 static void asmparser_texreg2ar(struct asm_parser *This, DWORD mod, DWORD shift,
463 const struct shader_reg *dst,
464 const struct shader_reg *src0) {
465 struct shader_reg src;
466
467 src = map_oldps_register(src0, FALSE);
468 /* Supply the correct swizzle */
469 src.u.swizzle = BWRITERVS_X_W | BWRITERVS_Y_X | BWRITERVS_Z_X | BWRITERVS_W_X;
470 asmparser_texhelper(This, mod, shift, dst, &src);
471 }
472
473 static void asmparser_texreg2gb(struct asm_parser *This, DWORD mod, DWORD shift,
474 const struct shader_reg *dst,
475 const struct shader_reg *src0) {
476 struct shader_reg src;
477
478 src = map_oldps_register(src0, FALSE);
479 /* Supply the correct swizzle */
480 src.u.swizzle = BWRITERVS_X_Y | BWRITERVS_Y_Z | BWRITERVS_Z_Z | BWRITERVS_W_Z;
481 asmparser_texhelper(This, mod, shift, dst, &src);
482 }
483
484 static void asmparser_texreg2rgb(struct asm_parser *This, DWORD mod, DWORD shift,
485 const struct shader_reg *dst,
486 const struct shader_reg *src0) {
487 struct shader_reg src;
488
489 src = map_oldps_register(src0, FALSE);
490 /* Supply the correct swizzle */
491 src.u.swizzle = BWRITERVS_X_X | BWRITERVS_Y_Y | BWRITERVS_Z_Z | BWRITERVS_W_Z;
492 asmparser_texhelper(This, mod, shift, dst, &src);
493 }
494
495 /* Complex pixel shader 1.3 instructions like texm3x3tex are tricky - the
496 * bytecode writer works instruction by instruction, so we can't properly
497 * convert these from/to equivalent ps_3_0 instructions. Then simply keep using
498 * the ps_1_3 opcodes and just adapt the registers in the common fashion (i.e.
499 * go through asmparser_instr).
500 */
501
502 static void asmparser_instr(struct asm_parser *This, DWORD opcode, DWORD mod, DWORD shift,
503 enum bwriter_comparison_type comp, const struct shader_reg *dst,
504 const struct src_regs *srcs, int expectednsrcs)
505 {
506 struct instruction *instr;
507 unsigned int i;
508 BOOL firstreg = TRUE;
509 unsigned int src_count = srcs ? srcs->count : 0;
510
511 if(!This->shader) return;
512
513 TRACE_(parsed_shader)("%s%s%s%s ", debug_print_opcode(opcode),
514 debug_print_dstmod(mod),
515 debug_print_shift(shift),
516 debug_print_comp(comp));
517 if(dst) {
518 TRACE_(parsed_shader)("%s", debug_print_dstreg(dst));
519 firstreg = FALSE;
520 }
521 for(i = 0; i < src_count; i++) {
522 if(!firstreg) TRACE_(parsed_shader)(", ");
523 else firstreg = FALSE;
524 TRACE_(parsed_shader)("%s", debug_print_srcreg(&srcs->reg[i]));
525 }
526 TRACE_(parsed_shader)("\n");
527
528 /* Check for instructions with different syntaxes in different shader versions */
529 switch(opcode) {
530 case BWRITERSIO_SINCOS:
531 /* The syntax changes between vs 2 and the other shader versions */
532 if(This->shader->version == BWRITERVS_VERSION(2, 0) ||
533 This->shader->version == BWRITERVS_VERSION(2, 1)) {
534 asmparser_sincos(This, mod, shift, dst, srcs);
535 return;
536 }
537 /* Use the default handling */
538 break;
539 case BWRITERSIO_TEXCOORD:
540 /* texcoord/texcrd are two instructions present only in PS <= 1.3 and PS 1.4 respectively */
541 if(This->shader->version == BWRITERPS_VERSION(1, 4))
542 asmparser_texcrd(This, mod, shift, dst, srcs);
543 else asmparser_texcoord(This, mod, shift, dst, srcs);
544 return;
545 case BWRITERSIO_TEX:
546 /* this encodes both the tex PS 1.x instruction and the
547 texld 1.4/2.0+ instruction */
548 if(This->shader->version == BWRITERPS_VERSION(1, 0) ||
549 This->shader->version == BWRITERPS_VERSION(1, 1) ||
550 This->shader->version == BWRITERPS_VERSION(1, 2) ||
551 This->shader->version == BWRITERPS_VERSION(1, 3)) {
552 asmparser_tex(This, mod, shift, dst);
553 return;
554 }
555 else if(This->shader->version == BWRITERPS_VERSION(1, 4)) {
556 asmparser_texld14(This, mod, shift, dst, srcs);
557 return;
558 }
559 /* else fallback to the standard behavior */
560 break;
561 }
562
563 if(src_count != expectednsrcs) {
564 asmparser_message(This, "Line %u: Wrong number of source registers\n", This->line_no);
565 set_parse_status(&This->status, PARSE_ERR);
566 return;
567 }
568
569 /* Handle PS 1.x instructions, "regularizing" them */
570 switch(opcode) {
571 case BWRITERSIO_TEXKILL:
572 asmparser_texkill(This, dst);
573 return;
574 case BWRITERSIO_TEXREG2AR:
575 asmparser_texreg2ar(This, mod, shift, dst, &srcs->reg[0]);
576 return;
577 case BWRITERSIO_TEXREG2GB:
578 asmparser_texreg2gb(This, mod, shift, dst, &srcs->reg[0]);
579 return;
580 case BWRITERSIO_TEXREG2RGB:
581 asmparser_texreg2rgb(This, mod, shift, dst, &srcs->reg[0]);
582 return;
583 }
584
585 instr = alloc_instr(src_count);
586 if(!instr) {
587 ERR("Error allocating memory for the instruction\n");
588 set_parse_status(&This->status, PARSE_ERR);
589 return;
590 }
591
592 instr->opcode = opcode;
593 instr->dstmod = mod;
594 instr->shift = shift;
595 instr->comptype = comp;
596 if(dst) This->funcs->dstreg(This, instr, dst);
597 for(i = 0; i < src_count; i++) {
598 This->funcs->srcreg(This, instr, i, &srcs->reg[i]);
599 }
600
601 if(!add_instruction(This->shader, instr)) {
602 ERR("Out of memory\n");
603 set_parse_status(&This->status, PARSE_ERR);
604 }
605 }
606
607 static struct shader_reg map_oldvs_register(const struct shader_reg *reg) {
608 struct shader_reg ret;
609 switch(reg->type) {
610 case BWRITERSPR_RASTOUT:
611 ret = *reg;
612 ret.type = BWRITERSPR_OUTPUT;
613 switch(reg->regnum) {
614 case BWRITERSRO_POSITION:
615 ret.regnum = OPOS_REG;
616 break;
617 case BWRITERSRO_FOG:
618 ret.regnum = OFOG_REG;
619 ret.u.writemask = OFOG_WRITEMASK;
620 break;
621 case BWRITERSRO_POINT_SIZE:
622 ret.regnum = OPTS_REG;
623 ret.u.writemask = OPTS_WRITEMASK;
624 break;
625 default:
626 FIXME("Unhandled RASTOUT register %u\n", reg->regnum);
627 return *reg;
628 }
629 return ret;
630
631 case BWRITERSPR_TEXCRDOUT:
632 ret = *reg;
633 ret.type = BWRITERSPR_OUTPUT;
634 switch(reg->regnum) {
635 case 0: ret.regnum = OT0_REG; break;
636 case 1: ret.regnum = OT1_REG; break;
637 case 2: ret.regnum = OT2_REG; break;
638 case 3: ret.regnum = OT3_REG; break;
639 case 4: ret.regnum = OT4_REG; break;
640 case 5: ret.regnum = OT5_REG; break;
641 case 6: ret.regnum = OT6_REG; break;
642 case 7: ret.regnum = OT7_REG; break;
643 default:
644 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg->regnum);
645 return *reg;
646 }
647 return ret;
648
649 case BWRITERSPR_ATTROUT:
650 ret = *reg;
651 ret.type = BWRITERSPR_OUTPUT;
652 switch(reg->regnum) {
653 case 0: ret.regnum = OD0_REG; break;
654 case 1: ret.regnum = OD1_REG; break;
655 default:
656 FIXME("Unhandled ATTROUT regnum %u\n", reg->regnum);
657 return *reg;
658 }
659 return ret;
660
661 default: return *reg;
662 }
663 }
664
665 /* Checks for unsupported source modifiers in VS (all versions) or
666 PS 2.0 and newer */
667 static void check_legacy_srcmod(struct asm_parser *This, DWORD srcmod) {
668 if(srcmod == BWRITERSPSM_BIAS || srcmod == BWRITERSPSM_BIASNEG ||
669 srcmod == BWRITERSPSM_SIGN || srcmod == BWRITERSPSM_SIGNNEG ||
670 srcmod == BWRITERSPSM_COMP || srcmod == BWRITERSPSM_X2 ||
671 srcmod == BWRITERSPSM_X2NEG || srcmod == BWRITERSPSM_DZ ||
672 srcmod == BWRITERSPSM_DW) {
673 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
674 This->line_no,
675 debug_print_srcmod(srcmod));
676 set_parse_status(&This->status, PARSE_ERR);
677 }
678 }
679
680 static void check_abs_srcmod(struct asm_parser *This, DWORD srcmod) {
681 if(srcmod == BWRITERSPSM_ABS || srcmod == BWRITERSPSM_ABSNEG) {
682 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
683 This->line_no,
684 debug_print_srcmod(srcmod));
685 set_parse_status(&This->status, PARSE_ERR);
686 }
687 }
688
689 static void check_loop_swizzle(struct asm_parser *This,
690 const struct shader_reg *src) {
691 if((src->type == BWRITERSPR_LOOP && src->u.swizzle != BWRITERVS_NOSWIZZLE) ||
692 (src->rel_reg && src->rel_reg->type == BWRITERSPR_LOOP &&
693 src->rel_reg->u.swizzle != BWRITERVS_NOSWIZZLE)) {
694 asmparser_message(This, "Line %u: Swizzle not allowed on aL register\n", This->line_no);
695 set_parse_status(&This->status, PARSE_ERR);
696 }
697 }
698
699 static void check_shift_dstmod(struct asm_parser *This, DWORD shift) {
700 if(shift != 0) {
701 asmparser_message(This, "Line %u: Shift modifiers not supported in this shader version\n",
702 This->line_no);
703 set_parse_status(&This->status, PARSE_ERR);
704 }
705 }
706
707 static void check_ps_dstmod(struct asm_parser *This, DWORD dstmod) {
708 if(dstmod == BWRITERSPDM_PARTIALPRECISION ||
709 dstmod == BWRITERSPDM_MSAMPCENTROID) {
710 asmparser_message(This, "Line %u: Instruction modifier %s not supported in this shader version\n",
711 This->line_no,
712 debug_print_dstmod(dstmod));
713 set_parse_status(&This->status, PARSE_ERR);
714 }
715 }
716
717 struct allowed_reg_type {
718 DWORD type;
719 DWORD count;
720 BOOL reladdr;
721 };
722
723 static BOOL check_reg_type(const struct shader_reg *reg,
724 const struct allowed_reg_type *allowed) {
725 unsigned int i = 0;
726
727 while(allowed[i].type != ~0U) {
728 if(reg->type == allowed[i].type) {
729 if(reg->rel_reg) {
730 if(allowed[i].reladdr)
731 return TRUE; /* The relative addressing register
732 can have a negative value, we
733 can't check the register index */
734 return FALSE;
735 }
736 if(reg->regnum < allowed[i].count) return TRUE;
737 return FALSE;
738 }
739 i++;
740 }
741 return FALSE;
742 }
743
744 /* Native assembler doesn't do separate checks for src and dst registers */
745 static const struct allowed_reg_type vs_1_reg_allowed[] = {
746 { BWRITERSPR_TEMP, 12, FALSE },
747 { BWRITERSPR_INPUT, 16, FALSE },
748 { BWRITERSPR_CONST, ~0U, TRUE },
749 { BWRITERSPR_ADDR, 1, FALSE },
750 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
751 { BWRITERSPR_ATTROUT, 2, FALSE },
752 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
753 { ~0U, 0 } /* End tag */
754 };
755
756 /* struct instruction *asmparser_srcreg
757 *
758 * Records a source register in the instruction and does shader version
759 * specific checks and modifications on it
760 *
761 * Parameters:
762 * This: Shader parser instance
763 * instr: instruction to store the register in
764 * num: Number of source register
765 * src: Pointer to source the register structure. The caller can free
766 * it afterwards
767 */
768 static void asmparser_srcreg_vs_1(struct asm_parser *This,
769 struct instruction *instr, int num,
770 const struct shader_reg *src) {
771 struct shader_reg reg;
772
773 if(!check_reg_type(src, vs_1_reg_allowed)) {
774 asmparser_message(This, "Line %u: Source register %s not supported in VS 1\n",
775 This->line_no,
776 debug_print_srcreg(src));
777 set_parse_status(&This->status, PARSE_ERR);
778 }
779 check_legacy_srcmod(This, src->srcmod);
780 check_abs_srcmod(This, src->srcmod);
781 reg = map_oldvs_register(src);
782 instr->src[num] = reg;
783 }
784
785 static const struct allowed_reg_type vs_2_reg_allowed[] = {
786 { BWRITERSPR_TEMP, 12, FALSE },
787 { BWRITERSPR_INPUT, 16, FALSE },
788 { BWRITERSPR_CONST, ~0U, TRUE },
789 { BWRITERSPR_ADDR, 1, FALSE },
790 { BWRITERSPR_CONSTBOOL, 16, FALSE },
791 { BWRITERSPR_CONSTINT, 16, FALSE },
792 { BWRITERSPR_LOOP, 1, FALSE },
793 { BWRITERSPR_LABEL, 2048, FALSE },
794 { BWRITERSPR_PREDICATE, 1, FALSE },
795 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
796 { BWRITERSPR_ATTROUT, 2, FALSE },
797 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
798 { ~0U, 0 } /* End tag */
799 };
800
801 static void asmparser_srcreg_vs_2(struct asm_parser *This,
802 struct instruction *instr, int num,
803 const struct shader_reg *src) {
804 struct shader_reg reg;
805
806 if(!check_reg_type(src, vs_2_reg_allowed)) {
807 asmparser_message(This, "Line %u: Source register %s not supported in VS 2\n",
808 This->line_no,
809 debug_print_srcreg(src));
810 set_parse_status(&This->status, PARSE_ERR);
811 }
812 check_loop_swizzle(This, src);
813 check_legacy_srcmod(This, src->srcmod);
814 check_abs_srcmod(This, src->srcmod);
815 reg = map_oldvs_register(src);
816 instr->src[num] = reg;
817 }
818
819 static const struct allowed_reg_type vs_3_reg_allowed[] = {
820 { BWRITERSPR_TEMP, 32, FALSE },
821 { BWRITERSPR_INPUT, 16, TRUE },
822 { BWRITERSPR_CONST, ~0U, TRUE },
823 { BWRITERSPR_ADDR, 1, FALSE },
824 { BWRITERSPR_CONSTBOOL, 16, FALSE },
825 { BWRITERSPR_CONSTINT, 16, FALSE },
826 { BWRITERSPR_LOOP, 1, FALSE },
827 { BWRITERSPR_LABEL, 2048, FALSE },
828 { BWRITERSPR_PREDICATE, 1, FALSE },
829 { BWRITERSPR_SAMPLER, 4, FALSE },
830 { BWRITERSPR_OUTPUT, 12, TRUE },
831 { ~0U, 0 } /* End tag */
832 };
833
834 static void asmparser_srcreg_vs_3(struct asm_parser *This,
835 struct instruction *instr, int num,
836 const struct shader_reg *src) {
837 if(!check_reg_type(src, vs_3_reg_allowed)) {
838 asmparser_message(This, "Line %u: Source register %s not supported in VS 3.0\n",
839 This->line_no,
840 debug_print_srcreg(src));
841 set_parse_status(&This->status, PARSE_ERR);
842 }
843 check_loop_swizzle(This, src);
844 check_legacy_srcmod(This, src->srcmod);
845 instr->src[num] = *src;
846 }
847
848 static const struct allowed_reg_type ps_1_0123_reg_allowed[] = {
849 { BWRITERSPR_CONST, 8, FALSE },
850 { BWRITERSPR_TEMP, 2, FALSE },
851 { BWRITERSPR_TEXTURE, 4, FALSE },
852 { BWRITERSPR_INPUT, 2, FALSE },
853 { ~0U, 0 } /* End tag */
854 };
855
856 static void asmparser_srcreg_ps_1_0123(struct asm_parser *This,
857 struct instruction *instr, int num,
858 const struct shader_reg *src) {
859 struct shader_reg reg;
860
861 if(!check_reg_type(src, ps_1_0123_reg_allowed)) {
862 asmparser_message(This, "Line %u: Source register %s not supported in <== PS 1.3\n",
863 This->line_no,
864 debug_print_srcreg(src));
865 set_parse_status(&This->status, PARSE_ERR);
866 }
867 check_abs_srcmod(This, src->srcmod);
868 reg = map_oldps_register(src, FALSE);
869 instr->src[num] = reg;
870 }
871
872 static const struct allowed_reg_type ps_1_4_reg_allowed[] = {
873 { BWRITERSPR_CONST, 8, FALSE },
874 { BWRITERSPR_TEMP, 6, FALSE },
875 { BWRITERSPR_TEXTURE, 6, FALSE },
876 { BWRITERSPR_INPUT, 2, FALSE },
877 { ~0U, 0 } /* End tag */
878 };
879
880 static void asmparser_srcreg_ps_1_4(struct asm_parser *This,
881 struct instruction *instr, int num,
882 const struct shader_reg *src) {
883 struct shader_reg reg;
884
885 if(!check_reg_type(src, ps_1_4_reg_allowed)) {
886 asmparser_message(This, "Line %u: Source register %s not supported in PS 1.4\n",
887 This->line_no,
888 debug_print_srcreg(src));
889 set_parse_status(&This->status, PARSE_ERR);
890 }
891 check_abs_srcmod(This, src->srcmod);
892 reg = map_oldps_register(src, TRUE);
893 instr->src[num] = reg;
894 }
895
896 static const struct allowed_reg_type ps_2_0_reg_allowed[] = {
897 { BWRITERSPR_INPUT, 2, FALSE },
898 { BWRITERSPR_TEMP, 32, FALSE },
899 { BWRITERSPR_CONST, 32, FALSE },
900 { BWRITERSPR_CONSTINT, 16, FALSE },
901 { BWRITERSPR_CONSTBOOL, 16, FALSE },
902 { BWRITERSPR_SAMPLER, 16, FALSE },
903 { BWRITERSPR_TEXTURE, 8, FALSE },
904 { BWRITERSPR_COLOROUT, 4, FALSE },
905 { BWRITERSPR_DEPTHOUT, 1, FALSE },
906 { ~0U, 0 } /* End tag */
907 };
908
909 static void asmparser_srcreg_ps_2(struct asm_parser *This,
910 struct instruction *instr, int num,
911 const struct shader_reg *src) {
912 struct shader_reg reg;
913
914 if(!check_reg_type(src, ps_2_0_reg_allowed)) {
915 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.0\n",
916 This->line_no,
917 debug_print_srcreg(src));
918 set_parse_status(&This->status, PARSE_ERR);
919 }
920 check_legacy_srcmod(This, src->srcmod);
921 check_abs_srcmod(This, src->srcmod);
922 reg = map_oldps_register(src, TRUE);
923 instr->src[num] = reg;
924 }
925
926 static const struct allowed_reg_type ps_2_x_reg_allowed[] = {
927 { BWRITERSPR_INPUT, 2, FALSE },
928 { BWRITERSPR_TEMP, 32, FALSE },
929 { BWRITERSPR_CONST, 32, FALSE },
930 { BWRITERSPR_CONSTINT, 16, FALSE },
931 { BWRITERSPR_CONSTBOOL, 16, FALSE },
932 { BWRITERSPR_PREDICATE, 1, FALSE },
933 { BWRITERSPR_SAMPLER, 16, FALSE },
934 { BWRITERSPR_TEXTURE, 8, FALSE },
935 { BWRITERSPR_LABEL, 2048, FALSE },
936 { BWRITERSPR_COLOROUT, 4, FALSE },
937 { BWRITERSPR_DEPTHOUT, 1, FALSE },
938 { ~0U, 0 } /* End tag */
939 };
940
941 static void asmparser_srcreg_ps_2_x(struct asm_parser *This,
942 struct instruction *instr, int num,
943 const struct shader_reg *src) {
944 struct shader_reg reg;
945
946 if(!check_reg_type(src, ps_2_x_reg_allowed)) {
947 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.x\n",
948 This->line_no,
949 debug_print_srcreg(src));
950 set_parse_status(&This->status, PARSE_ERR);
951 }
952 check_legacy_srcmod(This, src->srcmod);
953 check_abs_srcmod(This, src->srcmod);
954 reg = map_oldps_register(src, TRUE);
955 instr->src[num] = reg;
956 }
957
958 static const struct allowed_reg_type ps_3_reg_allowed[] = {
959 { BWRITERSPR_INPUT, 10, TRUE },
960 { BWRITERSPR_TEMP, 32, FALSE },
961 { BWRITERSPR_CONST, 224, FALSE },
962 { BWRITERSPR_CONSTINT, 16, FALSE },
963 { BWRITERSPR_CONSTBOOL, 16, FALSE },
964 { BWRITERSPR_PREDICATE, 1, FALSE },
965 { BWRITERSPR_SAMPLER, 16, FALSE },
966 { BWRITERSPR_MISCTYPE, 2, FALSE }, /* vPos and vFace */
967 { BWRITERSPR_LOOP, 1, FALSE },
968 { BWRITERSPR_LABEL, 2048, FALSE },
969 { BWRITERSPR_COLOROUT, 4, FALSE },
970 { BWRITERSPR_DEPTHOUT, 1, FALSE },
971 { ~0U, 0 } /* End tag */
972 };
973
974 static void asmparser_srcreg_ps_3(struct asm_parser *This,
975 struct instruction *instr, int num,
976 const struct shader_reg *src) {
977 if(!check_reg_type(src, ps_3_reg_allowed)) {
978 asmparser_message(This, "Line %u: Source register %s not supported in PS 3.0\n",
979 This->line_no,
980 debug_print_srcreg(src));
981 set_parse_status(&This->status, PARSE_ERR);
982 }
983 check_loop_swizzle(This, src);
984 check_legacy_srcmod(This, src->srcmod);
985 instr->src[num] = *src;
986 }
987
988 static void asmparser_dstreg_vs_1(struct asm_parser *This,
989 struct instruction *instr,
990 const struct shader_reg *dst) {
991 struct shader_reg reg;
992
993 if(!check_reg_type(dst, vs_1_reg_allowed)) {
994 asmparser_message(This, "Line %u: Destination register %s not supported in VS 1\n",
995 This->line_no,
996 debug_print_dstreg(dst));
997 set_parse_status(&This->status, PARSE_ERR);
998 }
999 check_ps_dstmod(This, instr->dstmod);
1000 check_shift_dstmod(This, instr->shift);
1001 reg = map_oldvs_register(dst);
1002 instr->dst = reg;
1003 instr->has_dst = TRUE;
1004 }
1005
1006 static void asmparser_dstreg_vs_2(struct asm_parser *This,
1007 struct instruction *instr,
1008 const struct shader_reg *dst) {
1009 struct shader_reg reg;
1010
1011 if(!check_reg_type(dst, vs_2_reg_allowed)) {
1012 asmparser_message(This, "Line %u: Destination register %s not supported in VS 2.0\n",
1013 This->line_no,
1014 debug_print_dstreg(dst));
1015 set_parse_status(&This->status, PARSE_ERR);
1016 }
1017 check_ps_dstmod(This, instr->dstmod);
1018 check_shift_dstmod(This, instr->shift);
1019 reg = map_oldvs_register(dst);
1020 instr->dst = reg;
1021 instr->has_dst = TRUE;
1022 }
1023
1024 static void asmparser_dstreg_vs_3(struct asm_parser *This,
1025 struct instruction *instr,
1026 const struct shader_reg *dst) {
1027 if(!check_reg_type(dst, vs_3_reg_allowed)) {
1028 asmparser_message(This, "Line %u: Destination register %s not supported in VS 3.0\n",
1029 This->line_no,
1030 debug_print_dstreg(dst));
1031 set_parse_status(&This->status, PARSE_ERR);
1032 }
1033 check_ps_dstmod(This, instr->dstmod);
1034 check_shift_dstmod(This, instr->shift);
1035 instr->dst = *dst;
1036 instr->has_dst = TRUE;
1037 }
1038
1039 static void asmparser_dstreg_ps_1_0123(struct asm_parser *This,
1040 struct instruction *instr,
1041 const struct shader_reg *dst) {
1042 struct shader_reg reg;
1043
1044 if(!check_reg_type(dst, ps_1_0123_reg_allowed)) {
1045 asmparser_message(This, "Line %u: Destination register %s not supported in PS 1\n",
1046 This->line_no,
1047 debug_print_dstreg(dst));
1048 set_parse_status(&This->status, PARSE_ERR);
1049 }
1050 reg = map_oldps_register(dst, FALSE);
1051 instr->dst = reg;
1052 instr->has_dst = TRUE;
1053 }
1054
1055 static void asmparser_dstreg_ps_1_4(struct asm_parser *This,
1056 struct instruction *instr,
1057 const struct shader_reg *dst) {
1058 struct shader_reg reg;
1059
1060 if(!check_reg_type(dst, ps_1_4_reg_allowed)) {
1061 asmparser_message(This, "Line %u: Destination register %s not supported in PS 1\n",
1062 This->line_no,
1063 debug_print_dstreg(dst));
1064 set_parse_status(&This->status, PARSE_ERR);
1065 }
1066 reg = map_oldps_register(dst, TRUE);
1067 instr->dst = reg;
1068 instr->has_dst = TRUE;
1069 }
1070
1071 static void asmparser_dstreg_ps_2(struct asm_parser *This,
1072 struct instruction *instr,
1073 const struct shader_reg *dst) {
1074 struct shader_reg reg;
1075
1076 if(!check_reg_type(dst, ps_2_0_reg_allowed)) {
1077 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.0\n",
1078 This->line_no,
1079 debug_print_dstreg(dst));
1080 set_parse_status(&This->status, PARSE_ERR);
1081 }
1082 check_shift_dstmod(This, instr->shift);
1083 reg = map_oldps_register(dst, TRUE);
1084 instr->dst = reg;
1085 instr->has_dst = TRUE;
1086 }
1087
1088 static void asmparser_dstreg_ps_2_x(struct asm_parser *This,
1089 struct instruction *instr,
1090 const struct shader_reg *dst) {
1091 struct shader_reg reg;
1092
1093 if(!check_reg_type(dst, ps_2_x_reg_allowed)) {
1094 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.x\n",
1095 This->line_no,
1096 debug_print_dstreg(dst));
1097 set_parse_status(&This->status, PARSE_ERR);
1098 }
1099 check_shift_dstmod(This, instr->shift);
1100 reg = map_oldps_register(dst, TRUE);
1101 instr->dst = reg;
1102 instr->has_dst = TRUE;
1103 }
1104
1105 static void asmparser_dstreg_ps_3(struct asm_parser *This,
1106 struct instruction *instr,
1107 const struct shader_reg *dst) {
1108 if(!check_reg_type(dst, ps_3_reg_allowed)) {
1109 asmparser_message(This, "Line %u: Destination register %s not supported in PS 3.0\n",
1110 This->line_no,
1111 debug_print_dstreg(dst));
1112 set_parse_status(&This->status, PARSE_ERR);
1113 }
1114 check_shift_dstmod(This, instr->shift);
1115 instr->dst = *dst;
1116 instr->has_dst = TRUE;
1117 }
1118
1119 static void asmparser_predicate_supported(struct asm_parser *This,
1120 const struct shader_reg *predicate) {
1121 /* this sets the predicate of the last instruction added to the shader */
1122 if(!This->shader) return;
1123 if(This->shader->num_instrs == 0) ERR("Predicate without an instruction\n");
1124 This->shader->instr[This->shader->num_instrs - 1]->has_predicate = TRUE;
1125 This->shader->instr[This->shader->num_instrs - 1]->predicate = *predicate;
1126 }
1127
1128 static void asmparser_predicate_unsupported(struct asm_parser *This,
1129 const struct shader_reg *predicate) {
1130 asmparser_message(This, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This->line_no);
1131 set_parse_status(&This->status, PARSE_ERR);
1132 }
1133
1134 static void asmparser_coissue_supported(struct asm_parser *This) {
1135 /* this sets the coissue flag of the last instruction added to the shader */
1136 if(!This->shader) return;
1137 if(This->shader->num_instrs == 0){
1138 asmparser_message(This, "Line %u: Coissue flag on the first shader instruction\n", This->line_no);
1139 set_parse_status(&This->status, PARSE_ERR);
1140 }
1141 This->shader->instr[This->shader->num_instrs-1]->coissue = TRUE;
1142 }
1143
1144 static void asmparser_coissue_unsupported(struct asm_parser *This) {
1145 asmparser_message(This, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This->line_no);
1146 set_parse_status(&This->status, PARSE_ERR);
1147 }
1148
1149 static const struct asmparser_backend parser_vs_1 = {
1150 asmparser_constF,
1151 asmparser_constI,
1152 asmparser_constB,
1153
1154 asmparser_dstreg_vs_1,
1155 asmparser_srcreg_vs_1,
1156
1157 asmparser_predicate_unsupported,
1158 asmparser_coissue_unsupported,
1159
1160 asmparser_dcl_output_unsupported,
1161 asmparser_dcl_input,
1162 asmparser_dcl_sampler_unsupported,
1163
1164 asmparser_end,
1165
1166 asmparser_instr,
1167 };
1168
1169 static const struct asmparser_backend parser_vs_2 = {
1170 asmparser_constF,
1171 asmparser_constI,
1172 asmparser_constB,
1173
1174 asmparser_dstreg_vs_2,
1175 asmparser_srcreg_vs_2,
1176
1177 asmparser_predicate_supported,
1178 asmparser_coissue_unsupported,
1179
1180 asmparser_dcl_output_unsupported,
1181 asmparser_dcl_input,
1182 asmparser_dcl_sampler_unsupported,
1183
1184 asmparser_end,
1185
1186 asmparser_instr,
1187 };
1188
1189 static const struct asmparser_backend parser_vs_3 = {
1190 asmparser_constF,
1191 asmparser_constI,
1192 asmparser_constB,
1193
1194 asmparser_dstreg_vs_3,
1195 asmparser_srcreg_vs_3,
1196
1197 asmparser_predicate_supported,
1198 asmparser_coissue_unsupported,
1199
1200 asmparser_dcl_output,
1201 asmparser_dcl_input,
1202 asmparser_dcl_sampler,
1203
1204 asmparser_end,
1205
1206 asmparser_instr,
1207 };
1208
1209 static const struct asmparser_backend parser_ps_1_0123 = {
1210 asmparser_constF,
1211 asmparser_constI,
1212 asmparser_constB,
1213
1214 asmparser_dstreg_ps_1_0123,
1215 asmparser_srcreg_ps_1_0123,
1216
1217 asmparser_predicate_unsupported,
1218 asmparser_coissue_supported,
1219
1220 asmparser_dcl_output_unsupported,
1221 asmparser_dcl_input_unsupported,
1222 asmparser_dcl_sampler_unsupported,
1223
1224 asmparser_end,
1225
1226 asmparser_instr,
1227 };
1228
1229 static const struct asmparser_backend parser_ps_1_4 = {
1230 asmparser_constF,
1231 asmparser_constI,
1232 asmparser_constB,
1233
1234 asmparser_dstreg_ps_1_4,
1235 asmparser_srcreg_ps_1_4,
1236
1237 asmparser_predicate_unsupported,
1238 asmparser_coissue_supported,
1239
1240 asmparser_dcl_output_unsupported,
1241 asmparser_dcl_input_unsupported,
1242 asmparser_dcl_sampler_unsupported,
1243
1244 asmparser_end,
1245
1246 asmparser_instr,
1247 };
1248
1249 static const struct asmparser_backend parser_ps_2 = {
1250 asmparser_constF,
1251 asmparser_constI,
1252 asmparser_constB,
1253
1254 asmparser_dstreg_ps_2,
1255 asmparser_srcreg_ps_2,
1256
1257 asmparser_predicate_unsupported,
1258 asmparser_coissue_unsupported,
1259
1260 asmparser_dcl_output_unsupported,
1261 asmparser_dcl_input_ps_2,
1262 asmparser_dcl_sampler,
1263
1264 asmparser_end,
1265
1266 asmparser_instr,
1267 };
1268
1269 static const struct asmparser_backend parser_ps_2_x = {
1270 asmparser_constF,
1271 asmparser_constI,
1272 asmparser_constB,
1273
1274 asmparser_dstreg_ps_2_x,
1275 asmparser_srcreg_ps_2_x,
1276
1277 asmparser_predicate_supported,
1278 asmparser_coissue_unsupported,
1279
1280 asmparser_dcl_output_unsupported,
1281 asmparser_dcl_input_ps_2,
1282 asmparser_dcl_sampler,
1283
1284 asmparser_end,
1285
1286 asmparser_instr,
1287 };
1288
1289 static const struct asmparser_backend parser_ps_3 = {
1290 asmparser_constF,
1291 asmparser_constI,
1292 asmparser_constB,
1293
1294 asmparser_dstreg_ps_3,
1295 asmparser_srcreg_ps_3,
1296
1297 asmparser_predicate_supported,
1298 asmparser_coissue_unsupported,
1299
1300 asmparser_dcl_output_unsupported,
1301 asmparser_dcl_input,
1302 asmparser_dcl_sampler,
1303
1304 asmparser_end,
1305
1306 asmparser_instr,
1307 };
1308
1309 static void gen_oldvs_output(struct bwriter_shader *shader) {
1310 record_declaration(shader, BWRITERDECLUSAGE_POSITION, 0, 0, TRUE, OPOS_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1311 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, TRUE, OT0_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1312 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, TRUE, OT1_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1313 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, TRUE, OT2_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1314 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, TRUE, OT3_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1315 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, TRUE, OT4_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1316 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, TRUE, OT5_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1317 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, TRUE, OT6_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1318 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, TRUE, OT7_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1319 record_declaration(shader, BWRITERDECLUSAGE_FOG, 0, 0, TRUE, OFOG_REG, OFOG_WRITEMASK, TRUE);
1320 record_declaration(shader, BWRITERDECLUSAGE_PSIZE, 0, 0, TRUE, OPTS_REG, OPTS_WRITEMASK, TRUE);
1321 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, TRUE, OD0_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1322 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, TRUE, OD1_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
1323 }
1324
1325 static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) {
1326 switch(texcoords) {
1327 case 8: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, FALSE, T7_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1328 /* fall through */
1329 case 7: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, FALSE, T6_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1330 /* fall through */
1331 case 6: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, FALSE, T5_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1332 /* fall through */
1333 case 5: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, FALSE, T4_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1334 /* fall through */
1335 case 4: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, FALSE, T3_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1336 /* fall through */
1337 case 3: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, FALSE, T2_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1338 /* fall through */
1339 case 2: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, FALSE, T1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1340 /* fall through */
1341 case 1: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, FALSE, T0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1342 };
1343 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, FALSE, C0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1344 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1345 }
1346
1347 void create_vs10_parser(struct asm_parser *ret) {
1348 TRACE_(parsed_shader)("vs_1_0\n");
1349
1350 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1351 if(!ret->shader) {
1352 ERR("Failed to allocate memory for the shader\n");
1353 set_parse_status(&ret->status, PARSE_ERR);
1354 return;
1355 }
1356
1357 ret->shader->type = ST_VERTEX;
1358 ret->shader->version = BWRITERVS_VERSION(1, 0);
1359 ret->funcs = &parser_vs_1;
1360 gen_oldvs_output(ret->shader);
1361 }
1362
1363 void create_vs11_parser(struct asm_parser *ret) {
1364 TRACE_(parsed_shader)("vs_1_1\n");
1365
1366 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1367 if(!ret->shader) {
1368 ERR("Failed to allocate memory for the shader\n");
1369 set_parse_status(&ret->status, PARSE_ERR);
1370 return;
1371 }
1372
1373 ret->shader->type = ST_VERTEX;
1374 ret->shader->version = BWRITERVS_VERSION(1, 1);
1375 ret->funcs = &parser_vs_1;
1376 gen_oldvs_output(ret->shader);
1377 }
1378
1379 void create_vs20_parser(struct asm_parser *ret) {
1380 TRACE_(parsed_shader)("vs_2_0\n");
1381
1382 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1383 if(!ret->shader) {
1384 ERR("Failed to allocate memory for the shader\n");
1385 set_parse_status(&ret->status, PARSE_ERR);
1386 return;
1387 }
1388
1389 ret->shader->type = ST_VERTEX;
1390 ret->shader->version = BWRITERVS_VERSION(2, 0);
1391 ret->funcs = &parser_vs_2;
1392 gen_oldvs_output(ret->shader);
1393 }
1394
1395 void create_vs2x_parser(struct asm_parser *ret) {
1396 TRACE_(parsed_shader)("vs_2_x\n");
1397
1398 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1399 if(!ret->shader) {
1400 ERR("Failed to allocate memory for the shader\n");
1401 set_parse_status(&ret->status, PARSE_ERR);
1402 return;
1403 }
1404
1405 ret->shader->type = ST_VERTEX;
1406 ret->shader->version = BWRITERVS_VERSION(2, 1);
1407 ret->funcs = &parser_vs_2;
1408 gen_oldvs_output(ret->shader);
1409 }
1410
1411 void create_vs30_parser(struct asm_parser *ret) {
1412 TRACE_(parsed_shader)("vs_3_0\n");
1413
1414 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1415 if(!ret->shader) {
1416 ERR("Failed to allocate memory for the shader\n");
1417 set_parse_status(&ret->status, PARSE_ERR);
1418 return;
1419 }
1420
1421 ret->shader->type = ST_VERTEX;
1422 ret->shader->version = BWRITERVS_VERSION(3, 0);
1423 ret->funcs = &parser_vs_3;
1424 }
1425
1426 void create_ps10_parser(struct asm_parser *ret) {
1427 TRACE_(parsed_shader)("ps_1_0\n");
1428
1429 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1430 if(!ret->shader) {
1431 ERR("Failed to allocate memory for the shader\n");
1432 set_parse_status(&ret->status, PARSE_ERR);
1433 return;
1434 }
1435
1436 ret->shader->type = ST_PIXEL;
1437 ret->shader->version = BWRITERPS_VERSION(1, 0);
1438 ret->funcs = &parser_ps_1_0123;
1439 gen_oldps_input(ret->shader, 4);
1440 }
1441
1442 void create_ps11_parser(struct asm_parser *ret) {
1443 TRACE_(parsed_shader)("ps_1_1\n");
1444
1445 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1446 if(!ret->shader) {
1447 ERR("Failed to allocate memory for the shader\n");
1448 set_parse_status(&ret->status, PARSE_ERR);
1449 return;
1450 }
1451
1452 ret->shader->type = ST_PIXEL;
1453 ret->shader->version = BWRITERPS_VERSION(1, 1);
1454 ret->funcs = &parser_ps_1_0123;
1455 gen_oldps_input(ret->shader, 4);
1456 }
1457
1458 void create_ps12_parser(struct asm_parser *ret) {
1459 TRACE_(parsed_shader)("ps_1_2\n");
1460
1461 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1462 if(!ret->shader) {
1463 ERR("Failed to allocate memory for the shader\n");
1464 set_parse_status(&ret->status, PARSE_ERR);
1465 return;
1466 }
1467
1468 ret->shader->type = ST_PIXEL;
1469 ret->shader->version = BWRITERPS_VERSION(1, 2);
1470 ret->funcs = &parser_ps_1_0123;
1471 gen_oldps_input(ret->shader, 4);
1472 }
1473
1474 void create_ps13_parser(struct asm_parser *ret) {
1475 TRACE_(parsed_shader)("ps_1_3\n");
1476
1477 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1478 if(!ret->shader) {
1479 ERR("Failed to allocate memory for the shader\n");
1480 set_parse_status(&ret->status, PARSE_ERR);
1481 return;
1482 }
1483
1484 ret->shader->type = ST_PIXEL;
1485 ret->shader->version = BWRITERPS_VERSION(1, 3);
1486 ret->funcs = &parser_ps_1_0123;
1487 gen_oldps_input(ret->shader, 4);
1488 }
1489
1490 void create_ps14_parser(struct asm_parser *ret) {
1491 TRACE_(parsed_shader)("ps_1_4\n");
1492
1493 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1494 if(!ret->shader) {
1495 ERR("Failed to allocate memory for the shader\n");
1496 set_parse_status(&ret->status, PARSE_ERR);
1497 return;
1498 }
1499
1500 ret->shader->type = ST_PIXEL;
1501 ret->shader->version = BWRITERPS_VERSION(1, 4);
1502 ret->funcs = &parser_ps_1_4;
1503 gen_oldps_input(ret->shader, 6);
1504 }
1505
1506 void create_ps20_parser(struct asm_parser *ret) {
1507 TRACE_(parsed_shader)("ps_2_0\n");
1508
1509 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1510 if(!ret->shader) {
1511 ERR("Failed to allocate memory for the shader\n");
1512 set_parse_status(&ret->status, PARSE_ERR);
1513 return;
1514 }
1515
1516 ret->shader->type = ST_PIXEL;
1517 ret->shader->version = BWRITERPS_VERSION(2, 0);
1518 ret->funcs = &parser_ps_2;
1519 gen_oldps_input(ret->shader, 8);
1520 }
1521
1522 void create_ps2x_parser(struct asm_parser *ret) {
1523 TRACE_(parsed_shader)("ps_2_x\n");
1524
1525 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1526 if(!ret->shader) {
1527 ERR("Failed to allocate memory for the shader\n");
1528 set_parse_status(&ret->status, PARSE_ERR);
1529 return;
1530 }
1531
1532 ret->shader->type = ST_PIXEL;
1533 ret->shader->version = BWRITERPS_VERSION(2, 1);
1534 ret->funcs = &parser_ps_2_x;
1535 gen_oldps_input(ret->shader, 8);
1536 }
1537
1538 void create_ps30_parser(struct asm_parser *ret) {
1539 TRACE_(parsed_shader)("ps_3_0\n");
1540
1541 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader));
1542 if(!ret->shader) {
1543 ERR("Failed to allocate memory for the shader\n");
1544 set_parse_status(&ret->status, PARSE_ERR);
1545 return;
1546 }
1547
1548 ret->shader->type = ST_PIXEL;
1549 ret->shader->version = BWRITERPS_VERSION(3, 0);
1550 ret->funcs = &parser_ps_3;
1551 }