2 * Direct3D asm shader parser
4 * Copyright 2008 Stefan Dösinger
5 * Copyright 2009 Matteo Bruni
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.
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.
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
24 #include "wine/port.h"
25 #include "wine/debug.h"
27 #include "d3dx9_36_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
30 WINE_DECLARE_DEBUG_CHANNEL(parsed_shader);
33 /* How to map vs 1.0 and 2.0 varyings to 3.0 ones
34 * oTx is mapped to ox, which happens to be an
35 * identical mapping since BWRITERSPR_TEXCRDOUT == BWRITERSPR_OUTPUT
36 * oPos, oFog and point size are mapped to general output regs as well.
37 * the vs 1.x and 2.x parser functions add varying declarations
38 * to the shader, and the 1.x and 2.x output functions check those varyings
50 #define OFOG_WRITEMASK BWRITERSP_WRITEMASK_0
52 #define OPTS_WRITEMASK BWRITERSP_WRITEMASK_1
56 /* Input color registers 0-1 are identically mapped */
68 /****************************************************************
69 * Common(non-version specific) shader parser control code *
70 ****************************************************************/
72 static void asmparser_end(struct asm_parser *This) {
73 TRACE("Finalizing shader\n");
76 static void asmparser_constF(struct asm_parser *This, DWORD reg, float x, float y, float z, float w) {
77 if(!This->shader) return;
78 TRACE("Adding float constant %u at pos %u\n", reg, This->shader->num_cf);
79 TRACE_(parsed_shader)("def c%u, %f, %f, %f, %f\n", reg, x, y, z, w);
80 if(!add_constF(This->shader, reg, x, y, z, w)) {
81 ERR("Out of memory\n");
82 set_parse_status(This, PARSE_ERR);
86 static void asmparser_constB(struct asm_parser *This, DWORD reg, BOOL x) {
87 if(!This->shader) return;
88 TRACE("Adding boolean constant %u at pos %u\n", reg, This->shader->num_cb);
89 TRACE_(parsed_shader)("def b%u, %s\n", reg, x ? "true" : "false");
90 if(!add_constB(This->shader, reg, x)) {
91 ERR("Out of memory\n");
92 set_parse_status(This, PARSE_ERR);
96 static void asmparser_constI(struct asm_parser *This, DWORD reg, INT x, INT y, INT z, INT w) {
97 if(!This->shader) return;
98 TRACE("Adding integer constant %u at pos %u\n", reg, This->shader->num_ci);
99 TRACE_(parsed_shader)("def i%u, %d, %d, %d, %d\n", reg, x, y, z, w);
100 if(!add_constI(This->shader, reg, x, y, z, w)) {
101 ERR("Out of memory\n");
102 set_parse_status(This, PARSE_ERR);
106 static void asmparser_dcl_output(struct asm_parser *This, DWORD usage, DWORD num,
107 const struct shader_reg *reg) {
108 if(!This->shader) return;
109 if(This->shader->type == ST_PIXEL) {
110 asmparser_message(This, "Line %u: Output register declared in a pixel shader\n", This->line_no);
111 set_parse_status(This, PARSE_ERR);
113 if(!record_declaration(This->shader, usage, num, 0, TRUE, reg->regnum, reg->writemask, FALSE)) {
114 ERR("Out of memory\n");
115 set_parse_status(This, PARSE_ERR);
119 static void asmparser_dcl_input(struct asm_parser *This, DWORD usage, DWORD num,
120 DWORD mod, const struct shader_reg *reg) {
121 struct instruction instr;
123 if(!This->shader) return;
125 (This->shader->version != BWRITERPS_VERSION(3, 0) ||
126 (mod != BWRITERSPDM_MSAMPCENTROID &&
127 mod != BWRITERSPDM_PARTIALPRECISION))) {
128 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
129 set_parse_status(This, PARSE_ERR);
133 /* Check register type and modifiers */
136 This->funcs->dstreg(This, &instr, reg);
138 if(!record_declaration(This->shader, usage, num, mod, FALSE, reg->regnum, reg->writemask, FALSE)) {
139 ERR("Out of memory\n");
140 set_parse_status(This, PARSE_ERR);
144 static void asmparser_dcl_input_ps_2(struct asm_parser *This, DWORD usage, DWORD num,
145 DWORD mod, const struct shader_reg *reg) {
146 struct instruction instr;
148 if(!This->shader) return;
150 asmparser_message(This, "Line %u: Unsupported usage in dcl instruction\n", This->line_no);
151 set_parse_status(This, PARSE_ERR);
156 This->funcs->dstreg(This, &instr, reg);
157 if(!record_declaration(This->shader, usage, num, mod, FALSE, instr.dst.regnum, instr.dst.writemask, FALSE)) {
158 ERR("Out of memory\n");
159 set_parse_status(This, PARSE_ERR);
163 static void asmparser_dcl_sampler(struct asm_parser *This, DWORD samptype,
164 DWORD mod, DWORD regnum,
165 unsigned int line_no) {
166 if(!This->shader) return;
168 (This->shader->version != BWRITERPS_VERSION(3, 0) ||
169 (mod != BWRITERSPDM_MSAMPCENTROID &&
170 mod != BWRITERSPDM_PARTIALPRECISION))) {
171 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
172 set_parse_status(This, PARSE_ERR);
175 if(!record_sampler(This->shader, samptype, mod, regnum)) {
176 ERR("Out of memory\n");
177 set_parse_status(This, PARSE_ERR);
181 static void asmparser_sincos(struct asm_parser *This, DWORD mod, DWORD shift,
182 const struct shader_reg *dst,
183 const struct src_regs *srcs) {
184 struct instruction *instr;
186 if(!srcs || srcs->count != 3) {
187 asmparser_message(This, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This->line_no);
188 set_parse_status(This, PARSE_ERR);
192 instr = alloc_instr(3);
194 ERR("Error allocating memory for the instruction\n");
195 set_parse_status(This, PARSE_ERR);
199 instr->opcode = BWRITERSIO_SINCOS;
201 instr->shift = shift;
204 This->funcs->dstreg(This, instr, dst);
205 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
206 This->funcs->srcreg(This, instr, 1, &srcs->reg[1]);
207 This->funcs->srcreg(This, instr, 2, &srcs->reg[2]);
209 if(!add_instruction(This->shader, instr)) {
210 ERR("Out of memory\n");
211 set_parse_status(This, PARSE_ERR);
215 static void asmparser_instr(struct asm_parser *This, DWORD opcode,
216 DWORD mod, DWORD shift,
217 BWRITER_COMPARISON_TYPE comp,
218 const struct shader_reg *dst,
219 const struct src_regs *srcs, int expectednsrcs) {
220 struct instruction *instr;
222 BOOL firstreg = TRUE;
223 unsigned int src_count = srcs ? srcs->count : 0;
225 if(!This->shader) return;
227 TRACE_(parsed_shader)("%s%s%s ", debug_print_opcode(opcode),
228 debug_print_dstmod(mod),
229 debug_print_comp(comp));
231 TRACE_(parsed_shader)("%s", debug_print_dstreg(dst, This->shader->type));
234 for(i = 0; i < src_count; i++) {
235 if(!firstreg) TRACE_(parsed_shader)(", ");
236 else firstreg = FALSE;
237 TRACE_(parsed_shader)("%s", debug_print_srcreg(&srcs->reg[i],
238 This->shader->type));
240 TRACE_(parsed_shader)("\n");
242 /* Check for instructions with different syntaxes in different shader versio
245 case BWRITERSIO_SINCOS:
246 /* The syntax changes between vs 2 and the other shader versions */
247 if(This->shader->version == BWRITERVS_VERSION(2, 0) ||
248 This->shader->version == BWRITERVS_VERSION(2, 1)) {
249 asmparser_sincos(This, mod, shift, dst, srcs);
252 /* Use the default handling */
256 if(src_count != expectednsrcs) {
257 asmparser_message(This, "Line %u: Wrong number of source registers\n", This->line_no);
258 set_parse_status(This, PARSE_ERR);
262 instr = alloc_instr(src_count);
264 ERR("Error allocating memory for the instruction\n");
265 set_parse_status(This, PARSE_ERR);
269 instr->opcode = opcode;
271 instr->shift = shift;
272 instr->comptype = comp;
273 if(dst) This->funcs->dstreg(This, instr, dst);
274 for(i = 0; i < src_count; i++) {
275 This->funcs->srcreg(This, instr, i, &srcs->reg[i]);
278 if(!add_instruction(This->shader, instr)) {
279 ERR("Out of memory\n");
280 set_parse_status(This, PARSE_ERR);
284 static struct shader_reg map_oldvs_register(const struct shader_reg *reg) {
285 struct shader_reg ret;
287 case BWRITERSPR_RASTOUT:
289 ret.type = BWRITERSPR_OUTPUT;
290 switch(reg->regnum) {
291 case BWRITERSRO_POSITION:
292 ret.regnum = OPOS_REG;
295 ret.regnum = OFOG_REG;
296 ret.writemask = OFOG_WRITEMASK;
298 case BWRITERSRO_POINT_SIZE:
299 ret.regnum = OPTS_REG;
300 ret.writemask = OPTS_WRITEMASK;
303 FIXME("Unhandled RASTOUT register %u\n", reg->regnum);
308 case BWRITERSPR_TEXCRDOUT:
310 ret.type = BWRITERSPR_OUTPUT;
311 switch(reg->regnum) {
312 case 0: ret.regnum = OT0_REG; break;
313 case 1: ret.regnum = OT1_REG; break;
314 case 2: ret.regnum = OT2_REG; break;
315 case 3: ret.regnum = OT3_REG; break;
316 case 4: ret.regnum = OT4_REG; break;
317 case 5: ret.regnum = OT5_REG; break;
318 case 6: ret.regnum = OT6_REG; break;
319 case 7: ret.regnum = OT7_REG; break;
321 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg->regnum);
326 case BWRITERSPR_ATTROUT:
328 ret.type = BWRITERSPR_OUTPUT;
329 switch(reg->regnum) {
330 case 0: ret.regnum = OD0_REG; break;
331 case 1: ret.regnum = OD1_REG; break;
333 FIXME("Unhandled ATTROUT regnum %u\n", reg->regnum);
338 default: return *reg;
342 static struct shader_reg map_oldps_register(const struct shader_reg *reg, BOOL tex_varying) {
343 struct shader_reg ret;
345 case BWRITERSPR_TEXTURE:
348 ret.type = BWRITERSPR_INPUT;
349 switch(reg->regnum) {
350 case 0: ret.regnum = T0_VARYING; break;
351 case 1: ret.regnum = T1_VARYING; break;
352 case 2: ret.regnum = T2_VARYING; break;
353 case 3: ret.regnum = T3_VARYING; break;
354 case 4: ret.regnum = T4_VARYING; break;
355 case 5: ret.regnum = T5_VARYING; break;
356 case 6: ret.regnum = T6_VARYING; break;
357 case 7: ret.regnum = T7_VARYING; break;
359 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
364 FIXME("TODO: ps_1_x texture register mapping\n");
368 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
371 default: return *reg;
375 /* Checks for unsupported source modifiers in VS (all versions) or
377 static void check_legacy_srcmod(struct asm_parser *This, DWORD srcmod) {
378 if(srcmod == BWRITERSPSM_BIAS || srcmod == BWRITERSPSM_BIASNEG ||
379 srcmod == BWRITERSPSM_SIGN || srcmod == BWRITERSPSM_SIGNNEG ||
380 srcmod == BWRITERSPSM_COMP || srcmod == BWRITERSPSM_X2 ||
381 srcmod == BWRITERSPSM_X2NEG || srcmod == BWRITERSPSM_DZ ||
382 srcmod == BWRITERSPSM_DW) {
383 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
385 debug_print_srcmod(srcmod));
386 set_parse_status(This, PARSE_ERR);
390 static void check_abs_srcmod(struct asm_parser *This, DWORD srcmod) {
391 if(srcmod == BWRITERSPSM_ABS || srcmod == BWRITERSPSM_ABSNEG) {
392 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
394 debug_print_srcmod(srcmod));
395 set_parse_status(This, PARSE_ERR);
399 static void check_loop_swizzle(struct asm_parser *This,
400 const struct shader_reg *src) {
401 if((src->type == BWRITERSPR_LOOP && src->swizzle != BWRITERVS_NOSWIZZLE) ||
402 (src->rel_reg && src->rel_reg->type == BWRITERSPR_LOOP &&
403 src->rel_reg->swizzle != BWRITERVS_NOSWIZZLE)) {
404 asmparser_message(This, "Line %u: Swizzle not allowed on aL register\n", This->line_no);
405 set_parse_status(This, PARSE_ERR);
409 static void check_shift_dstmod(struct asm_parser *This, DWORD shift) {
411 asmparser_message(This, "Line %u: Shift modifiers not supported in this shader version\n",
413 set_parse_status(This, PARSE_ERR);
417 static void check_ps_dstmod(struct asm_parser *This, DWORD dstmod) {
418 if(dstmod == BWRITERSPDM_PARTIALPRECISION ||
419 dstmod == BWRITERSPDM_MSAMPCENTROID) {
420 asmparser_message(This, "Line %u: Instruction modifier %s not supported in this shader version\n",
422 debug_print_dstmod(dstmod));
423 set_parse_status(This, PARSE_ERR);
427 struct allowed_reg_type {
433 static BOOL check_reg_type(const struct shader_reg *reg,
434 const struct allowed_reg_type *allowed) {
437 while(allowed[i].type != ~0U) {
438 if(reg->type == allowed[i].type) {
440 if(allowed[i].reladdr)
441 return TRUE; /* The relative addressing register
442 can have a negative value, we
443 can't check the register index */
446 if(reg->regnum < allowed[i].count) return TRUE;
454 /* Native assembler doesn't do separate checks for src and dst registers */
455 static const struct allowed_reg_type vs_1_reg_allowed[] = {
456 { BWRITERSPR_TEMP, 12, FALSE },
457 { BWRITERSPR_INPUT, 16, FALSE },
458 { BWRITERSPR_CONST, ~0U, TRUE },
459 { BWRITERSPR_ADDR, 1, FALSE },
460 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
461 { BWRITERSPR_ATTROUT, 2, FALSE },
462 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
463 { ~0U, 0 } /* End tag */
466 /* struct instruction *asmparser_srcreg
468 * Records a source register in the instruction and does shader version
469 * specific checks and modifications on it
472 * This: Shader parser instance
473 * instr: instruction to store the register in
474 * num: Number of source register
475 * src: Pointer to source the register structure. The caller can free
478 static void asmparser_srcreg_vs_1(struct asm_parser *This,
479 struct instruction *instr, int num,
480 const struct shader_reg *src) {
481 struct shader_reg reg;
483 if(!check_reg_type(src, vs_1_reg_allowed)) {
484 asmparser_message(This, "Line %u: Source register %s not supported in VS 1\n",
486 debug_print_srcreg(src, ST_VERTEX));
487 set_parse_status(This, PARSE_ERR);
489 check_legacy_srcmod(This, src->srcmod);
490 check_abs_srcmod(This, src->srcmod);
491 reg = map_oldvs_register(src);
492 memcpy(&instr->src[num], ®, sizeof(reg));
495 static const struct allowed_reg_type vs_2_reg_allowed[] = {
496 { BWRITERSPR_TEMP, 12, FALSE },
497 { BWRITERSPR_INPUT, 16, FALSE },
498 { BWRITERSPR_CONST, ~0U, TRUE },
499 { BWRITERSPR_ADDR, 1, FALSE },
500 { BWRITERSPR_CONSTBOOL, 16, FALSE },
501 { BWRITERSPR_CONSTINT, 16, FALSE },
502 { BWRITERSPR_LOOP, 1, FALSE },
503 { BWRITERSPR_LABEL, 2048, FALSE },
504 { BWRITERSPR_PREDICATE, 1, FALSE },
505 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
506 { BWRITERSPR_ATTROUT, 2, FALSE },
507 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
508 { ~0U, 0 } /* End tag */
511 static void asmparser_srcreg_vs_2(struct asm_parser *This,
512 struct instruction *instr, int num,
513 const struct shader_reg *src) {
514 struct shader_reg reg;
516 if(!check_reg_type(src, vs_2_reg_allowed)) {
517 asmparser_message(This, "Line %u: Source register %s not supported in VS 2\n",
519 debug_print_srcreg(src, ST_VERTEX));
520 set_parse_status(This, PARSE_ERR);
522 check_loop_swizzle(This, src);
523 check_legacy_srcmod(This, src->srcmod);
524 check_abs_srcmod(This, src->srcmod);
525 reg = map_oldvs_register(src);
526 memcpy(&instr->src[num], ®, sizeof(reg));
529 static const struct allowed_reg_type vs_3_reg_allowed[] = {
530 { BWRITERSPR_TEMP, 32, FALSE },
531 { BWRITERSPR_INPUT, 16, TRUE },
532 { BWRITERSPR_CONST, ~0U, TRUE },
533 { BWRITERSPR_ADDR, 1, FALSE },
534 { BWRITERSPR_CONSTBOOL, 16, FALSE },
535 { BWRITERSPR_CONSTINT, 16, FALSE },
536 { BWRITERSPR_LOOP, 1, FALSE },
537 { BWRITERSPR_LABEL, 2048, FALSE },
538 { BWRITERSPR_PREDICATE, 1, FALSE },
539 { BWRITERSPR_SAMPLER, 4, FALSE },
540 { BWRITERSPR_OUTPUT, 12, TRUE },
541 { ~0U, 0 } /* End tag */
544 static void asmparser_srcreg_vs_3(struct asm_parser *This,
545 struct instruction *instr, int num,
546 const struct shader_reg *src) {
547 if(!check_reg_type(src, vs_3_reg_allowed)) {
548 asmparser_message(This, "Line %u: Source register %s not supported in VS 3.0\n",
550 debug_print_srcreg(src, ST_VERTEX));
551 set_parse_status(This, PARSE_ERR);
553 check_loop_swizzle(This, src);
554 check_legacy_srcmod(This, src->srcmod);
555 memcpy(&instr->src[num], src, sizeof(*src));
558 static const struct allowed_reg_type ps_2_0_reg_allowed[] = {
559 { BWRITERSPR_INPUT, 2, FALSE },
560 { BWRITERSPR_TEMP, 32, FALSE },
561 { BWRITERSPR_CONST, 32, FALSE },
562 { BWRITERSPR_CONSTINT, 16, FALSE },
563 { BWRITERSPR_CONSTBOOL, 16, FALSE },
564 { BWRITERSPR_SAMPLER, 16, FALSE },
565 { BWRITERSPR_TEXTURE, 8, FALSE },
566 { BWRITERSPR_COLOROUT, 4, FALSE },
567 { BWRITERSPR_DEPTHOUT, 1, FALSE },
568 { ~0U, 0 } /* End tag */
571 static void asmparser_srcreg_ps_2(struct asm_parser *This,
572 struct instruction *instr, int num,
573 const struct shader_reg *src) {
574 struct shader_reg reg;
576 if(!check_reg_type(src, ps_2_0_reg_allowed)) {
577 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.0\n",
579 debug_print_srcreg(src, ST_PIXEL));
580 set_parse_status(This, PARSE_ERR);
582 check_legacy_srcmod(This, src->srcmod);
583 check_abs_srcmod(This, src->srcmod);
584 reg = map_oldps_register(src, TRUE);
585 memcpy(&instr->src[num], ®, sizeof(reg));
588 static const struct allowed_reg_type ps_2_x_reg_allowed[] = {
589 { BWRITERSPR_INPUT, 2, FALSE },
590 { BWRITERSPR_TEMP, 32, FALSE },
591 { BWRITERSPR_CONST, 32, FALSE },
592 { BWRITERSPR_CONSTINT, 16, FALSE },
593 { BWRITERSPR_CONSTBOOL, 16, FALSE },
594 { BWRITERSPR_PREDICATE, 1, FALSE },
595 { BWRITERSPR_SAMPLER, 16, FALSE },
596 { BWRITERSPR_TEXTURE, 8, FALSE },
597 { BWRITERSPR_LABEL, 2048, FALSE },
598 { BWRITERSPR_COLOROUT, 4, FALSE },
599 { BWRITERSPR_DEPTHOUT, 1, FALSE },
600 { ~0U, 0 } /* End tag */
603 static void asmparser_srcreg_ps_2_x(struct asm_parser *This,
604 struct instruction *instr, int num,
605 const struct shader_reg *src) {
606 struct shader_reg reg;
608 if(!check_reg_type(src, ps_2_x_reg_allowed)) {
609 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.x\n",
611 debug_print_srcreg(src, ST_PIXEL));
612 set_parse_status(This, PARSE_ERR);
614 check_legacy_srcmod(This, src->srcmod);
615 check_abs_srcmod(This, src->srcmod);
616 reg = map_oldps_register(src, TRUE);
617 memcpy(&instr->src[num], ®, sizeof(reg));
620 static const struct allowed_reg_type ps_3_reg_allowed[] = {
621 { BWRITERSPR_INPUT, 10, TRUE },
622 { BWRITERSPR_TEMP, 32, FALSE },
623 { BWRITERSPR_CONST, 224, FALSE },
624 { BWRITERSPR_CONSTINT, 16, FALSE },
625 { BWRITERSPR_CONSTBOOL, 16, FALSE },
626 { BWRITERSPR_PREDICATE, 1, FALSE },
627 { BWRITERSPR_SAMPLER, 16, FALSE },
628 { BWRITERSPR_MISCTYPE, 2, FALSE }, /* vPos and vFace */
629 { BWRITERSPR_LOOP, 1, FALSE },
630 { BWRITERSPR_LABEL, 2048, FALSE },
631 { BWRITERSPR_COLOROUT, 4, FALSE },
632 { BWRITERSPR_DEPTHOUT, 1, FALSE },
633 { ~0U, 0 } /* End tag */
636 static void asmparser_srcreg_ps_3(struct asm_parser *This,
637 struct instruction *instr, int num,
638 const struct shader_reg *src) {
639 if(!check_reg_type(src, ps_3_reg_allowed)) {
640 asmparser_message(This, "Line %u: Source register %s not supported in PS 3.0\n",
642 debug_print_srcreg(src, ST_PIXEL));
643 set_parse_status(This, PARSE_ERR);
645 check_loop_swizzle(This, src);
646 check_legacy_srcmod(This, src->srcmod);
647 memcpy(&instr->src[num], src, sizeof(*src));
650 static void asmparser_dstreg_vs_1(struct asm_parser *This,
651 struct instruction *instr,
652 const struct shader_reg *dst) {
653 struct shader_reg reg;
655 if(!check_reg_type(dst, vs_1_reg_allowed)) {
656 asmparser_message(This, "Line %u: Destination register %s not supported in VS 1\n",
658 debug_print_dstreg(dst, ST_VERTEX));
659 set_parse_status(This, PARSE_ERR);
661 check_ps_dstmod(This, instr->dstmod);
662 check_shift_dstmod(This, instr->shift);
663 reg = map_oldvs_register(dst);
664 memcpy(&instr->dst, ®, sizeof(reg));
665 instr->has_dst = TRUE;
668 static void asmparser_dstreg_vs_2(struct asm_parser *This,
669 struct instruction *instr,
670 const struct shader_reg *dst) {
671 struct shader_reg reg;
673 if(!check_reg_type(dst, vs_2_reg_allowed)) {
674 asmparser_message(This, "Line %u: Destination register %s not supported in VS 2.0\n",
676 debug_print_dstreg(dst, ST_VERTEX));
677 set_parse_status(This, PARSE_ERR);
679 check_ps_dstmod(This, instr->dstmod);
680 check_shift_dstmod(This, instr->shift);
681 reg = map_oldvs_register(dst);
682 memcpy(&instr->dst, ®, sizeof(reg));
683 instr->has_dst = TRUE;
686 static void asmparser_dstreg_vs_3(struct asm_parser *This,
687 struct instruction *instr,
688 const struct shader_reg *dst) {
689 if(!check_reg_type(dst, vs_3_reg_allowed)) {
690 asmparser_message(This, "Line %u: Destination register %s not supported in VS 3.0\n",
692 debug_print_dstreg(dst, ST_VERTEX));
693 set_parse_status(This, PARSE_ERR);
695 check_ps_dstmod(This, instr->dstmod);
696 check_shift_dstmod(This, instr->shift);
697 memcpy(&instr->dst, dst, sizeof(*dst));
698 instr->has_dst = TRUE;
701 static void asmparser_dstreg_ps_2(struct asm_parser *This,
702 struct instruction *instr,
703 const struct shader_reg *dst) {
704 struct shader_reg reg;
706 if(!check_reg_type(dst, ps_2_0_reg_allowed)) {
707 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.0\n",
709 debug_print_dstreg(dst, ST_PIXEL));
710 set_parse_status(This, PARSE_ERR);
712 check_shift_dstmod(This, instr->shift);
713 reg = map_oldps_register(dst, TRUE);
714 memcpy(&instr->dst, ®, sizeof(reg));
715 instr->has_dst = TRUE;
718 static void asmparser_dstreg_ps_2_x(struct asm_parser *This,
719 struct instruction *instr,
720 const struct shader_reg *dst) {
721 struct shader_reg reg;
723 if(!check_reg_type(dst, ps_2_x_reg_allowed)) {
724 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.x\n",
726 debug_print_dstreg(dst, ST_PIXEL));
727 set_parse_status(This, PARSE_ERR);
729 check_shift_dstmod(This, instr->shift);
730 reg = map_oldps_register(dst, TRUE);
731 memcpy(&instr->dst, ®, sizeof(reg));
732 instr->has_dst = TRUE;
735 static void asmparser_dstreg_ps_3(struct asm_parser *This,
736 struct instruction *instr,
737 const struct shader_reg *dst) {
738 if(!check_reg_type(dst, ps_3_reg_allowed)) {
739 asmparser_message(This, "Line %u: Destination register %s not supported in PS 3.0\n",
741 debug_print_dstreg(dst, ST_PIXEL));
742 set_parse_status(This, PARSE_ERR);
744 check_shift_dstmod(This, instr->shift);
745 memcpy(&instr->dst, dst, sizeof(*dst));
746 instr->has_dst = TRUE;
749 static void asmparser_predicate_supported(struct asm_parser *This,
750 const struct shader_reg *predicate) {
751 /* this sets the predicate of the last instruction added to the shader */
752 if(!This->shader) return;
753 if(This->shader->num_instrs == 0) ERR("Predicate without an instruction\n");
754 This->shader->instr[This->shader->num_instrs - 1]->has_predicate = TRUE;
755 memcpy(&This->shader->instr[This->shader->num_instrs - 1]->predicate, predicate, sizeof(*predicate));
758 static void asmparser_predicate_unsupported(struct asm_parser *This,
759 const struct shader_reg *predicate) {
760 asmparser_message(This, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This->line_no);
761 set_parse_status(This, PARSE_ERR);
764 static void asmparser_coissue_unsupported(struct asm_parser *This) {
765 asmparser_message(This, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This->line_no);
766 set_parse_status(This, PARSE_ERR);
769 static const struct asmparser_backend parser_vs_1 = {
774 asmparser_dstreg_vs_1,
775 asmparser_srcreg_vs_1,
777 asmparser_predicate_unsupported,
778 asmparser_coissue_unsupported,
780 asmparser_dcl_output,
782 asmparser_dcl_sampler,
789 static const struct asmparser_backend parser_vs_2 = {
794 asmparser_dstreg_vs_2,
795 asmparser_srcreg_vs_2,
797 asmparser_predicate_supported,
798 asmparser_coissue_unsupported,
800 asmparser_dcl_output,
802 asmparser_dcl_sampler,
809 static const struct asmparser_backend parser_vs_3 = {
814 asmparser_dstreg_vs_3,
815 asmparser_srcreg_vs_3,
817 asmparser_predicate_supported,
818 asmparser_coissue_unsupported,
820 asmparser_dcl_output,
822 asmparser_dcl_sampler,
829 static const struct asmparser_backend parser_ps_2 = {
834 asmparser_dstreg_ps_2,
835 asmparser_srcreg_ps_2,
837 asmparser_predicate_unsupported,
838 asmparser_coissue_unsupported,
840 asmparser_dcl_output,
841 asmparser_dcl_input_ps_2,
842 asmparser_dcl_sampler,
849 static const struct asmparser_backend parser_ps_2_x = {
854 asmparser_dstreg_ps_2_x,
855 asmparser_srcreg_ps_2_x,
857 asmparser_predicate_supported,
858 asmparser_coissue_unsupported,
860 asmparser_dcl_output,
861 asmparser_dcl_input_ps_2,
862 asmparser_dcl_sampler,
869 static const struct asmparser_backend parser_ps_3 = {
874 asmparser_dstreg_ps_3,
875 asmparser_srcreg_ps_3,
877 asmparser_predicate_supported,
878 asmparser_coissue_unsupported,
880 asmparser_dcl_output,
882 asmparser_dcl_sampler,
889 static void gen_oldvs_output(struct bwriter_shader *shader) {
890 record_declaration(shader, BWRITERDECLUSAGE_POSITION, 0, 0, TRUE, OPOS_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
891 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, TRUE, OT0_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
892 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, TRUE, OT1_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
893 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, TRUE, OT2_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
894 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, TRUE, OT3_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
895 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, TRUE, OT4_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
896 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, TRUE, OT5_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
897 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, TRUE, OT6_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
898 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, TRUE, OT7_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
899 record_declaration(shader, BWRITERDECLUSAGE_FOG, 0, 0, TRUE, OFOG_REG, OFOG_WRITEMASK, TRUE);
900 record_declaration(shader, BWRITERDECLUSAGE_PSIZE, 0, 0, TRUE, OPTS_REG, OPTS_WRITEMASK, TRUE);
901 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, TRUE, OD0_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
902 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, TRUE, OD1_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
905 static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) {
907 case 8: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, FALSE, T7_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
908 case 7: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, FALSE, T6_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
909 case 6: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, FALSE, T5_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
910 case 5: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, FALSE, T4_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
911 case 4: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, FALSE, T3_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
912 case 3: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, FALSE, T2_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
913 case 2: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, FALSE, T1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
914 case 1: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, FALSE, T0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
916 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, FALSE, C0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
917 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
920 void create_vs10_parser(struct asm_parser *ret) {
921 TRACE_(parsed_shader)("vs_1_0\n");
923 ret->shader = asm_alloc(sizeof(*ret->shader));
925 ERR("Failed to allocate memory for the shader\n");
926 set_parse_status(ret, PARSE_ERR);
930 ret->shader->type = ST_VERTEX;
931 ret->shader->version = BWRITERVS_VERSION(1, 0);
932 ret->funcs = &parser_vs_1;
933 gen_oldvs_output(ret->shader);
936 void create_vs11_parser(struct asm_parser *ret) {
937 TRACE_(parsed_shader)("vs_1_1\n");
939 ret->shader = asm_alloc(sizeof(*ret->shader));
941 ERR("Failed to allocate memory for the shader\n");
942 set_parse_status(ret, PARSE_ERR);
946 ret->shader->type = ST_VERTEX;
947 ret->shader->version = BWRITERVS_VERSION(1, 1);
948 ret->funcs = &parser_vs_1;
949 gen_oldvs_output(ret->shader);
952 void create_vs20_parser(struct asm_parser *ret) {
953 TRACE_(parsed_shader)("vs_2_0\n");
955 ret->shader = asm_alloc(sizeof(*ret->shader));
957 ERR("Failed to allocate memory for the shader\n");
958 set_parse_status(ret, PARSE_ERR);
962 ret->shader->type = ST_VERTEX;
963 ret->shader->version = BWRITERVS_VERSION(2, 0);
964 ret->funcs = &parser_vs_2;
965 gen_oldvs_output(ret->shader);
968 void create_vs2x_parser(struct asm_parser *ret) {
969 TRACE_(parsed_shader)("vs_2_x\n");
971 ret->shader = asm_alloc(sizeof(*ret->shader));
973 ERR("Failed to allocate memory for the shader\n");
974 set_parse_status(ret, PARSE_ERR);
978 ret->shader->type = ST_VERTEX;
979 ret->shader->version = BWRITERVS_VERSION(2, 1);
980 ret->funcs = &parser_vs_2;
981 gen_oldvs_output(ret->shader);
984 void create_vs30_parser(struct asm_parser *ret) {
985 TRACE_(parsed_shader)("vs_3_0\n");
987 ret->shader = asm_alloc(sizeof(*ret->shader));
989 ERR("Failed to allocate memory for the shader\n");
990 set_parse_status(ret, PARSE_ERR);
994 ret->shader->type = ST_VERTEX;
995 ret->shader->version = BWRITERVS_VERSION(3, 0);
996 ret->funcs = &parser_vs_3;
999 void create_ps20_parser(struct asm_parser *ret) {
1000 TRACE_(parsed_shader)("ps_2_0\n");
1002 ret->shader = asm_alloc(sizeof(*ret->shader));
1004 ERR("Failed to allocate memory for the shader\n");
1005 set_parse_status(ret, PARSE_ERR);
1009 ret->shader->type = ST_PIXEL;
1010 ret->shader->version = BWRITERPS_VERSION(2, 0);
1011 ret->funcs = &parser_ps_2;
1012 gen_oldps_input(ret->shader, 8);
1015 void create_ps2x_parser(struct asm_parser *ret) {
1016 TRACE_(parsed_shader)("ps_2_x\n");
1018 ret->shader = asm_alloc(sizeof(*ret->shader));
1020 ERR("Failed to allocate memory for the shader\n");
1021 set_parse_status(ret, PARSE_ERR);
1025 ret->shader->type = ST_PIXEL;
1026 ret->shader->version = BWRITERPS_VERSION(2, 1);
1027 ret->funcs = &parser_ps_2_x;
1028 gen_oldps_input(ret->shader, 8);
1031 void create_ps30_parser(struct asm_parser *ret) {
1032 TRACE_(parsed_shader)("ps_3_0\n");
1034 ret->shader = asm_alloc(sizeof(*ret->shader));
1036 ERR("Failed to allocate memory for the shader\n");
1037 set_parse_status(ret, PARSE_ERR);
1041 ret->shader->type = ST_PIXEL;
1042 ret->shader->version = BWRITERPS_VERSION(3, 0);
1043 ret->funcs = &parser_ps_3;