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
)) {
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 if(!This
->shader
) return;
123 (This
->shader
->version
!= BWRITERPS_VERSION(3, 0) ||
124 (mod
!= BWRITERSPDM_MSAMPCENTROID
&&
125 mod
!= BWRITERSPDM_PARTIALPRECISION
))) {
126 asmparser_message(This
, "Line %u: Unsupported modifier in dcl instruction\n", This
->line_no
);
127 set_parse_status(This
, PARSE_ERR
);
130 if(!record_declaration(This
->shader
, usage
, num
, mod
, FALSE
, reg
->regnum
, reg
->writemask
)) {
131 ERR("Out of memory\n");
132 set_parse_status(This
, PARSE_ERR
);
136 static void asmparser_dcl_sampler(struct asm_parser
*This
, DWORD samptype
, DWORD regnum
, unsigned int line_no
) {
137 if(!This
->shader
) return;
138 if(!record_sampler(This
->shader
, samptype
, regnum
)) {
139 ERR("Out of memory\n");
140 set_parse_status(This
, PARSE_ERR
);
144 static void asmparser_sincos(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
145 const struct shader_reg
*dst
,
146 const struct src_regs
*srcs
) {
147 struct instruction
*instr
;
149 if(!srcs
|| srcs
->count
!= 3) {
150 asmparser_message(This
, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This
->line_no
);
151 set_parse_status(This
, PARSE_ERR
);
155 instr
= alloc_instr(3);
157 ERR("Error allocating memory for the instruction\n");
158 set_parse_status(This
, PARSE_ERR
);
162 instr
->opcode
= BWRITERSIO_SINCOS
;
164 instr
->shift
= shift
;
167 This
->funcs
->dstreg(This
, instr
, dst
);
168 This
->funcs
->srcreg(This
, instr
, 0, &srcs
->reg
[0]);
169 This
->funcs
->srcreg(This
, instr
, 1, &srcs
->reg
[1]);
170 This
->funcs
->srcreg(This
, instr
, 2, &srcs
->reg
[2]);
172 if(!add_instruction(This
->shader
, instr
)) {
173 ERR("Out of memory\n");
174 set_parse_status(This
, PARSE_ERR
);
178 static void asmparser_instr(struct asm_parser
*This
, DWORD opcode
,
179 DWORD mod
, DWORD shift
,
180 BWRITER_COMPARISON_TYPE comp
,
181 const struct shader_reg
*dst
,
182 const struct src_regs
*srcs
, int expectednsrcs
) {
183 struct instruction
*instr
;
185 BOOL firstreg
= TRUE
;
186 unsigned int src_count
= srcs
? srcs
->count
: 0;
188 if(!This
->shader
) return;
190 TRACE_(parsed_shader
)("%s%s%s ", debug_print_opcode(opcode
),
191 debug_print_dstmod(mod
),
192 debug_print_comp(comp
));
194 TRACE_(parsed_shader
)("%s", debug_print_dstreg(dst
, This
->shader
->type
));
197 for(i
= 0; i
< src_count
; i
++) {
198 if(!firstreg
) TRACE_(parsed_shader
)(", ");
199 else firstreg
= FALSE
;
200 TRACE_(parsed_shader
)("%s", debug_print_srcreg(&srcs
->reg
[i
],
201 This
->shader
->type
));
203 TRACE_(parsed_shader
)("\n");
205 /* Check for instructions with different syntaxes in different shader versio
208 case BWRITERSIO_SINCOS
:
209 /* The syntax changes between vs 2 and the other shader versions */
210 if(This
->shader
->version
== BWRITERVS_VERSION(2, 0) ||
211 This
->shader
->version
== BWRITERVS_VERSION(2, 1)) {
212 asmparser_sincos(This
, mod
, shift
, dst
, srcs
);
215 /* Use the default handling */
219 if(src_count
!= expectednsrcs
) {
220 asmparser_message(This
, "Line %u: Wrong number of source registers\n", This
->line_no
);
221 set_parse_status(This
, PARSE_ERR
);
225 instr
= alloc_instr(src_count
);
227 ERR("Error allocating memory for the instruction\n");
228 set_parse_status(This
, PARSE_ERR
);
232 instr
->opcode
= opcode
;
234 instr
->shift
= shift
;
235 instr
->comptype
= comp
;
236 if(dst
) This
->funcs
->dstreg(This
, instr
, dst
);
237 for(i
= 0; i
< src_count
; i
++) {
238 This
->funcs
->srcreg(This
, instr
, i
, &srcs
->reg
[i
]);
241 if(!add_instruction(This
->shader
, instr
)) {
242 ERR("Out of memory\n");
243 set_parse_status(This
, PARSE_ERR
);
247 static struct shader_reg
map_oldvs_register(const struct shader_reg
*reg
) {
248 struct shader_reg ret
;
250 case BWRITERSPR_RASTOUT
:
252 ret
.type
= BWRITERSPR_OUTPUT
;
253 switch(reg
->regnum
) {
254 case BWRITERSRO_POSITION
:
255 ret
.regnum
= OPOS_REG
;
258 ret
.regnum
= OFOG_REG
;
259 ret
.writemask
= OFOG_WRITEMASK
;
261 case BWRITERSRO_POINT_SIZE
:
262 ret
.regnum
= OPTS_REG
;
263 ret
.writemask
= OPTS_WRITEMASK
;
266 FIXME("Unhandled RASTOUT register %u\n", reg
->regnum
);
271 case BWRITERSPR_TEXCRDOUT
:
273 ret
.type
= BWRITERSPR_OUTPUT
;
274 switch(reg
->regnum
) {
275 case 0: ret
.regnum
= OT0_REG
; break;
276 case 1: ret
.regnum
= OT1_REG
; break;
277 case 2: ret
.regnum
= OT2_REG
; break;
278 case 3: ret
.regnum
= OT3_REG
; break;
279 case 4: ret
.regnum
= OT4_REG
; break;
280 case 5: ret
.regnum
= OT5_REG
; break;
281 case 6: ret
.regnum
= OT6_REG
; break;
282 case 7: ret
.regnum
= OT7_REG
; break;
284 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg
->regnum
);
289 case BWRITERSPR_ATTROUT
:
291 ret
.type
= BWRITERSPR_OUTPUT
;
292 switch(reg
->regnum
) {
293 case 0: ret
.regnum
= OD0_REG
; break;
294 case 1: ret
.regnum
= OD1_REG
; break;
296 FIXME("Unhandled ATTROUT regnum %u\n", reg
->regnum
);
301 default: return *reg
;
305 static struct shader_reg
map_oldps_register(const struct shader_reg
*reg
, BOOL tex_varying
) {
306 struct shader_reg ret
;
308 case BWRITERSPR_TEXTURE
:
311 ret
.type
= BWRITERSPR_INPUT
;
312 switch(reg
->regnum
) {
313 case 0: ret
.regnum
= T0_VARYING
; break;
314 case 1: ret
.regnum
= T1_VARYING
; break;
315 case 2: ret
.regnum
= T2_VARYING
; break;
316 case 3: ret
.regnum
= T3_VARYING
; break;
317 case 4: ret
.regnum
= T4_VARYING
; break;
318 case 5: ret
.regnum
= T5_VARYING
; break;
319 case 6: ret
.regnum
= T6_VARYING
; break;
320 case 7: ret
.regnum
= T7_VARYING
; break;
322 FIXME("Unexpected TEXTURE register t%u\n", reg
->regnum
);
327 FIXME("TODO: ps_1_x texture register mapping\n");
331 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
334 default: return *reg
;
338 /* Checks for unsupported source modifiers in VS (all versions) or
340 static void check_legacy_srcmod(struct asm_parser
*This
, DWORD srcmod
) {
341 if(srcmod
== BWRITERSPSM_BIAS
|| srcmod
== BWRITERSPSM_BIASNEG
||
342 srcmod
== BWRITERSPSM_SIGN
|| srcmod
== BWRITERSPSM_SIGNNEG
||
343 srcmod
== BWRITERSPSM_COMP
|| srcmod
== BWRITERSPSM_X2
||
344 srcmod
== BWRITERSPSM_X2NEG
|| srcmod
== BWRITERSPSM_DZ
||
345 srcmod
== BWRITERSPSM_DW
) {
346 asmparser_message(This
, "Line %u: Source modifier %s not supported in this shader version\n",
348 debug_print_srcmod(srcmod
));
349 set_parse_status(This
, PARSE_ERR
);
353 static void check_abs_srcmod(struct asm_parser
*This
, DWORD srcmod
) {
354 if(srcmod
== BWRITERSPSM_ABS
|| srcmod
== BWRITERSPSM_ABSNEG
) {
355 asmparser_message(This
, "Line %u: Source modifier %s not supported in this shader version\n",
357 debug_print_srcmod(srcmod
));
358 set_parse_status(This
, PARSE_ERR
);
362 static void check_loop_swizzle(struct asm_parser
*This
,
363 const struct shader_reg
*src
) {
364 if((src
->type
== BWRITERSPR_LOOP
&& src
->swizzle
!= BWRITERVS_NOSWIZZLE
) ||
365 (src
->rel_reg
&& src
->rel_reg
->type
== BWRITERSPR_LOOP
&&
366 src
->rel_reg
->swizzle
!= BWRITERVS_NOSWIZZLE
)) {
367 asmparser_message(This
, "Line %u: Swizzle not allowed on aL register\n", This
->line_no
);
368 set_parse_status(This
, PARSE_ERR
);
372 static void check_shift_dstmod(struct asm_parser
*This
, DWORD shift
) {
374 asmparser_message(This
, "Line %u: Shift modifiers not supported in this shader version\n",
376 set_parse_status(This
, PARSE_ERR
);
380 static void check_ps_dstmod(struct asm_parser
*This
, DWORD dstmod
) {
381 if(dstmod
== BWRITERSPDM_PARTIALPRECISION
||
382 dstmod
== BWRITERSPDM_MSAMPCENTROID
) {
383 asmparser_message(This
, "Line %u: Instruction modifier %s not supported in this shader version\n",
385 debug_print_dstmod(dstmod
));
386 set_parse_status(This
, PARSE_ERR
);
390 struct allowed_reg_type
{
396 static BOOL
check_reg_type(const struct shader_reg
*reg
,
397 const struct allowed_reg_type
*allowed
) {
400 while(allowed
[i
].type
!= ~0U) {
401 if(reg
->type
== allowed
[i
].type
) {
403 if(allowed
[i
].reladdr
)
404 return TRUE
; /* The relative addressing register
405 can have a negative value, we
406 can't check the register index */
409 if(reg
->regnum
< allowed
[i
].count
) return TRUE
;
417 /* Native assembler doesn't do separate checks for src and dst registers */
418 static const struct allowed_reg_type vs_1_reg_allowed
[] = {
419 { BWRITERSPR_TEMP
, 12, FALSE
},
420 { BWRITERSPR_INPUT
, 16, FALSE
},
421 { BWRITERSPR_CONST
, ~0U, TRUE
},
422 { BWRITERSPR_ADDR
, 1, FALSE
},
423 { BWRITERSPR_RASTOUT
, 3, FALSE
}, /* oPos, oFog and oPts */
424 { BWRITERSPR_ATTROUT
, 2, FALSE
},
425 { BWRITERSPR_TEXCRDOUT
, 8, FALSE
},
426 { ~0U, 0 } /* End tag */
429 /* struct instruction *asmparser_srcreg
431 * Records a source register in the instruction and does shader version
432 * specific checks and modifications on it
435 * This: Shader parser instance
436 * instr: instruction to store the register in
437 * num: Number of source register
438 * src: Pointer to source the register structure. The caller can free
441 static void asmparser_srcreg_vs_1(struct asm_parser
*This
,
442 struct instruction
*instr
, int num
,
443 const struct shader_reg
*src
) {
444 struct shader_reg reg
;
446 if(!check_reg_type(src
, vs_1_reg_allowed
)) {
447 asmparser_message(This
, "Line %u: Source register %s not supported in VS 1\n",
449 debug_print_srcreg(src
, ST_VERTEX
));
450 set_parse_status(This
, PARSE_ERR
);
452 check_legacy_srcmod(This
, src
->srcmod
);
453 check_abs_srcmod(This
, src
->srcmod
);
454 reg
= map_oldvs_register(src
);
455 memcpy(&instr
->src
[num
], ®
, sizeof(reg
));
458 static const struct allowed_reg_type vs_2_reg_allowed
[] = {
459 { BWRITERSPR_TEMP
, 12, FALSE
},
460 { BWRITERSPR_INPUT
, 16, FALSE
},
461 { BWRITERSPR_CONST
, ~0U, TRUE
},
462 { BWRITERSPR_ADDR
, 1, FALSE
},
463 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
464 { BWRITERSPR_CONSTINT
, 16, FALSE
},
465 { BWRITERSPR_LOOP
, 1, FALSE
},
466 { BWRITERSPR_LABEL
, 2048, FALSE
},
467 { BWRITERSPR_PREDICATE
, 1, FALSE
},
468 { BWRITERSPR_RASTOUT
, 3, FALSE
}, /* oPos, oFog and oPts */
469 { BWRITERSPR_ATTROUT
, 2, FALSE
},
470 { BWRITERSPR_TEXCRDOUT
, 8, FALSE
},
471 { ~0U, 0 } /* End tag */
474 static void asmparser_srcreg_vs_2(struct asm_parser
*This
,
475 struct instruction
*instr
, int num
,
476 const struct shader_reg
*src
) {
477 struct shader_reg reg
;
479 if(!check_reg_type(src
, vs_2_reg_allowed
)) {
480 asmparser_message(This
, "Line %u: Source register %s not supported in VS 2\n",
482 debug_print_srcreg(src
, ST_VERTEX
));
483 set_parse_status(This
, PARSE_ERR
);
485 check_loop_swizzle(This
, src
);
486 check_legacy_srcmod(This
, src
->srcmod
);
487 check_abs_srcmod(This
, src
->srcmod
);
488 reg
= map_oldvs_register(src
);
489 memcpy(&instr
->src
[num
], ®
, sizeof(reg
));
492 static const struct allowed_reg_type vs_3_reg_allowed
[] = {
493 { BWRITERSPR_TEMP
, 32, FALSE
},
494 { BWRITERSPR_INPUT
, 16, TRUE
},
495 { BWRITERSPR_CONST
, ~0U, TRUE
},
496 { BWRITERSPR_ADDR
, 1, FALSE
},
497 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
498 { BWRITERSPR_CONSTINT
, 16, FALSE
},
499 { BWRITERSPR_LOOP
, 1, FALSE
},
500 { BWRITERSPR_LABEL
, 2048, FALSE
},
501 { BWRITERSPR_PREDICATE
, 1, FALSE
},
502 { BWRITERSPR_SAMPLER
, 4, FALSE
},
503 { BWRITERSPR_OUTPUT
, 12, TRUE
},
504 { ~0U, 0 } /* End tag */
507 static void asmparser_srcreg_vs_3(struct asm_parser
*This
,
508 struct instruction
*instr
, int num
,
509 const struct shader_reg
*src
) {
510 if(!check_reg_type(src
, vs_3_reg_allowed
)) {
511 asmparser_message(This
, "Line %u: Source register %s not supported in VS 3.0\n",
513 debug_print_srcreg(src
, ST_VERTEX
));
514 set_parse_status(This
, PARSE_ERR
);
516 check_loop_swizzle(This
, src
);
517 check_legacy_srcmod(This
, src
->srcmod
);
518 memcpy(&instr
->src
[num
], src
, sizeof(*src
));
521 static const struct allowed_reg_type ps_2_0_reg_allowed
[] = {
522 { BWRITERSPR_INPUT
, 2, FALSE
},
523 { BWRITERSPR_TEMP
, 32, FALSE
},
524 { BWRITERSPR_CONST
, 32, FALSE
},
525 { BWRITERSPR_CONSTINT
, 16, FALSE
},
526 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
527 { BWRITERSPR_SAMPLER
, 16, FALSE
},
528 { BWRITERSPR_TEXTURE
, 8, FALSE
},
529 { BWRITERSPR_COLOROUT
, 4, FALSE
},
530 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
531 { ~0U, 0 } /* End tag */
534 static void asmparser_srcreg_ps_2(struct asm_parser
*This
,
535 struct instruction
*instr
, int num
,
536 const struct shader_reg
*src
) {
537 struct shader_reg reg
;
539 if(!check_reg_type(src
, ps_2_0_reg_allowed
)) {
540 asmparser_message(This
, "Line %u: Source register %s not supported in PS 2.0\n",
542 debug_print_srcreg(src
, ST_PIXEL
));
543 set_parse_status(This
, PARSE_ERR
);
545 check_legacy_srcmod(This
, src
->srcmod
);
546 check_abs_srcmod(This
, src
->srcmod
);
547 reg
= map_oldps_register(src
, TRUE
);
548 memcpy(&instr
->src
[num
], ®
, sizeof(reg
));
551 static const struct allowed_reg_type ps_2_x_reg_allowed
[] = {
552 { BWRITERSPR_INPUT
, 2, FALSE
},
553 { BWRITERSPR_TEMP
, 32, FALSE
},
554 { BWRITERSPR_CONST
, 32, FALSE
},
555 { BWRITERSPR_CONSTINT
, 16, FALSE
},
556 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
557 { BWRITERSPR_PREDICATE
, 1, FALSE
},
558 { BWRITERSPR_SAMPLER
, 16, FALSE
},
559 { BWRITERSPR_TEXTURE
, 8, FALSE
},
560 { BWRITERSPR_LABEL
, 2048, FALSE
},
561 { BWRITERSPR_COLOROUT
, 4, FALSE
},
562 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
563 { ~0U, 0 } /* End tag */
566 static void asmparser_srcreg_ps_2_x(struct asm_parser
*This
,
567 struct instruction
*instr
, int num
,
568 const struct shader_reg
*src
) {
569 struct shader_reg reg
;
571 if(!check_reg_type(src
, ps_2_x_reg_allowed
)) {
572 asmparser_message(This
, "Line %u: Source register %s not supported in PS 2.x\n",
574 debug_print_srcreg(src
, ST_PIXEL
));
575 set_parse_status(This
, PARSE_ERR
);
577 check_legacy_srcmod(This
, src
->srcmod
);
578 check_abs_srcmod(This
, src
->srcmod
);
579 reg
= map_oldps_register(src
, TRUE
);
580 memcpy(&instr
->src
[num
], ®
, sizeof(reg
));
583 static const struct allowed_reg_type ps_3_reg_allowed
[] = {
584 { BWRITERSPR_INPUT
, 10, TRUE
},
585 { BWRITERSPR_TEMP
, 32, FALSE
},
586 { BWRITERSPR_CONST
, 224, FALSE
},
587 { BWRITERSPR_CONSTINT
, 16, FALSE
},
588 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
589 { BWRITERSPR_PREDICATE
, 1, FALSE
},
590 { BWRITERSPR_SAMPLER
, 16, FALSE
},
591 { BWRITERSPR_MISCTYPE
, 2, FALSE
}, /* vPos and vFace */
592 { BWRITERSPR_LOOP
, 1, FALSE
},
593 { BWRITERSPR_LABEL
, 2048, FALSE
},
594 { BWRITERSPR_COLOROUT
, 4, FALSE
},
595 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
596 { ~0U, 0 } /* End tag */
599 static void asmparser_srcreg_ps_3(struct asm_parser
*This
,
600 struct instruction
*instr
, int num
,
601 const struct shader_reg
*src
) {
602 if(!check_reg_type(src
, ps_3_reg_allowed
)) {
603 asmparser_message(This
, "Line %u: Source register %s not supported in PS 3.0\n",
605 debug_print_srcreg(src
, ST_PIXEL
));
606 set_parse_status(This
, PARSE_ERR
);
608 check_loop_swizzle(This
, src
);
609 check_legacy_srcmod(This
, src
->srcmod
);
610 memcpy(&instr
->src
[num
], src
, sizeof(*src
));
613 static void asmparser_dstreg_vs_1(struct asm_parser
*This
,
614 struct instruction
*instr
,
615 const struct shader_reg
*dst
) {
616 struct shader_reg reg
;
618 if(!check_reg_type(dst
, vs_1_reg_allowed
)) {
619 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 1\n",
621 debug_print_dstreg(dst
, ST_VERTEX
));
622 set_parse_status(This
, PARSE_ERR
);
624 check_ps_dstmod(This
, instr
->dstmod
);
625 check_shift_dstmod(This
, instr
->shift
);
626 reg
= map_oldvs_register(dst
);
627 memcpy(&instr
->dst
, ®
, sizeof(reg
));
628 instr
->has_dst
= TRUE
;
631 static void asmparser_dstreg_vs_2(struct asm_parser
*This
,
632 struct instruction
*instr
,
633 const struct shader_reg
*dst
) {
634 struct shader_reg reg
;
636 if(!check_reg_type(dst
, vs_2_reg_allowed
)) {
637 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 2.0\n",
639 debug_print_dstreg(dst
, ST_VERTEX
));
640 set_parse_status(This
, PARSE_ERR
);
642 check_ps_dstmod(This
, instr
->dstmod
);
643 check_shift_dstmod(This
, instr
->shift
);
644 reg
= map_oldvs_register(dst
);
645 memcpy(&instr
->dst
, ®
, sizeof(reg
));
646 instr
->has_dst
= TRUE
;
649 static void asmparser_dstreg_vs_3(struct asm_parser
*This
,
650 struct instruction
*instr
,
651 const struct shader_reg
*dst
) {
652 if(!check_reg_type(dst
, vs_3_reg_allowed
)) {
653 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 3.0\n",
655 debug_print_dstreg(dst
, ST_VERTEX
));
656 set_parse_status(This
, PARSE_ERR
);
658 check_ps_dstmod(This
, instr
->dstmod
);
659 check_shift_dstmod(This
, instr
->shift
);
660 memcpy(&instr
->dst
, dst
, sizeof(*dst
));
661 instr
->has_dst
= TRUE
;
664 static void asmparser_dstreg_ps_2(struct asm_parser
*This
,
665 struct instruction
*instr
,
666 const struct shader_reg
*dst
) {
667 struct shader_reg reg
;
669 if(!check_reg_type(dst
, ps_2_0_reg_allowed
)) {
670 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 2.0\n",
672 debug_print_dstreg(dst
, ST_PIXEL
));
673 set_parse_status(This
, PARSE_ERR
);
675 check_shift_dstmod(This
, instr
->shift
);
676 reg
= map_oldps_register(dst
, TRUE
);
677 memcpy(&instr
->dst
, ®
, sizeof(reg
));
678 instr
->has_dst
= TRUE
;
681 static void asmparser_dstreg_ps_2_x(struct asm_parser
*This
,
682 struct instruction
*instr
,
683 const struct shader_reg
*dst
) {
684 struct shader_reg reg
;
686 if(!check_reg_type(dst
, ps_2_x_reg_allowed
)) {
687 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 2.x\n",
689 debug_print_dstreg(dst
, ST_PIXEL
));
690 set_parse_status(This
, PARSE_ERR
);
692 check_shift_dstmod(This
, instr
->shift
);
693 reg
= map_oldps_register(dst
, TRUE
);
694 memcpy(&instr
->dst
, ®
, sizeof(reg
));
695 instr
->has_dst
= TRUE
;
698 static void asmparser_dstreg_ps_3(struct asm_parser
*This
,
699 struct instruction
*instr
,
700 const struct shader_reg
*dst
) {
701 if(!check_reg_type(dst
, ps_3_reg_allowed
)) {
702 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 3.0\n",
704 debug_print_dstreg(dst
, ST_PIXEL
));
705 set_parse_status(This
, PARSE_ERR
);
707 check_shift_dstmod(This
, instr
->shift
);
708 memcpy(&instr
->dst
, dst
, sizeof(*dst
));
709 instr
->has_dst
= TRUE
;
712 static void asmparser_predicate_supported(struct asm_parser
*This
,
713 const struct shader_reg
*predicate
) {
714 /* this sets the predicate of the last instruction added to the shader */
715 if(!This
->shader
) return;
716 if(This
->shader
->num_instrs
== 0) ERR("Predicate without an instruction\n");
717 This
->shader
->instr
[This
->shader
->num_instrs
- 1]->has_predicate
= TRUE
;
718 memcpy(&This
->shader
->instr
[This
->shader
->num_instrs
- 1]->predicate
, predicate
, sizeof(*predicate
));
721 static void asmparser_predicate_unsupported(struct asm_parser
*This
,
722 const struct shader_reg
*predicate
) {
723 asmparser_message(This
, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This
->line_no
);
724 set_parse_status(This
, PARSE_ERR
);
727 static void asmparser_coissue_unsupported(struct asm_parser
*This
) {
728 asmparser_message(This
, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This
->line_no
);
729 set_parse_status(This
, PARSE_ERR
);
732 static const struct asmparser_backend parser_vs_1
= {
737 asmparser_dstreg_vs_1
,
738 asmparser_srcreg_vs_1
,
740 asmparser_predicate_unsupported
,
741 asmparser_coissue_unsupported
,
743 asmparser_dcl_output
,
745 asmparser_dcl_sampler
,
752 static const struct asmparser_backend parser_vs_2
= {
757 asmparser_dstreg_vs_2
,
758 asmparser_srcreg_vs_2
,
760 asmparser_predicate_supported
,
761 asmparser_coissue_unsupported
,
763 asmparser_dcl_output
,
765 asmparser_dcl_sampler
,
772 static const struct asmparser_backend parser_vs_3
= {
777 asmparser_dstreg_vs_3
,
778 asmparser_srcreg_vs_3
,
780 asmparser_predicate_supported
,
781 asmparser_coissue_unsupported
,
783 asmparser_dcl_output
,
785 asmparser_dcl_sampler
,
792 static const struct asmparser_backend parser_ps_2
= {
797 asmparser_dstreg_ps_2
,
798 asmparser_srcreg_ps_2
,
800 asmparser_predicate_unsupported
,
801 asmparser_coissue_unsupported
,
803 asmparser_dcl_output
,
805 asmparser_dcl_sampler
,
812 static const struct asmparser_backend parser_ps_2_x
= {
817 asmparser_dstreg_ps_2_x
,
818 asmparser_srcreg_ps_2_x
,
820 asmparser_predicate_supported
,
821 asmparser_coissue_unsupported
,
823 asmparser_dcl_output
,
825 asmparser_dcl_sampler
,
832 static const struct asmparser_backend parser_ps_3
= {
837 asmparser_dstreg_ps_3
,
838 asmparser_srcreg_ps_3
,
840 asmparser_predicate_supported
,
841 asmparser_coissue_unsupported
,
843 asmparser_dcl_output
,
845 asmparser_dcl_sampler
,
852 static void gen_oldvs_output(struct bwriter_shader
*shader
) {
853 record_declaration(shader
, BWRITERDECLUSAGE_POSITION
, 0, 0, TRUE
, OPOS_REG
, BWRITERSP_WRITEMASK_ALL
);
854 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 0, 0, TRUE
, OT0_REG
, BWRITERSP_WRITEMASK_ALL
);
855 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 1, 0, TRUE
, OT1_REG
, BWRITERSP_WRITEMASK_ALL
);
856 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 2, 0, TRUE
, OT2_REG
, BWRITERSP_WRITEMASK_ALL
);
857 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 3, 0, TRUE
, OT3_REG
, BWRITERSP_WRITEMASK_ALL
);
858 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 4, 0, TRUE
, OT4_REG
, BWRITERSP_WRITEMASK_ALL
);
859 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 5, 0, TRUE
, OT5_REG
, BWRITERSP_WRITEMASK_ALL
);
860 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 6, 0, TRUE
, OT6_REG
, BWRITERSP_WRITEMASK_ALL
);
861 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 7, 0, TRUE
, OT7_REG
, BWRITERSP_WRITEMASK_ALL
);
862 record_declaration(shader
, BWRITERDECLUSAGE_FOG
, 0, 0, TRUE
, OFOG_REG
, OFOG_WRITEMASK
);
863 record_declaration(shader
, BWRITERDECLUSAGE_PSIZE
, 0, 0, TRUE
, OPTS_REG
, OPTS_WRITEMASK
);
864 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 0, 0, TRUE
, OD0_REG
, BWRITERSP_WRITEMASK_ALL
);
865 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 1, 0, TRUE
, OD1_REG
, BWRITERSP_WRITEMASK_ALL
);
868 static void gen_oldps_input(struct bwriter_shader
*shader
, DWORD texcoords
) {
870 case 8: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 7, 0, FALSE
, T7_VARYING
, BWRITERSP_WRITEMASK_ALL
);
871 case 7: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 6, 0, FALSE
, T6_VARYING
, BWRITERSP_WRITEMASK_ALL
);
872 case 6: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 5, 0, FALSE
, T5_VARYING
, BWRITERSP_WRITEMASK_ALL
);
873 case 5: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 4, 0, FALSE
, T4_VARYING
, BWRITERSP_WRITEMASK_ALL
);
874 case 4: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 3, 0, FALSE
, T3_VARYING
, BWRITERSP_WRITEMASK_ALL
);
875 case 3: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 2, 0, FALSE
, T2_VARYING
, BWRITERSP_WRITEMASK_ALL
);
876 case 2: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 1, 0, FALSE
, T1_VARYING
, BWRITERSP_WRITEMASK_ALL
);
877 case 1: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 0, 0, FALSE
, T0_VARYING
, BWRITERSP_WRITEMASK_ALL
);
879 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 0, 0, FALSE
, C0_VARYING
, BWRITERSP_WRITEMASK_ALL
);
880 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 1, 0, FALSE
, C1_VARYING
, BWRITERSP_WRITEMASK_ALL
);
883 void create_vs10_parser(struct asm_parser
*ret
) {
884 TRACE_(parsed_shader
)("vs_1_0\n");
886 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
888 ERR("Failed to allocate memory for the shader\n");
889 set_parse_status(ret
, PARSE_ERR
);
893 ret
->shader
->type
= ST_VERTEX
;
894 ret
->shader
->version
= BWRITERVS_VERSION(1, 0);
895 ret
->funcs
= &parser_vs_1
;
896 gen_oldvs_output(ret
->shader
);
899 void create_vs11_parser(struct asm_parser
*ret
) {
900 TRACE_(parsed_shader
)("vs_1_1\n");
902 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
904 ERR("Failed to allocate memory for the shader\n");
905 set_parse_status(ret
, PARSE_ERR
);
909 ret
->shader
->type
= ST_VERTEX
;
910 ret
->shader
->version
= BWRITERVS_VERSION(1, 1);
911 ret
->funcs
= &parser_vs_1
;
912 gen_oldvs_output(ret
->shader
);
915 void create_vs20_parser(struct asm_parser
*ret
) {
916 TRACE_(parsed_shader
)("vs_2_0\n");
918 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
920 ERR("Failed to allocate memory for the shader\n");
921 set_parse_status(ret
, PARSE_ERR
);
925 ret
->shader
->type
= ST_VERTEX
;
926 ret
->shader
->version
= BWRITERVS_VERSION(2, 0);
927 ret
->funcs
= &parser_vs_2
;
928 gen_oldvs_output(ret
->shader
);
931 void create_vs2x_parser(struct asm_parser
*ret
) {
932 TRACE_(parsed_shader
)("vs_2_x\n");
934 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
936 ERR("Failed to allocate memory for the shader\n");
937 set_parse_status(ret
, PARSE_ERR
);
941 ret
->shader
->type
= ST_VERTEX
;
942 ret
->shader
->version
= BWRITERVS_VERSION(2, 1);
943 ret
->funcs
= &parser_vs_2
;
944 gen_oldvs_output(ret
->shader
);
947 void create_vs30_parser(struct asm_parser
*ret
) {
948 TRACE_(parsed_shader
)("vs_3_0\n");
950 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
952 ERR("Failed to allocate memory for the shader\n");
953 set_parse_status(ret
, PARSE_ERR
);
957 ret
->shader
->type
= ST_VERTEX
;
958 ret
->shader
->version
= BWRITERVS_VERSION(3, 0);
959 ret
->funcs
= &parser_vs_3
;
962 void create_ps20_parser(struct asm_parser
*ret
) {
963 TRACE_(parsed_shader
)("ps_2_0\n");
965 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
967 ERR("Failed to allocate memory for the shader\n");
968 set_parse_status(ret
, PARSE_ERR
);
972 ret
->shader
->type
= ST_PIXEL
;
973 ret
->shader
->version
= BWRITERPS_VERSION(2, 0);
974 ret
->funcs
= &parser_ps_2
;
975 gen_oldps_input(ret
->shader
, 8);
978 void create_ps2x_parser(struct asm_parser
*ret
) {
979 TRACE_(parsed_shader
)("ps_2_x\n");
981 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
983 ERR("Failed to allocate memory for the shader\n");
984 set_parse_status(ret
, PARSE_ERR
);
988 ret
->shader
->type
= ST_PIXEL
;
989 ret
->shader
->version
= BWRITERPS_VERSION(2, 1);
990 ret
->funcs
= &parser_ps_2_x
;
991 gen_oldps_input(ret
->shader
, 8);
994 void create_ps30_parser(struct asm_parser
*ret
) {
995 TRACE_(parsed_shader
)("ps_3_0\n");
997 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
999 ERR("Failed to allocate memory for the shader\n");
1000 set_parse_status(ret
, PARSE_ERR
);
1004 ret
->shader
->type
= ST_PIXEL
;
1005 ret
->shader
->version
= BWRITERPS_VERSION(3, 0);
1006 ret
->funcs
= &parser_ps_3
;