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_dcl_sampler_unsupported(struct asm_parser
*This
, DWORD samptype
,
182 DWORD mod
, DWORD regnum
,
183 unsigned int line_no
) {
184 asmparser_message(This
, "Line %u: Sampler declaration unsupported in this shader version\n", This
->line_no
);
185 set_parse_status(This
, PARSE_ERR
);
188 static void asmparser_sincos(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
189 const struct shader_reg
*dst
,
190 const struct src_regs
*srcs
) {
191 struct instruction
*instr
;
193 if(!srcs
|| srcs
->count
!= 3) {
194 asmparser_message(This
, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This
->line_no
);
195 set_parse_status(This
, PARSE_ERR
);
199 instr
= alloc_instr(3);
201 ERR("Error allocating memory for the instruction\n");
202 set_parse_status(This
, PARSE_ERR
);
206 instr
->opcode
= BWRITERSIO_SINCOS
;
208 instr
->shift
= shift
;
211 This
->funcs
->dstreg(This
, instr
, dst
);
212 This
->funcs
->srcreg(This
, instr
, 0, &srcs
->reg
[0]);
213 This
->funcs
->srcreg(This
, instr
, 1, &srcs
->reg
[1]);
214 This
->funcs
->srcreg(This
, instr
, 2, &srcs
->reg
[2]);
216 if(!add_instruction(This
->shader
, instr
)) {
217 ERR("Out of memory\n");
218 set_parse_status(This
, PARSE_ERR
);
222 static void asmparser_instr(struct asm_parser
*This
, DWORD opcode
,
223 DWORD mod
, DWORD shift
,
224 BWRITER_COMPARISON_TYPE comp
,
225 const struct shader_reg
*dst
,
226 const struct src_regs
*srcs
, int expectednsrcs
) {
227 struct instruction
*instr
;
229 BOOL firstreg
= TRUE
;
230 unsigned int src_count
= srcs
? srcs
->count
: 0;
232 if(!This
->shader
) return;
234 TRACE_(parsed_shader
)("%s%s%s ", debug_print_opcode(opcode
),
235 debug_print_dstmod(mod
),
236 debug_print_comp(comp
));
238 TRACE_(parsed_shader
)("%s", debug_print_dstreg(dst
, This
->shader
->type
));
241 for(i
= 0; i
< src_count
; i
++) {
242 if(!firstreg
) TRACE_(parsed_shader
)(", ");
243 else firstreg
= FALSE
;
244 TRACE_(parsed_shader
)("%s", debug_print_srcreg(&srcs
->reg
[i
],
245 This
->shader
->type
));
247 TRACE_(parsed_shader
)("\n");
249 /* Check for instructions with different syntaxes in different shader versio
252 case BWRITERSIO_SINCOS
:
253 /* The syntax changes between vs 2 and the other shader versions */
254 if(This
->shader
->version
== BWRITERVS_VERSION(2, 0) ||
255 This
->shader
->version
== BWRITERVS_VERSION(2, 1)) {
256 asmparser_sincos(This
, mod
, shift
, dst
, srcs
);
259 /* Use the default handling */
263 if(src_count
!= expectednsrcs
) {
264 asmparser_message(This
, "Line %u: Wrong number of source registers\n", This
->line_no
);
265 set_parse_status(This
, PARSE_ERR
);
269 instr
= alloc_instr(src_count
);
271 ERR("Error allocating memory for the instruction\n");
272 set_parse_status(This
, PARSE_ERR
);
276 instr
->opcode
= opcode
;
278 instr
->shift
= shift
;
279 instr
->comptype
= comp
;
280 if(dst
) This
->funcs
->dstreg(This
, instr
, dst
);
281 for(i
= 0; i
< src_count
; i
++) {
282 This
->funcs
->srcreg(This
, instr
, i
, &srcs
->reg
[i
]);
285 if(!add_instruction(This
->shader
, instr
)) {
286 ERR("Out of memory\n");
287 set_parse_status(This
, PARSE_ERR
);
291 static struct shader_reg
map_oldvs_register(const struct shader_reg
*reg
) {
292 struct shader_reg ret
;
294 case BWRITERSPR_RASTOUT
:
296 ret
.type
= BWRITERSPR_OUTPUT
;
297 switch(reg
->regnum
) {
298 case BWRITERSRO_POSITION
:
299 ret
.regnum
= OPOS_REG
;
302 ret
.regnum
= OFOG_REG
;
303 ret
.writemask
= OFOG_WRITEMASK
;
305 case BWRITERSRO_POINT_SIZE
:
306 ret
.regnum
= OPTS_REG
;
307 ret
.writemask
= OPTS_WRITEMASK
;
310 FIXME("Unhandled RASTOUT register %u\n", reg
->regnum
);
315 case BWRITERSPR_TEXCRDOUT
:
317 ret
.type
= BWRITERSPR_OUTPUT
;
318 switch(reg
->regnum
) {
319 case 0: ret
.regnum
= OT0_REG
; break;
320 case 1: ret
.regnum
= OT1_REG
; break;
321 case 2: ret
.regnum
= OT2_REG
; break;
322 case 3: ret
.regnum
= OT3_REG
; break;
323 case 4: ret
.regnum
= OT4_REG
; break;
324 case 5: ret
.regnum
= OT5_REG
; break;
325 case 6: ret
.regnum
= OT6_REG
; break;
326 case 7: ret
.regnum
= OT7_REG
; break;
328 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg
->regnum
);
333 case BWRITERSPR_ATTROUT
:
335 ret
.type
= BWRITERSPR_OUTPUT
;
336 switch(reg
->regnum
) {
337 case 0: ret
.regnum
= OD0_REG
; break;
338 case 1: ret
.regnum
= OD1_REG
; break;
340 FIXME("Unhandled ATTROUT regnum %u\n", reg
->regnum
);
345 default: return *reg
;
349 static struct shader_reg
map_oldps_register(const struct shader_reg
*reg
, BOOL tex_varying
) {
350 struct shader_reg ret
;
352 case BWRITERSPR_TEXTURE
:
355 ret
.type
= BWRITERSPR_INPUT
;
356 switch(reg
->regnum
) {
357 case 0: ret
.regnum
= T0_VARYING
; break;
358 case 1: ret
.regnum
= T1_VARYING
; break;
359 case 2: ret
.regnum
= T2_VARYING
; break;
360 case 3: ret
.regnum
= T3_VARYING
; break;
361 case 4: ret
.regnum
= T4_VARYING
; break;
362 case 5: ret
.regnum
= T5_VARYING
; break;
363 case 6: ret
.regnum
= T6_VARYING
; break;
364 case 7: ret
.regnum
= T7_VARYING
; break;
366 FIXME("Unexpected TEXTURE register t%u\n", reg
->regnum
);
371 FIXME("TODO: ps_1_x texture register mapping\n");
375 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
378 default: return *reg
;
382 /* Checks for unsupported source modifiers in VS (all versions) or
384 static void check_legacy_srcmod(struct asm_parser
*This
, DWORD srcmod
) {
385 if(srcmod
== BWRITERSPSM_BIAS
|| srcmod
== BWRITERSPSM_BIASNEG
||
386 srcmod
== BWRITERSPSM_SIGN
|| srcmod
== BWRITERSPSM_SIGNNEG
||
387 srcmod
== BWRITERSPSM_COMP
|| srcmod
== BWRITERSPSM_X2
||
388 srcmod
== BWRITERSPSM_X2NEG
|| srcmod
== BWRITERSPSM_DZ
||
389 srcmod
== BWRITERSPSM_DW
) {
390 asmparser_message(This
, "Line %u: Source modifier %s not supported in this shader version\n",
392 debug_print_srcmod(srcmod
));
393 set_parse_status(This
, PARSE_ERR
);
397 static void check_abs_srcmod(struct asm_parser
*This
, DWORD srcmod
) {
398 if(srcmod
== BWRITERSPSM_ABS
|| srcmod
== BWRITERSPSM_ABSNEG
) {
399 asmparser_message(This
, "Line %u: Source modifier %s not supported in this shader version\n",
401 debug_print_srcmod(srcmod
));
402 set_parse_status(This
, PARSE_ERR
);
406 static void check_loop_swizzle(struct asm_parser
*This
,
407 const struct shader_reg
*src
) {
408 if((src
->type
== BWRITERSPR_LOOP
&& src
->swizzle
!= BWRITERVS_NOSWIZZLE
) ||
409 (src
->rel_reg
&& src
->rel_reg
->type
== BWRITERSPR_LOOP
&&
410 src
->rel_reg
->swizzle
!= BWRITERVS_NOSWIZZLE
)) {
411 asmparser_message(This
, "Line %u: Swizzle not allowed on aL register\n", This
->line_no
);
412 set_parse_status(This
, PARSE_ERR
);
416 static void check_shift_dstmod(struct asm_parser
*This
, DWORD shift
) {
418 asmparser_message(This
, "Line %u: Shift modifiers not supported in this shader version\n",
420 set_parse_status(This
, PARSE_ERR
);
424 static void check_ps_dstmod(struct asm_parser
*This
, DWORD dstmod
) {
425 if(dstmod
== BWRITERSPDM_PARTIALPRECISION
||
426 dstmod
== BWRITERSPDM_MSAMPCENTROID
) {
427 asmparser_message(This
, "Line %u: Instruction modifier %s not supported in this shader version\n",
429 debug_print_dstmod(dstmod
));
430 set_parse_status(This
, PARSE_ERR
);
434 struct allowed_reg_type
{
440 static BOOL
check_reg_type(const struct shader_reg
*reg
,
441 const struct allowed_reg_type
*allowed
) {
444 while(allowed
[i
].type
!= ~0U) {
445 if(reg
->type
== allowed
[i
].type
) {
447 if(allowed
[i
].reladdr
)
448 return TRUE
; /* The relative addressing register
449 can have a negative value, we
450 can't check the register index */
453 if(reg
->regnum
< allowed
[i
].count
) return TRUE
;
461 /* Native assembler doesn't do separate checks for src and dst registers */
462 static const struct allowed_reg_type vs_1_reg_allowed
[] = {
463 { BWRITERSPR_TEMP
, 12, FALSE
},
464 { BWRITERSPR_INPUT
, 16, FALSE
},
465 { BWRITERSPR_CONST
, ~0U, TRUE
},
466 { BWRITERSPR_ADDR
, 1, FALSE
},
467 { BWRITERSPR_RASTOUT
, 3, FALSE
}, /* oPos, oFog and oPts */
468 { BWRITERSPR_ATTROUT
, 2, FALSE
},
469 { BWRITERSPR_TEXCRDOUT
, 8, FALSE
},
470 { ~0U, 0 } /* End tag */
473 /* struct instruction *asmparser_srcreg
475 * Records a source register in the instruction and does shader version
476 * specific checks and modifications on it
479 * This: Shader parser instance
480 * instr: instruction to store the register in
481 * num: Number of source register
482 * src: Pointer to source the register structure. The caller can free
485 static void asmparser_srcreg_vs_1(struct asm_parser
*This
,
486 struct instruction
*instr
, int num
,
487 const struct shader_reg
*src
) {
488 struct shader_reg reg
;
490 if(!check_reg_type(src
, vs_1_reg_allowed
)) {
491 asmparser_message(This
, "Line %u: Source register %s not supported in VS 1\n",
493 debug_print_srcreg(src
, ST_VERTEX
));
494 set_parse_status(This
, PARSE_ERR
);
496 check_legacy_srcmod(This
, src
->srcmod
);
497 check_abs_srcmod(This
, src
->srcmod
);
498 reg
= map_oldvs_register(src
);
499 memcpy(&instr
->src
[num
], ®
, sizeof(reg
));
502 static const struct allowed_reg_type vs_2_reg_allowed
[] = {
503 { BWRITERSPR_TEMP
, 12, FALSE
},
504 { BWRITERSPR_INPUT
, 16, FALSE
},
505 { BWRITERSPR_CONST
, ~0U, TRUE
},
506 { BWRITERSPR_ADDR
, 1, FALSE
},
507 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
508 { BWRITERSPR_CONSTINT
, 16, FALSE
},
509 { BWRITERSPR_LOOP
, 1, FALSE
},
510 { BWRITERSPR_LABEL
, 2048, FALSE
},
511 { BWRITERSPR_PREDICATE
, 1, FALSE
},
512 { BWRITERSPR_RASTOUT
, 3, FALSE
}, /* oPos, oFog and oPts */
513 { BWRITERSPR_ATTROUT
, 2, FALSE
},
514 { BWRITERSPR_TEXCRDOUT
, 8, FALSE
},
515 { ~0U, 0 } /* End tag */
518 static void asmparser_srcreg_vs_2(struct asm_parser
*This
,
519 struct instruction
*instr
, int num
,
520 const struct shader_reg
*src
) {
521 struct shader_reg reg
;
523 if(!check_reg_type(src
, vs_2_reg_allowed
)) {
524 asmparser_message(This
, "Line %u: Source register %s not supported in VS 2\n",
526 debug_print_srcreg(src
, ST_VERTEX
));
527 set_parse_status(This
, PARSE_ERR
);
529 check_loop_swizzle(This
, src
);
530 check_legacy_srcmod(This
, src
->srcmod
);
531 check_abs_srcmod(This
, src
->srcmod
);
532 reg
= map_oldvs_register(src
);
533 memcpy(&instr
->src
[num
], ®
, sizeof(reg
));
536 static const struct allowed_reg_type vs_3_reg_allowed
[] = {
537 { BWRITERSPR_TEMP
, 32, FALSE
},
538 { BWRITERSPR_INPUT
, 16, TRUE
},
539 { BWRITERSPR_CONST
, ~0U, TRUE
},
540 { BWRITERSPR_ADDR
, 1, FALSE
},
541 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
542 { BWRITERSPR_CONSTINT
, 16, FALSE
},
543 { BWRITERSPR_LOOP
, 1, FALSE
},
544 { BWRITERSPR_LABEL
, 2048, FALSE
},
545 { BWRITERSPR_PREDICATE
, 1, FALSE
},
546 { BWRITERSPR_SAMPLER
, 4, FALSE
},
547 { BWRITERSPR_OUTPUT
, 12, TRUE
},
548 { ~0U, 0 } /* End tag */
551 static void asmparser_srcreg_vs_3(struct asm_parser
*This
,
552 struct instruction
*instr
, int num
,
553 const struct shader_reg
*src
) {
554 if(!check_reg_type(src
, vs_3_reg_allowed
)) {
555 asmparser_message(This
, "Line %u: Source register %s not supported in VS 3.0\n",
557 debug_print_srcreg(src
, ST_VERTEX
));
558 set_parse_status(This
, PARSE_ERR
);
560 check_loop_swizzle(This
, src
);
561 check_legacy_srcmod(This
, src
->srcmod
);
562 memcpy(&instr
->src
[num
], src
, sizeof(*src
));
565 static const struct allowed_reg_type ps_2_0_reg_allowed
[] = {
566 { BWRITERSPR_INPUT
, 2, FALSE
},
567 { BWRITERSPR_TEMP
, 32, FALSE
},
568 { BWRITERSPR_CONST
, 32, FALSE
},
569 { BWRITERSPR_CONSTINT
, 16, FALSE
},
570 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
571 { BWRITERSPR_SAMPLER
, 16, FALSE
},
572 { BWRITERSPR_TEXTURE
, 8, FALSE
},
573 { BWRITERSPR_COLOROUT
, 4, FALSE
},
574 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
575 { ~0U, 0 } /* End tag */
578 static void asmparser_srcreg_ps_2(struct asm_parser
*This
,
579 struct instruction
*instr
, int num
,
580 const struct shader_reg
*src
) {
581 struct shader_reg reg
;
583 if(!check_reg_type(src
, ps_2_0_reg_allowed
)) {
584 asmparser_message(This
, "Line %u: Source register %s not supported in PS 2.0\n",
586 debug_print_srcreg(src
, ST_PIXEL
));
587 set_parse_status(This
, PARSE_ERR
);
589 check_legacy_srcmod(This
, src
->srcmod
);
590 check_abs_srcmod(This
, src
->srcmod
);
591 reg
= map_oldps_register(src
, TRUE
);
592 memcpy(&instr
->src
[num
], ®
, sizeof(reg
));
595 static const struct allowed_reg_type ps_2_x_reg_allowed
[] = {
596 { BWRITERSPR_INPUT
, 2, FALSE
},
597 { BWRITERSPR_TEMP
, 32, FALSE
},
598 { BWRITERSPR_CONST
, 32, FALSE
},
599 { BWRITERSPR_CONSTINT
, 16, FALSE
},
600 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
601 { BWRITERSPR_PREDICATE
, 1, FALSE
},
602 { BWRITERSPR_SAMPLER
, 16, FALSE
},
603 { BWRITERSPR_TEXTURE
, 8, FALSE
},
604 { BWRITERSPR_LABEL
, 2048, FALSE
},
605 { BWRITERSPR_COLOROUT
, 4, FALSE
},
606 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
607 { ~0U, 0 } /* End tag */
610 static void asmparser_srcreg_ps_2_x(struct asm_parser
*This
,
611 struct instruction
*instr
, int num
,
612 const struct shader_reg
*src
) {
613 struct shader_reg reg
;
615 if(!check_reg_type(src
, ps_2_x_reg_allowed
)) {
616 asmparser_message(This
, "Line %u: Source register %s not supported in PS 2.x\n",
618 debug_print_srcreg(src
, ST_PIXEL
));
619 set_parse_status(This
, PARSE_ERR
);
621 check_legacy_srcmod(This
, src
->srcmod
);
622 check_abs_srcmod(This
, src
->srcmod
);
623 reg
= map_oldps_register(src
, TRUE
);
624 memcpy(&instr
->src
[num
], ®
, sizeof(reg
));
627 static const struct allowed_reg_type ps_3_reg_allowed
[] = {
628 { BWRITERSPR_INPUT
, 10, TRUE
},
629 { BWRITERSPR_TEMP
, 32, FALSE
},
630 { BWRITERSPR_CONST
, 224, FALSE
},
631 { BWRITERSPR_CONSTINT
, 16, FALSE
},
632 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
633 { BWRITERSPR_PREDICATE
, 1, FALSE
},
634 { BWRITERSPR_SAMPLER
, 16, FALSE
},
635 { BWRITERSPR_MISCTYPE
, 2, FALSE
}, /* vPos and vFace */
636 { BWRITERSPR_LOOP
, 1, FALSE
},
637 { BWRITERSPR_LABEL
, 2048, FALSE
},
638 { BWRITERSPR_COLOROUT
, 4, FALSE
},
639 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
640 { ~0U, 0 } /* End tag */
643 static void asmparser_srcreg_ps_3(struct asm_parser
*This
,
644 struct instruction
*instr
, int num
,
645 const struct shader_reg
*src
) {
646 if(!check_reg_type(src
, ps_3_reg_allowed
)) {
647 asmparser_message(This
, "Line %u: Source register %s not supported in PS 3.0\n",
649 debug_print_srcreg(src
, ST_PIXEL
));
650 set_parse_status(This
, PARSE_ERR
);
652 check_loop_swizzle(This
, src
);
653 check_legacy_srcmod(This
, src
->srcmod
);
654 memcpy(&instr
->src
[num
], src
, sizeof(*src
));
657 static void asmparser_dstreg_vs_1(struct asm_parser
*This
,
658 struct instruction
*instr
,
659 const struct shader_reg
*dst
) {
660 struct shader_reg reg
;
662 if(!check_reg_type(dst
, vs_1_reg_allowed
)) {
663 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 1\n",
665 debug_print_dstreg(dst
, ST_VERTEX
));
666 set_parse_status(This
, PARSE_ERR
);
668 check_ps_dstmod(This
, instr
->dstmod
);
669 check_shift_dstmod(This
, instr
->shift
);
670 reg
= map_oldvs_register(dst
);
671 memcpy(&instr
->dst
, ®
, sizeof(reg
));
672 instr
->has_dst
= TRUE
;
675 static void asmparser_dstreg_vs_2(struct asm_parser
*This
,
676 struct instruction
*instr
,
677 const struct shader_reg
*dst
) {
678 struct shader_reg reg
;
680 if(!check_reg_type(dst
, vs_2_reg_allowed
)) {
681 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 2.0\n",
683 debug_print_dstreg(dst
, ST_VERTEX
));
684 set_parse_status(This
, PARSE_ERR
);
686 check_ps_dstmod(This
, instr
->dstmod
);
687 check_shift_dstmod(This
, instr
->shift
);
688 reg
= map_oldvs_register(dst
);
689 memcpy(&instr
->dst
, ®
, sizeof(reg
));
690 instr
->has_dst
= TRUE
;
693 static void asmparser_dstreg_vs_3(struct asm_parser
*This
,
694 struct instruction
*instr
,
695 const struct shader_reg
*dst
) {
696 if(!check_reg_type(dst
, vs_3_reg_allowed
)) {
697 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 3.0\n",
699 debug_print_dstreg(dst
, ST_VERTEX
));
700 set_parse_status(This
, PARSE_ERR
);
702 check_ps_dstmod(This
, instr
->dstmod
);
703 check_shift_dstmod(This
, instr
->shift
);
704 memcpy(&instr
->dst
, dst
, sizeof(*dst
));
705 instr
->has_dst
= TRUE
;
708 static void asmparser_dstreg_ps_2(struct asm_parser
*This
,
709 struct instruction
*instr
,
710 const struct shader_reg
*dst
) {
711 struct shader_reg reg
;
713 if(!check_reg_type(dst
, ps_2_0_reg_allowed
)) {
714 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 2.0\n",
716 debug_print_dstreg(dst
, ST_PIXEL
));
717 set_parse_status(This
, PARSE_ERR
);
719 check_shift_dstmod(This
, instr
->shift
);
720 reg
= map_oldps_register(dst
, TRUE
);
721 memcpy(&instr
->dst
, ®
, sizeof(reg
));
722 instr
->has_dst
= TRUE
;
725 static void asmparser_dstreg_ps_2_x(struct asm_parser
*This
,
726 struct instruction
*instr
,
727 const struct shader_reg
*dst
) {
728 struct shader_reg reg
;
730 if(!check_reg_type(dst
, ps_2_x_reg_allowed
)) {
731 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 2.x\n",
733 debug_print_dstreg(dst
, ST_PIXEL
));
734 set_parse_status(This
, PARSE_ERR
);
736 check_shift_dstmod(This
, instr
->shift
);
737 reg
= map_oldps_register(dst
, TRUE
);
738 memcpy(&instr
->dst
, ®
, sizeof(reg
));
739 instr
->has_dst
= TRUE
;
742 static void asmparser_dstreg_ps_3(struct asm_parser
*This
,
743 struct instruction
*instr
,
744 const struct shader_reg
*dst
) {
745 if(!check_reg_type(dst
, ps_3_reg_allowed
)) {
746 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 3.0\n",
748 debug_print_dstreg(dst
, ST_PIXEL
));
749 set_parse_status(This
, PARSE_ERR
);
751 check_shift_dstmod(This
, instr
->shift
);
752 memcpy(&instr
->dst
, dst
, sizeof(*dst
));
753 instr
->has_dst
= TRUE
;
756 static void asmparser_predicate_supported(struct asm_parser
*This
,
757 const struct shader_reg
*predicate
) {
758 /* this sets the predicate of the last instruction added to the shader */
759 if(!This
->shader
) return;
760 if(This
->shader
->num_instrs
== 0) ERR("Predicate without an instruction\n");
761 This
->shader
->instr
[This
->shader
->num_instrs
- 1]->has_predicate
= TRUE
;
762 memcpy(&This
->shader
->instr
[This
->shader
->num_instrs
- 1]->predicate
, predicate
, sizeof(*predicate
));
765 static void asmparser_predicate_unsupported(struct asm_parser
*This
,
766 const struct shader_reg
*predicate
) {
767 asmparser_message(This
, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This
->line_no
);
768 set_parse_status(This
, PARSE_ERR
);
771 static void asmparser_coissue_unsupported(struct asm_parser
*This
) {
772 asmparser_message(This
, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This
->line_no
);
773 set_parse_status(This
, PARSE_ERR
);
776 static const struct asmparser_backend parser_vs_1
= {
781 asmparser_dstreg_vs_1
,
782 asmparser_srcreg_vs_1
,
784 asmparser_predicate_unsupported
,
785 asmparser_coissue_unsupported
,
787 asmparser_dcl_output
,
789 asmparser_dcl_sampler_unsupported
,
796 static const struct asmparser_backend parser_vs_2
= {
801 asmparser_dstreg_vs_2
,
802 asmparser_srcreg_vs_2
,
804 asmparser_predicate_supported
,
805 asmparser_coissue_unsupported
,
807 asmparser_dcl_output
,
809 asmparser_dcl_sampler_unsupported
,
816 static const struct asmparser_backend parser_vs_3
= {
821 asmparser_dstreg_vs_3
,
822 asmparser_srcreg_vs_3
,
824 asmparser_predicate_supported
,
825 asmparser_coissue_unsupported
,
827 asmparser_dcl_output
,
829 asmparser_dcl_sampler
,
836 static const struct asmparser_backend parser_ps_2
= {
841 asmparser_dstreg_ps_2
,
842 asmparser_srcreg_ps_2
,
844 asmparser_predicate_unsupported
,
845 asmparser_coissue_unsupported
,
847 asmparser_dcl_output
,
848 asmparser_dcl_input_ps_2
,
849 asmparser_dcl_sampler
,
856 static const struct asmparser_backend parser_ps_2_x
= {
861 asmparser_dstreg_ps_2_x
,
862 asmparser_srcreg_ps_2_x
,
864 asmparser_predicate_supported
,
865 asmparser_coissue_unsupported
,
867 asmparser_dcl_output
,
868 asmparser_dcl_input_ps_2
,
869 asmparser_dcl_sampler
,
876 static const struct asmparser_backend parser_ps_3
= {
881 asmparser_dstreg_ps_3
,
882 asmparser_srcreg_ps_3
,
884 asmparser_predicate_supported
,
885 asmparser_coissue_unsupported
,
887 asmparser_dcl_output
,
889 asmparser_dcl_sampler
,
896 static void gen_oldvs_output(struct bwriter_shader
*shader
) {
897 record_declaration(shader
, BWRITERDECLUSAGE_POSITION
, 0, 0, TRUE
, OPOS_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
898 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 0, 0, TRUE
, OT0_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
899 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 1, 0, TRUE
, OT1_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
900 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 2, 0, TRUE
, OT2_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
901 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 3, 0, TRUE
, OT3_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
902 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 4, 0, TRUE
, OT4_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
903 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 5, 0, TRUE
, OT5_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
904 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 6, 0, TRUE
, OT6_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
905 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 7, 0, TRUE
, OT7_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
906 record_declaration(shader
, BWRITERDECLUSAGE_FOG
, 0, 0, TRUE
, OFOG_REG
, OFOG_WRITEMASK
, TRUE
);
907 record_declaration(shader
, BWRITERDECLUSAGE_PSIZE
, 0, 0, TRUE
, OPTS_REG
, OPTS_WRITEMASK
, TRUE
);
908 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 0, 0, TRUE
, OD0_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
909 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 1, 0, TRUE
, OD1_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
912 static void gen_oldps_input(struct bwriter_shader
*shader
, DWORD texcoords
) {
914 case 8: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 7, 0, FALSE
, T7_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
915 case 7: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 6, 0, FALSE
, T6_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
916 case 6: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 5, 0, FALSE
, T5_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
917 case 5: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 4, 0, FALSE
, T4_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
918 case 4: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 3, 0, FALSE
, T3_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
919 case 3: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 2, 0, FALSE
, T2_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
920 case 2: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 1, 0, FALSE
, T1_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
921 case 1: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 0, 0, FALSE
, T0_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
923 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 0, 0, FALSE
, C0_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
924 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 1, 0, FALSE
, C1_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
927 void create_vs10_parser(struct asm_parser
*ret
) {
928 TRACE_(parsed_shader
)("vs_1_0\n");
930 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
932 ERR("Failed to allocate memory for the shader\n");
933 set_parse_status(ret
, PARSE_ERR
);
937 ret
->shader
->type
= ST_VERTEX
;
938 ret
->shader
->version
= BWRITERVS_VERSION(1, 0);
939 ret
->funcs
= &parser_vs_1
;
940 gen_oldvs_output(ret
->shader
);
943 void create_vs11_parser(struct asm_parser
*ret
) {
944 TRACE_(parsed_shader
)("vs_1_1\n");
946 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
948 ERR("Failed to allocate memory for the shader\n");
949 set_parse_status(ret
, PARSE_ERR
);
953 ret
->shader
->type
= ST_VERTEX
;
954 ret
->shader
->version
= BWRITERVS_VERSION(1, 1);
955 ret
->funcs
= &parser_vs_1
;
956 gen_oldvs_output(ret
->shader
);
959 void create_vs20_parser(struct asm_parser
*ret
) {
960 TRACE_(parsed_shader
)("vs_2_0\n");
962 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
964 ERR("Failed to allocate memory for the shader\n");
965 set_parse_status(ret
, PARSE_ERR
);
969 ret
->shader
->type
= ST_VERTEX
;
970 ret
->shader
->version
= BWRITERVS_VERSION(2, 0);
971 ret
->funcs
= &parser_vs_2
;
972 gen_oldvs_output(ret
->shader
);
975 void create_vs2x_parser(struct asm_parser
*ret
) {
976 TRACE_(parsed_shader
)("vs_2_x\n");
978 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
980 ERR("Failed to allocate memory for the shader\n");
981 set_parse_status(ret
, PARSE_ERR
);
985 ret
->shader
->type
= ST_VERTEX
;
986 ret
->shader
->version
= BWRITERVS_VERSION(2, 1);
987 ret
->funcs
= &parser_vs_2
;
988 gen_oldvs_output(ret
->shader
);
991 void create_vs30_parser(struct asm_parser
*ret
) {
992 TRACE_(parsed_shader
)("vs_3_0\n");
994 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
996 ERR("Failed to allocate memory for the shader\n");
997 set_parse_status(ret
, PARSE_ERR
);
1001 ret
->shader
->type
= ST_VERTEX
;
1002 ret
->shader
->version
= BWRITERVS_VERSION(3, 0);
1003 ret
->funcs
= &parser_vs_3
;
1006 void create_ps20_parser(struct asm_parser
*ret
) {
1007 TRACE_(parsed_shader
)("ps_2_0\n");
1009 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
1011 ERR("Failed to allocate memory for the shader\n");
1012 set_parse_status(ret
, PARSE_ERR
);
1016 ret
->shader
->type
= ST_PIXEL
;
1017 ret
->shader
->version
= BWRITERPS_VERSION(2, 0);
1018 ret
->funcs
= &parser_ps_2
;
1019 gen_oldps_input(ret
->shader
, 8);
1022 void create_ps2x_parser(struct asm_parser
*ret
) {
1023 TRACE_(parsed_shader
)("ps_2_x\n");
1025 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
1027 ERR("Failed to allocate memory for the shader\n");
1028 set_parse_status(ret
, PARSE_ERR
);
1032 ret
->shader
->type
= ST_PIXEL
;
1033 ret
->shader
->version
= BWRITERPS_VERSION(2, 1);
1034 ret
->funcs
= &parser_ps_2_x
;
1035 gen_oldps_input(ret
->shader
, 8);
1038 void create_ps30_parser(struct asm_parser
*ret
) {
1039 TRACE_(parsed_shader
)("ps_3_0\n");
1041 ret
->shader
= asm_alloc(sizeof(*ret
->shader
));
1043 ERR("Failed to allocate memory for the shader\n");
1044 set_parse_status(ret
, PARSE_ERR
);
1048 ret
->shader
->type
= ST_PIXEL
;
1049 ret
->shader
->version
= BWRITERPS_VERSION(3, 0);
1050 ret
->funcs
= &parser_ps_3
;