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
23 #include "wine/debug.h"
25 #include "d3dcompiler_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(asmshader
);
28 WINE_DECLARE_DEBUG_CHANNEL(parsed_shader
);
31 /* How to map vs 1.0 and 2.0 varyings to 3.0 ones
32 * oTx is mapped to ox, which happens to be an
33 * identical mapping since BWRITERSPR_TEXCRDOUT == BWRITERSPR_OUTPUT
34 * oPos, oFog and point size are mapped to general output regs as well.
35 * the vs 1.x and 2.x parser functions add varying declarations
36 * to the shader, and the 1.x and 2.x output functions check those varyings
48 #define OFOG_WRITEMASK BWRITERSP_WRITEMASK_0
50 #define OPTS_WRITEMASK BWRITERSP_WRITEMASK_1
54 /* Input color registers 0-1 are identically mapped */
66 /****************************************************************
67 * Common(non-version specific) shader parser control code *
68 ****************************************************************/
70 static void asmparser_end(struct asm_parser
*This
) {
71 TRACE("Finalizing shader\n");
74 static void asmparser_constF(struct asm_parser
*This
, DWORD reg
, float x
, float y
, float z
, float w
) {
75 if(!This
->shader
) return;
76 TRACE("Adding float constant %u at pos %u\n", reg
, This
->shader
->num_cf
);
77 TRACE_(parsed_shader
)("def c%u, %f, %f, %f, %f\n", reg
, x
, y
, z
, w
);
78 if(!add_constF(This
->shader
, reg
, x
, y
, z
, w
)) {
79 ERR("Out of memory\n");
80 set_parse_status(&This
->status
, PARSE_ERR
);
84 static void asmparser_constB(struct asm_parser
*This
, DWORD reg
, BOOL x
) {
85 if(!This
->shader
) return;
86 TRACE("Adding boolean constant %u at pos %u\n", reg
, This
->shader
->num_cb
);
87 TRACE_(parsed_shader
)("def b%u, %s\n", reg
, x
? "true" : "false");
88 if(!add_constB(This
->shader
, reg
, x
)) {
89 ERR("Out of memory\n");
90 set_parse_status(&This
->status
, PARSE_ERR
);
94 static void asmparser_constI(struct asm_parser
*This
, DWORD reg
, INT x
, INT y
, INT z
, INT w
) {
95 if(!This
->shader
) return;
96 TRACE("Adding integer constant %u at pos %u\n", reg
, This
->shader
->num_ci
);
97 TRACE_(parsed_shader
)("def i%u, %d, %d, %d, %d\n", reg
, x
, y
, z
, w
);
98 if(!add_constI(This
->shader
, reg
, x
, y
, z
, w
)) {
99 ERR("Out of memory\n");
100 set_parse_status(&This
->status
, PARSE_ERR
);
104 static void asmparser_dcl_output(struct asm_parser
*This
, DWORD usage
, DWORD num
,
105 const struct shader_reg
*reg
) {
106 if(!This
->shader
) return;
107 if(This
->shader
->type
== ST_PIXEL
) {
108 asmparser_message(This
, "Line %u: Output register declared in a pixel shader\n", This
->line_no
);
109 set_parse_status(&This
->status
, PARSE_ERR
);
111 if(!record_declaration(This
->shader
, usage
, num
, 0, TRUE
, reg
->regnum
, reg
->u
.writemask
, FALSE
)) {
112 ERR("Out of memory\n");
113 set_parse_status(&This
->status
, PARSE_ERR
);
117 static void asmparser_dcl_output_unsupported(struct asm_parser
*This
, DWORD usage
, DWORD num
,
118 const struct shader_reg
*reg
) {
119 asmparser_message(This
, "Line %u: Output declaration unsupported in this shader version\n", This
->line_no
);
120 set_parse_status(&This
->status
, PARSE_ERR
);
123 static void asmparser_dcl_input(struct asm_parser
*This
, DWORD usage
, DWORD num
,
124 DWORD mod
, const struct shader_reg
*reg
) {
125 struct instruction instr
;
127 if(!This
->shader
) return;
128 if (mod
&& (This
->shader
->type
!= ST_PIXEL
|| This
->shader
->major_version
!= 3
129 || (mod
!= BWRITERSPDM_MSAMPCENTROID
&& mod
!= BWRITERSPDM_PARTIALPRECISION
)))
131 asmparser_message(This
, "Line %u: Unsupported modifier in dcl instruction\n", This
->line_no
);
132 set_parse_status(&This
->status
, PARSE_ERR
);
136 /* Check register type and modifiers */
139 This
->funcs
->dstreg(This
, &instr
, reg
);
141 if(!record_declaration(This
->shader
, usage
, num
, mod
, FALSE
, reg
->regnum
, reg
->u
.writemask
, FALSE
)) {
142 ERR("Out of memory\n");
143 set_parse_status(&This
->status
, PARSE_ERR
);
147 static void asmparser_dcl_input_ps_2(struct asm_parser
*This
, DWORD usage
, DWORD num
,
148 DWORD mod
, const struct shader_reg
*reg
) {
149 struct instruction instr
;
151 if(!This
->shader
) return;
154 This
->funcs
->dstreg(This
, &instr
, reg
);
155 if(!record_declaration(This
->shader
, usage
, num
, mod
, FALSE
, instr
.dst
.regnum
, instr
.dst
.u
.writemask
, FALSE
)) {
156 ERR("Out of memory\n");
157 set_parse_status(&This
->status
, PARSE_ERR
);
161 static void asmparser_dcl_input_unsupported(struct asm_parser
*This
,
162 DWORD usage
, DWORD num
, DWORD mod
, const struct shader_reg
*reg
)
164 asmparser_message(This
, "Line %u: Input declaration unsupported in this shader version\n", This
->line_no
);
165 set_parse_status(&This
->status
, PARSE_ERR
);
168 static void asmparser_dcl_sampler(struct asm_parser
*This
, DWORD samptype
,
169 DWORD mod
, DWORD regnum
,
170 unsigned int line_no
) {
171 if(!This
->shader
) return;
172 if (mod
&& (This
->shader
->type
!= ST_PIXEL
|| This
->shader
->major_version
!= 3
173 || (mod
!= BWRITERSPDM_MSAMPCENTROID
&& mod
!= BWRITERSPDM_PARTIALPRECISION
)))
175 asmparser_message(This
, "Line %u: Unsupported modifier in dcl instruction\n", This
->line_no
);
176 set_parse_status(&This
->status
, PARSE_ERR
);
179 if(!record_sampler(This
->shader
, samptype
, mod
, regnum
)) {
180 ERR("Out of memory\n");
181 set_parse_status(&This
->status
, PARSE_ERR
);
185 static void asmparser_dcl_sampler_unsupported(struct asm_parser
*This
,
186 DWORD samptype
, DWORD mod
, DWORD regnum
, unsigned int line_no
)
188 asmparser_message(This
, "Line %u: Sampler declaration unsupported in this shader version\n", This
->line_no
);
189 set_parse_status(&This
->status
, PARSE_ERR
);
192 static void asmparser_sincos(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
193 const struct shader_reg
*dst
,
194 const struct src_regs
*srcs
) {
195 struct instruction
*instr
;
197 if(!srcs
|| srcs
->count
!= 3) {
198 asmparser_message(This
, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This
->line_no
);
199 set_parse_status(&This
->status
, PARSE_ERR
);
203 instr
= alloc_instr(3);
205 ERR("Error allocating memory for the instruction\n");
206 set_parse_status(&This
->status
, PARSE_ERR
);
210 instr
->opcode
= BWRITERSIO_SINCOS
;
212 instr
->shift
= shift
;
215 This
->funcs
->dstreg(This
, instr
, dst
);
216 This
->funcs
->srcreg(This
, instr
, 0, &srcs
->reg
[0]);
217 This
->funcs
->srcreg(This
, instr
, 1, &srcs
->reg
[1]);
218 This
->funcs
->srcreg(This
, instr
, 2, &srcs
->reg
[2]);
220 if(!add_instruction(This
->shader
, instr
)) {
221 ERR("Out of memory\n");
222 set_parse_status(&This
->status
, PARSE_ERR
);
226 static struct shader_reg
map_oldps_register(const struct shader_reg
*reg
, BOOL tex_varying
) {
227 struct shader_reg ret
;
229 case BWRITERSPR_TEXTURE
:
232 ret
.type
= BWRITERSPR_INPUT
;
233 switch(reg
->regnum
) {
234 case 0: ret
.regnum
= T0_VARYING
; break;
235 case 1: ret
.regnum
= T1_VARYING
; break;
236 case 2: ret
.regnum
= T2_VARYING
; break;
237 case 3: ret
.regnum
= T3_VARYING
; break;
238 case 4: ret
.regnum
= T4_VARYING
; break;
239 case 5: ret
.regnum
= T5_VARYING
; break;
240 case 6: ret
.regnum
= T6_VARYING
; break;
241 case 7: ret
.regnum
= T7_VARYING
; break;
243 FIXME("Unexpected TEXTURE register t%u\n", reg
->regnum
);
249 ret
.type
= BWRITERSPR_TEMP
;
250 switch(reg
->regnum
) {
251 case 0: ret
.regnum
= T0_REG
; break;
252 case 1: ret
.regnum
= T1_REG
; break;
253 case 2: ret
.regnum
= T2_REG
; break;
254 case 3: ret
.regnum
= T3_REG
; break;
256 FIXME("Unexpected TEXTURE register t%u\n", reg
->regnum
);
262 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
265 default: return *reg
;
269 static void asmparser_texcoord(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
270 const struct shader_reg
*dst
,
271 const struct src_regs
*srcs
) {
272 struct instruction
*instr
;
275 asmparser_message(This
, "Line %u: Source registers in texcoord instruction\n", This
->line_no
);
276 set_parse_status(&This
->status
, PARSE_ERR
);
280 instr
= alloc_instr(1);
282 ERR("Error allocating memory for the instruction\n");
283 set_parse_status(&This
->status
, PARSE_ERR
);
287 /* texcoord copies the texture coord data into a temporary register-like
288 * readable form. In newer shader models this equals a MOV from v0 to r0,
291 instr
->opcode
= BWRITERSIO_MOV
;
292 instr
->dstmod
= mod
| BWRITERSPDM_SATURATE
; /* texcoord clamps to [0;1] */
293 instr
->shift
= shift
;
296 This
->funcs
->dstreg(This
, instr
, dst
);
297 /* The src reg needs special care */
298 instr
->src
[0] = map_oldps_register(dst
, TRUE
);
300 if(!add_instruction(This
->shader
, instr
)) {
301 ERR("Out of memory\n");
302 set_parse_status(&This
->status
, PARSE_ERR
);
306 static void asmparser_texcrd(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
307 const struct shader_reg
*dst
,
308 const struct src_regs
*srcs
) {
309 struct instruction
*instr
;
311 if(!srcs
|| srcs
->count
!= 1) {
312 asmparser_message(This
, "Line %u: Wrong number of source registers in texcrd instruction\n", This
->line_no
);
313 set_parse_status(&This
->status
, PARSE_ERR
);
317 instr
= alloc_instr(1);
319 ERR("Error allocating memory for the instruction\n");
320 set_parse_status(&This
->status
, PARSE_ERR
);
324 /* The job of texcrd is done by mov in later shader versions */
325 instr
->opcode
= BWRITERSIO_MOV
;
327 instr
->shift
= shift
;
330 This
->funcs
->dstreg(This
, instr
, dst
);
331 This
->funcs
->srcreg(This
, instr
, 0, &srcs
->reg
[0]);
333 if(!add_instruction(This
->shader
, instr
)) {
334 ERR("Out of memory\n");
335 set_parse_status(&This
->status
, PARSE_ERR
);
339 static void asmparser_texkill(struct asm_parser
*This
,
340 const struct shader_reg
*dst
) {
341 struct instruction
*instr
= alloc_instr(0);
344 ERR("Error allocating memory for the instruction\n");
345 set_parse_status(&This
->status
, PARSE_ERR
);
349 instr
->opcode
= BWRITERSIO_TEXKILL
;
354 /* Do not run the dst register through the normal
355 * register conversion. If used with ps_1_0 to ps_1_3
356 * the texture coordinate from that register is used,
357 * not the temporary register value. In ps_1_4 and
358 * ps_2_0 t0 is always a varying and temporaries can
359 * be used with texkill.
361 instr
->dst
= map_oldps_register(dst
, TRUE
);
362 instr
->has_dst
= TRUE
;
364 if(!add_instruction(This
->shader
, instr
)) {
365 ERR("Out of memory\n");
366 set_parse_status(&This
->status
, PARSE_ERR
);
370 static void asmparser_texhelper(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
371 const struct shader_reg
*dst
,
372 const struct shader_reg
*src0
) {
373 struct instruction
*instr
= alloc_instr(2);
376 ERR("Error allocating memory for the instruction\n");
377 set_parse_status(&This
->status
, PARSE_ERR
);
381 instr
->opcode
= BWRITERSIO_TEX
;
383 instr
->shift
= shift
;
385 /* The dest register can be mapped normally to a temporary register */
386 This
->funcs
->dstreg(This
, instr
, dst
);
387 /* Use the src passed as parameter by the specific instruction handler */
388 instr
->src
[0] = *src0
;
390 /* The 2nd source register is the sampler register with the
391 * destination's regnum
393 ZeroMemory(&instr
->src
[1], sizeof(instr
->src
[1]));
394 instr
->src
[1].type
= BWRITERSPR_SAMPLER
;
395 instr
->src
[1].regnum
= dst
->regnum
;
396 instr
->src
[1].u
.swizzle
= BWRITERVS_NOSWIZZLE
;
397 instr
->src
[1].srcmod
= BWRITERSPSM_NONE
;
398 instr
->src
[1].rel_reg
= NULL
;
400 if(!add_instruction(This
->shader
, instr
)) {
401 ERR("Out of memory\n");
402 set_parse_status(&This
->status
, PARSE_ERR
);
406 static void asmparser_tex(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
407 const struct shader_reg
*dst
) {
408 struct shader_reg src
;
410 /* The first source register is the varying containing the coordinate */
411 src
= map_oldps_register(dst
, TRUE
);
412 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
415 static void asmparser_texld14(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
416 const struct shader_reg
*dst
,
417 const struct src_regs
*srcs
) {
418 struct instruction
*instr
;
420 if(!srcs
|| srcs
->count
!= 1) {
421 asmparser_message(This
, "Line %u: texld (PS 1.4) has a wrong number of source registers\n", This
->line_no
);
422 set_parse_status(&This
->status
, PARSE_ERR
);
426 instr
= alloc_instr(2);
428 ERR("Error allocating memory for the instruction\n");
429 set_parse_status(&This
->status
, PARSE_ERR
);
433 /* This code is recording a texld instruction, not tex. However,
434 * texld borrows the opcode of tex
436 instr
->opcode
= BWRITERSIO_TEX
;
438 instr
->shift
= shift
;
441 This
->funcs
->dstreg(This
, instr
, dst
);
442 This
->funcs
->srcreg(This
, instr
, 0, &srcs
->reg
[0]);
444 /* The 2nd source register is the sampler register with the
445 * destination's regnum
447 ZeroMemory(&instr
->src
[1], sizeof(instr
->src
[1]));
448 instr
->src
[1].type
= BWRITERSPR_SAMPLER
;
449 instr
->src
[1].regnum
= dst
->regnum
;
450 instr
->src
[1].u
.swizzle
= BWRITERVS_NOSWIZZLE
;
451 instr
->src
[1].srcmod
= BWRITERSPSM_NONE
;
452 instr
->src
[1].rel_reg
= NULL
;
454 if(!add_instruction(This
->shader
, instr
)) {
455 ERR("Out of memory\n");
456 set_parse_status(&This
->status
, PARSE_ERR
);
460 static void asmparser_texreg2ar(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
461 const struct shader_reg
*dst
,
462 const struct shader_reg
*src0
) {
463 struct shader_reg src
;
465 src
= map_oldps_register(src0
, FALSE
);
466 /* Supply the correct swizzle */
467 src
.u
.swizzle
= BWRITERVS_X_W
| BWRITERVS_Y_X
| BWRITERVS_Z_X
| BWRITERVS_W_X
;
468 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
471 static void asmparser_texreg2gb(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
472 const struct shader_reg
*dst
,
473 const struct shader_reg
*src0
) {
474 struct shader_reg src
;
476 src
= map_oldps_register(src0
, FALSE
);
477 /* Supply the correct swizzle */
478 src
.u
.swizzle
= BWRITERVS_X_Y
| BWRITERVS_Y_Z
| BWRITERVS_Z_Z
| BWRITERVS_W_Z
;
479 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
482 static void asmparser_texreg2rgb(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
483 const struct shader_reg
*dst
,
484 const struct shader_reg
*src0
) {
485 struct shader_reg src
;
487 src
= map_oldps_register(src0
, FALSE
);
488 /* Supply the correct swizzle */
489 src
.u
.swizzle
= BWRITERVS_X_X
| BWRITERVS_Y_Y
| BWRITERVS_Z_Z
| BWRITERVS_W_Z
;
490 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
493 /* Complex pixel shader 1.3 instructions like texm3x3tex are tricky - the
494 * bytecode writer works instruction by instruction, so we can't properly
495 * convert these from/to equivalent ps_3_0 instructions. Then simply keep using
496 * the ps_1_3 opcodes and just adapt the registers in the common fashion (i.e.
497 * go through asmparser_instr).
500 static void asmparser_instr(struct asm_parser
*This
, DWORD opcode
, DWORD mod
, DWORD shift
,
501 enum bwriter_comparison_type comp
, const struct shader_reg
*dst
,
502 const struct src_regs
*srcs
, int expectednsrcs
)
504 struct bwriter_shader
*shader
= This
->shader
;
505 struct instruction
*instr
;
507 BOOL firstreg
= TRUE
;
508 unsigned int src_count
= srcs
? srcs
->count
: 0;
510 if(!This
->shader
) return;
512 TRACE_(parsed_shader
)("%s%s%s%s ", debug_print_opcode(opcode
),
513 debug_print_dstmod(mod
),
514 debug_print_shift(shift
),
515 debug_print_comp(comp
));
517 TRACE_(parsed_shader
)("%s", debug_print_dstreg(dst
));
520 for(i
= 0; i
< src_count
; i
++) {
521 if(!firstreg
) TRACE_(parsed_shader
)(", ");
522 else firstreg
= FALSE
;
523 TRACE_(parsed_shader
)("%s", debug_print_srcreg(&srcs
->reg
[i
]));
525 TRACE_(parsed_shader
)("\n");
527 /* Check for instructions with different syntaxes in different shader versions */
529 case BWRITERSIO_SINCOS
:
530 /* The syntax changes between vs 2 and the other shader versions */
531 if (This
->shader
->type
== ST_VERTEX
&& This
->shader
->major_version
== 2)
533 asmparser_sincos(This
, mod
, shift
, dst
, srcs
);
536 /* Use the default handling */
538 case BWRITERSIO_TEXCOORD
:
539 /* texcoord/texcrd are two instructions present only in PS <= 1.3 and PS 1.4 respectively */
540 if (shader
->type
== ST_PIXEL
&& shader
->major_version
== 1 && shader
->minor_version
== 4)
541 asmparser_texcrd(This
, mod
, shift
, dst
, srcs
);
543 asmparser_texcoord(This
, mod
, shift
, dst
, srcs
);
546 /* this encodes both the tex PS 1.x instruction and the
547 texld 1.4/2.0+ instruction */
548 if (shader
->type
== ST_PIXEL
&& shader
->major_version
== 1)
550 if (shader
->minor_version
< 4)
551 asmparser_tex(This
, mod
, shift
, dst
);
553 asmparser_texld14(This
, mod
, shift
, dst
, srcs
);
556 /* else fallback to the standard behavior */
560 if(src_count
!= expectednsrcs
) {
561 asmparser_message(This
, "Line %u: Wrong number of source registers\n", This
->line_no
);
562 set_parse_status(&This
->status
, PARSE_ERR
);
566 /* Handle PS 1.x instructions, "regularizing" them */
568 case BWRITERSIO_TEXKILL
:
569 asmparser_texkill(This
, dst
);
571 case BWRITERSIO_TEXREG2AR
:
572 asmparser_texreg2ar(This
, mod
, shift
, dst
, &srcs
->reg
[0]);
574 case BWRITERSIO_TEXREG2GB
:
575 asmparser_texreg2gb(This
, mod
, shift
, dst
, &srcs
->reg
[0]);
577 case BWRITERSIO_TEXREG2RGB
:
578 asmparser_texreg2rgb(This
, mod
, shift
, dst
, &srcs
->reg
[0]);
582 instr
= alloc_instr(src_count
);
584 ERR("Error allocating memory for the instruction\n");
585 set_parse_status(&This
->status
, PARSE_ERR
);
589 instr
->opcode
= opcode
;
591 instr
->shift
= shift
;
592 instr
->comptype
= comp
;
593 if(dst
) This
->funcs
->dstreg(This
, instr
, dst
);
594 for(i
= 0; i
< src_count
; i
++) {
595 This
->funcs
->srcreg(This
, instr
, i
, &srcs
->reg
[i
]);
598 if(!add_instruction(This
->shader
, instr
)) {
599 ERR("Out of memory\n");
600 set_parse_status(&This
->status
, PARSE_ERR
);
604 static struct shader_reg
map_oldvs_register(const struct shader_reg
*reg
) {
605 struct shader_reg ret
;
607 case BWRITERSPR_RASTOUT
:
609 ret
.type
= BWRITERSPR_OUTPUT
;
610 switch(reg
->regnum
) {
611 case BWRITERSRO_POSITION
:
612 ret
.regnum
= OPOS_REG
;
615 ret
.regnum
= OFOG_REG
;
616 ret
.u
.writemask
= OFOG_WRITEMASK
;
618 case BWRITERSRO_POINT_SIZE
:
619 ret
.regnum
= OPTS_REG
;
620 ret
.u
.writemask
= OPTS_WRITEMASK
;
623 FIXME("Unhandled RASTOUT register %u\n", reg
->regnum
);
628 case BWRITERSPR_TEXCRDOUT
:
630 ret
.type
= BWRITERSPR_OUTPUT
;
631 switch(reg
->regnum
) {
632 case 0: ret
.regnum
= OT0_REG
; break;
633 case 1: ret
.regnum
= OT1_REG
; break;
634 case 2: ret
.regnum
= OT2_REG
; break;
635 case 3: ret
.regnum
= OT3_REG
; break;
636 case 4: ret
.regnum
= OT4_REG
; break;
637 case 5: ret
.regnum
= OT5_REG
; break;
638 case 6: ret
.regnum
= OT6_REG
; break;
639 case 7: ret
.regnum
= OT7_REG
; break;
641 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg
->regnum
);
646 case BWRITERSPR_ATTROUT
:
648 ret
.type
= BWRITERSPR_OUTPUT
;
649 switch(reg
->regnum
) {
650 case 0: ret
.regnum
= OD0_REG
; break;
651 case 1: ret
.regnum
= OD1_REG
; break;
653 FIXME("Unhandled ATTROUT regnum %u\n", reg
->regnum
);
658 default: return *reg
;
662 /* Checks for unsupported source modifiers in VS (all versions) or
664 static void check_legacy_srcmod(struct asm_parser
*This
, DWORD srcmod
) {
665 if(srcmod
== BWRITERSPSM_BIAS
|| srcmod
== BWRITERSPSM_BIASNEG
||
666 srcmod
== BWRITERSPSM_SIGN
|| srcmod
== BWRITERSPSM_SIGNNEG
||
667 srcmod
== BWRITERSPSM_COMP
|| srcmod
== BWRITERSPSM_X2
||
668 srcmod
== BWRITERSPSM_X2NEG
|| srcmod
== BWRITERSPSM_DZ
||
669 srcmod
== BWRITERSPSM_DW
) {
670 asmparser_message(This
, "Line %u: Source modifier %s not supported in this shader version\n",
672 debug_print_srcmod(srcmod
));
673 set_parse_status(&This
->status
, PARSE_ERR
);
677 static void check_abs_srcmod(struct asm_parser
*This
, DWORD srcmod
) {
678 if(srcmod
== BWRITERSPSM_ABS
|| srcmod
== BWRITERSPSM_ABSNEG
) {
679 asmparser_message(This
, "Line %u: Source modifier %s not supported in this shader version\n",
681 debug_print_srcmod(srcmod
));
682 set_parse_status(&This
->status
, PARSE_ERR
);
686 static void check_loop_swizzle(struct asm_parser
*This
,
687 const struct shader_reg
*src
) {
688 if((src
->type
== BWRITERSPR_LOOP
&& src
->u
.swizzle
!= BWRITERVS_NOSWIZZLE
) ||
689 (src
->rel_reg
&& src
->rel_reg
->type
== BWRITERSPR_LOOP
&&
690 src
->rel_reg
->u
.swizzle
!= BWRITERVS_NOSWIZZLE
)) {
691 asmparser_message(This
, "Line %u: Swizzle not allowed on aL register\n", This
->line_no
);
692 set_parse_status(&This
->status
, PARSE_ERR
);
696 static void check_shift_dstmod(struct asm_parser
*This
, DWORD shift
) {
698 asmparser_message(This
, "Line %u: Shift modifiers not supported in this shader version\n",
700 set_parse_status(&This
->status
, PARSE_ERR
);
704 static void check_ps_dstmod(struct asm_parser
*This
, DWORD dstmod
) {
705 if(dstmod
== BWRITERSPDM_PARTIALPRECISION
||
706 dstmod
== BWRITERSPDM_MSAMPCENTROID
) {
707 asmparser_message(This
, "Line %u: Instruction modifier %s not supported in this shader version\n",
709 debug_print_dstmod(dstmod
));
710 set_parse_status(&This
->status
, PARSE_ERR
);
714 struct allowed_reg_type
{
720 static BOOL
check_reg_type(const struct shader_reg
*reg
,
721 const struct allowed_reg_type
*allowed
) {
724 while(allowed
[i
].type
!= ~0U) {
725 if(reg
->type
== allowed
[i
].type
) {
727 if(allowed
[i
].reladdr
)
728 return TRUE
; /* The relative addressing register
729 can have a negative value, we
730 can't check the register index */
733 if(reg
->regnum
< allowed
[i
].count
) return TRUE
;
741 /* Native assembler doesn't do separate checks for src and dst registers */
742 static const struct allowed_reg_type vs_1_reg_allowed
[] = {
743 { BWRITERSPR_TEMP
, 12, FALSE
},
744 { BWRITERSPR_INPUT
, 16, FALSE
},
745 { BWRITERSPR_CONST
, ~0U, TRUE
},
746 { BWRITERSPR_ADDR
, 1, FALSE
},
747 { BWRITERSPR_RASTOUT
, 3, FALSE
}, /* oPos, oFog and oPts */
748 { BWRITERSPR_ATTROUT
, 2, FALSE
},
749 { BWRITERSPR_TEXCRDOUT
, 8, FALSE
},
750 { ~0U, 0 } /* End tag */
753 /* struct instruction *asmparser_srcreg
755 * Records a source register in the instruction and does shader version
756 * specific checks and modifications on it
759 * This: Shader parser instance
760 * instr: instruction to store the register in
761 * num: Number of source register
762 * src: Pointer to source the register structure. The caller can free
765 static void asmparser_srcreg_vs_1(struct asm_parser
*This
,
766 struct instruction
*instr
, int num
,
767 const struct shader_reg
*src
) {
768 struct shader_reg reg
;
770 if(!check_reg_type(src
, vs_1_reg_allowed
)) {
771 asmparser_message(This
, "Line %u: Source register %s not supported in VS 1\n",
773 debug_print_srcreg(src
));
774 set_parse_status(&This
->status
, PARSE_ERR
);
776 check_legacy_srcmod(This
, src
->srcmod
);
777 check_abs_srcmod(This
, src
->srcmod
);
778 reg
= map_oldvs_register(src
);
779 instr
->src
[num
] = reg
;
782 static const struct allowed_reg_type vs_2_reg_allowed
[] = {
783 { BWRITERSPR_TEMP
, 12, FALSE
},
784 { BWRITERSPR_INPUT
, 16, FALSE
},
785 { BWRITERSPR_CONST
, ~0U, TRUE
},
786 { BWRITERSPR_ADDR
, 1, FALSE
},
787 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
788 { BWRITERSPR_CONSTINT
, 16, FALSE
},
789 { BWRITERSPR_LOOP
, 1, FALSE
},
790 { BWRITERSPR_LABEL
, 2048, FALSE
},
791 { BWRITERSPR_PREDICATE
, 1, FALSE
},
792 { BWRITERSPR_RASTOUT
, 3, FALSE
}, /* oPos, oFog and oPts */
793 { BWRITERSPR_ATTROUT
, 2, FALSE
},
794 { BWRITERSPR_TEXCRDOUT
, 8, FALSE
},
795 { ~0U, 0 } /* End tag */
798 static void asmparser_srcreg_vs_2(struct asm_parser
*This
,
799 struct instruction
*instr
, int num
,
800 const struct shader_reg
*src
) {
801 struct shader_reg reg
;
803 if(!check_reg_type(src
, vs_2_reg_allowed
)) {
804 asmparser_message(This
, "Line %u: Source register %s not supported in VS 2\n",
806 debug_print_srcreg(src
));
807 set_parse_status(&This
->status
, PARSE_ERR
);
809 check_loop_swizzle(This
, src
);
810 check_legacy_srcmod(This
, src
->srcmod
);
811 check_abs_srcmod(This
, src
->srcmod
);
812 reg
= map_oldvs_register(src
);
813 instr
->src
[num
] = reg
;
816 static const struct allowed_reg_type vs_3_reg_allowed
[] = {
817 { BWRITERSPR_TEMP
, 32, FALSE
},
818 { BWRITERSPR_INPUT
, 16, TRUE
},
819 { BWRITERSPR_CONST
, ~0U, TRUE
},
820 { BWRITERSPR_ADDR
, 1, FALSE
},
821 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
822 { BWRITERSPR_CONSTINT
, 16, FALSE
},
823 { BWRITERSPR_LOOP
, 1, FALSE
},
824 { BWRITERSPR_LABEL
, 2048, FALSE
},
825 { BWRITERSPR_PREDICATE
, 1, FALSE
},
826 { BWRITERSPR_SAMPLER
, 4, FALSE
},
827 { BWRITERSPR_OUTPUT
, 12, TRUE
},
828 { ~0U, 0 } /* End tag */
831 static void asmparser_srcreg_vs_3(struct asm_parser
*This
,
832 struct instruction
*instr
, int num
,
833 const struct shader_reg
*src
) {
834 if(!check_reg_type(src
, vs_3_reg_allowed
)) {
835 asmparser_message(This
, "Line %u: Source register %s not supported in VS 3.0\n",
837 debug_print_srcreg(src
));
838 set_parse_status(&This
->status
, PARSE_ERR
);
840 check_loop_swizzle(This
, src
);
841 check_legacy_srcmod(This
, src
->srcmod
);
842 instr
->src
[num
] = *src
;
845 static const struct allowed_reg_type ps_1_0123_reg_allowed
[] = {
846 { BWRITERSPR_CONST
, 8, FALSE
},
847 { BWRITERSPR_TEMP
, 2, FALSE
},
848 { BWRITERSPR_TEXTURE
, 4, FALSE
},
849 { BWRITERSPR_INPUT
, 2, FALSE
},
850 { ~0U, 0 } /* End tag */
853 static void asmparser_srcreg_ps_1_0123(struct asm_parser
*This
,
854 struct instruction
*instr
, int num
,
855 const struct shader_reg
*src
) {
856 struct shader_reg reg
;
858 if(!check_reg_type(src
, ps_1_0123_reg_allowed
)) {
859 asmparser_message(This
, "Line %u: Source register %s not supported in <== PS 1.3\n",
861 debug_print_srcreg(src
));
862 set_parse_status(&This
->status
, PARSE_ERR
);
864 check_abs_srcmod(This
, src
->srcmod
);
865 reg
= map_oldps_register(src
, FALSE
);
866 instr
->src
[num
] = reg
;
869 static const struct allowed_reg_type ps_1_4_reg_allowed
[] = {
870 { BWRITERSPR_CONST
, 8, FALSE
},
871 { BWRITERSPR_TEMP
, 6, FALSE
},
872 { BWRITERSPR_TEXTURE
, 6, FALSE
},
873 { BWRITERSPR_INPUT
, 2, FALSE
},
874 { ~0U, 0 } /* End tag */
877 static void asmparser_srcreg_ps_1_4(struct asm_parser
*This
,
878 struct instruction
*instr
, int num
,
879 const struct shader_reg
*src
) {
880 struct shader_reg reg
;
882 if(!check_reg_type(src
, ps_1_4_reg_allowed
)) {
883 asmparser_message(This
, "Line %u: Source register %s not supported in PS 1.4\n",
885 debug_print_srcreg(src
));
886 set_parse_status(&This
->status
, PARSE_ERR
);
888 check_abs_srcmod(This
, src
->srcmod
);
889 reg
= map_oldps_register(src
, TRUE
);
890 instr
->src
[num
] = reg
;
893 static const struct allowed_reg_type ps_2_0_reg_allowed
[] = {
894 { BWRITERSPR_INPUT
, 2, FALSE
},
895 { BWRITERSPR_TEMP
, 32, FALSE
},
896 { BWRITERSPR_CONST
, 32, FALSE
},
897 { BWRITERSPR_CONSTINT
, 16, FALSE
},
898 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
899 { BWRITERSPR_SAMPLER
, 16, FALSE
},
900 { BWRITERSPR_TEXTURE
, 8, FALSE
},
901 { BWRITERSPR_COLOROUT
, 4, FALSE
},
902 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
903 { ~0U, 0 } /* End tag */
906 static void asmparser_srcreg_ps_2(struct asm_parser
*This
,
907 struct instruction
*instr
, int num
,
908 const struct shader_reg
*src
) {
909 struct shader_reg reg
;
911 if(!check_reg_type(src
, ps_2_0_reg_allowed
)) {
912 asmparser_message(This
, "Line %u: Source register %s not supported in PS 2.0\n",
914 debug_print_srcreg(src
));
915 set_parse_status(&This
->status
, PARSE_ERR
);
917 check_legacy_srcmod(This
, src
->srcmod
);
918 check_abs_srcmod(This
, src
->srcmod
);
919 reg
= map_oldps_register(src
, TRUE
);
920 instr
->src
[num
] = reg
;
923 static const struct allowed_reg_type ps_2_x_reg_allowed
[] = {
924 { BWRITERSPR_INPUT
, 2, FALSE
},
925 { BWRITERSPR_TEMP
, 32, FALSE
},
926 { BWRITERSPR_CONST
, 32, FALSE
},
927 { BWRITERSPR_CONSTINT
, 16, FALSE
},
928 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
929 { BWRITERSPR_PREDICATE
, 1, FALSE
},
930 { BWRITERSPR_SAMPLER
, 16, FALSE
},
931 { BWRITERSPR_TEXTURE
, 8, FALSE
},
932 { BWRITERSPR_LABEL
, 2048, FALSE
},
933 { BWRITERSPR_COLOROUT
, 4, FALSE
},
934 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
935 { ~0U, 0 } /* End tag */
938 static void asmparser_srcreg_ps_2_x(struct asm_parser
*This
,
939 struct instruction
*instr
, int num
,
940 const struct shader_reg
*src
) {
941 struct shader_reg reg
;
943 if(!check_reg_type(src
, ps_2_x_reg_allowed
)) {
944 asmparser_message(This
, "Line %u: Source register %s not supported in PS 2.x\n",
946 debug_print_srcreg(src
));
947 set_parse_status(&This
->status
, PARSE_ERR
);
949 check_legacy_srcmod(This
, src
->srcmod
);
950 check_abs_srcmod(This
, src
->srcmod
);
951 reg
= map_oldps_register(src
, TRUE
);
952 instr
->src
[num
] = reg
;
955 static const struct allowed_reg_type ps_3_reg_allowed
[] = {
956 { BWRITERSPR_INPUT
, 10, TRUE
},
957 { BWRITERSPR_TEMP
, 32, FALSE
},
958 { BWRITERSPR_CONST
, 224, FALSE
},
959 { BWRITERSPR_CONSTINT
, 16, FALSE
},
960 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
961 { BWRITERSPR_PREDICATE
, 1, FALSE
},
962 { BWRITERSPR_SAMPLER
, 16, FALSE
},
963 { BWRITERSPR_MISCTYPE
, 2, FALSE
}, /* vPos and vFace */
964 { BWRITERSPR_LOOP
, 1, FALSE
},
965 { BWRITERSPR_LABEL
, 2048, FALSE
},
966 { BWRITERSPR_COLOROUT
, 4, FALSE
},
967 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
968 { ~0U, 0 } /* End tag */
971 static void asmparser_srcreg_ps_3(struct asm_parser
*This
,
972 struct instruction
*instr
, int num
,
973 const struct shader_reg
*src
) {
974 if(!check_reg_type(src
, ps_3_reg_allowed
)) {
975 asmparser_message(This
, "Line %u: Source register %s not supported in PS 3.0\n",
977 debug_print_srcreg(src
));
978 set_parse_status(&This
->status
, PARSE_ERR
);
980 check_loop_swizzle(This
, src
);
981 check_legacy_srcmod(This
, src
->srcmod
);
982 instr
->src
[num
] = *src
;
985 static void asmparser_dstreg_vs_1(struct asm_parser
*This
,
986 struct instruction
*instr
,
987 const struct shader_reg
*dst
) {
988 struct shader_reg reg
;
990 if(!check_reg_type(dst
, vs_1_reg_allowed
)) {
991 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 1\n",
993 debug_print_dstreg(dst
));
994 set_parse_status(&This
->status
, PARSE_ERR
);
996 check_ps_dstmod(This
, instr
->dstmod
);
997 check_shift_dstmod(This
, instr
->shift
);
998 reg
= map_oldvs_register(dst
);
1000 instr
->has_dst
= TRUE
;
1003 static void asmparser_dstreg_vs_2(struct asm_parser
*This
,
1004 struct instruction
*instr
,
1005 const struct shader_reg
*dst
) {
1006 struct shader_reg reg
;
1008 if(!check_reg_type(dst
, vs_2_reg_allowed
)) {
1009 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 2.0\n",
1011 debug_print_dstreg(dst
));
1012 set_parse_status(&This
->status
, PARSE_ERR
);
1014 check_ps_dstmod(This
, instr
->dstmod
);
1015 check_shift_dstmod(This
, instr
->shift
);
1016 reg
= map_oldvs_register(dst
);
1018 instr
->has_dst
= TRUE
;
1021 static void asmparser_dstreg_vs_3(struct asm_parser
*This
,
1022 struct instruction
*instr
,
1023 const struct shader_reg
*dst
) {
1024 if(!check_reg_type(dst
, vs_3_reg_allowed
)) {
1025 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 3.0\n",
1027 debug_print_dstreg(dst
));
1028 set_parse_status(&This
->status
, PARSE_ERR
);
1030 check_ps_dstmod(This
, instr
->dstmod
);
1031 check_shift_dstmod(This
, instr
->shift
);
1033 instr
->has_dst
= TRUE
;
1036 static void asmparser_dstreg_ps_1_0123(struct asm_parser
*This
,
1037 struct instruction
*instr
,
1038 const struct shader_reg
*dst
) {
1039 struct shader_reg reg
;
1041 if(!check_reg_type(dst
, ps_1_0123_reg_allowed
)) {
1042 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 1\n",
1044 debug_print_dstreg(dst
));
1045 set_parse_status(&This
->status
, PARSE_ERR
);
1047 reg
= map_oldps_register(dst
, FALSE
);
1049 instr
->has_dst
= TRUE
;
1052 static void asmparser_dstreg_ps_1_4(struct asm_parser
*This
,
1053 struct instruction
*instr
,
1054 const struct shader_reg
*dst
) {
1055 struct shader_reg reg
;
1057 if(!check_reg_type(dst
, ps_1_4_reg_allowed
)) {
1058 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 1\n",
1060 debug_print_dstreg(dst
));
1061 set_parse_status(&This
->status
, PARSE_ERR
);
1063 reg
= map_oldps_register(dst
, TRUE
);
1065 instr
->has_dst
= TRUE
;
1068 static void asmparser_dstreg_ps_2(struct asm_parser
*This
,
1069 struct instruction
*instr
,
1070 const struct shader_reg
*dst
) {
1071 struct shader_reg reg
;
1073 if(!check_reg_type(dst
, ps_2_0_reg_allowed
)) {
1074 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 2.0\n",
1076 debug_print_dstreg(dst
));
1077 set_parse_status(&This
->status
, PARSE_ERR
);
1079 check_shift_dstmod(This
, instr
->shift
);
1080 reg
= map_oldps_register(dst
, TRUE
);
1082 instr
->has_dst
= TRUE
;
1085 static void asmparser_dstreg_ps_2_x(struct asm_parser
*This
,
1086 struct instruction
*instr
,
1087 const struct shader_reg
*dst
) {
1088 struct shader_reg reg
;
1090 if(!check_reg_type(dst
, ps_2_x_reg_allowed
)) {
1091 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 2.x\n",
1093 debug_print_dstreg(dst
));
1094 set_parse_status(&This
->status
, PARSE_ERR
);
1096 check_shift_dstmod(This
, instr
->shift
);
1097 reg
= map_oldps_register(dst
, TRUE
);
1099 instr
->has_dst
= TRUE
;
1102 static void asmparser_dstreg_ps_3(struct asm_parser
*This
,
1103 struct instruction
*instr
,
1104 const struct shader_reg
*dst
) {
1105 if(!check_reg_type(dst
, ps_3_reg_allowed
)) {
1106 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 3.0\n",
1108 debug_print_dstreg(dst
));
1109 set_parse_status(&This
->status
, PARSE_ERR
);
1111 check_shift_dstmod(This
, instr
->shift
);
1113 instr
->has_dst
= TRUE
;
1116 static void asmparser_predicate_supported(struct asm_parser
*This
,
1117 const struct shader_reg
*predicate
) {
1118 /* this sets the predicate of the last instruction added to the shader */
1119 if(!This
->shader
) return;
1120 if(This
->shader
->num_instrs
== 0) ERR("Predicate without an instruction\n");
1121 This
->shader
->instr
[This
->shader
->num_instrs
- 1]->has_predicate
= TRUE
;
1122 This
->shader
->instr
[This
->shader
->num_instrs
- 1]->predicate
= *predicate
;
1125 static void asmparser_predicate_unsupported(struct asm_parser
*This
,
1126 const struct shader_reg
*predicate
) {
1127 asmparser_message(This
, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This
->line_no
);
1128 set_parse_status(&This
->status
, PARSE_ERR
);
1131 static void asmparser_coissue_supported(struct asm_parser
*This
) {
1132 /* this sets the coissue flag of the last instruction added to the shader */
1133 if(!This
->shader
) return;
1134 if(This
->shader
->num_instrs
== 0){
1135 asmparser_message(This
, "Line %u: Coissue flag on the first shader instruction\n", This
->line_no
);
1136 set_parse_status(&This
->status
, PARSE_ERR
);
1138 This
->shader
->instr
[This
->shader
->num_instrs
-1]->coissue
= TRUE
;
1141 static void asmparser_coissue_unsupported(struct asm_parser
*This
) {
1142 asmparser_message(This
, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This
->line_no
);
1143 set_parse_status(&This
->status
, PARSE_ERR
);
1146 static const struct asmparser_backend parser_vs_1
= {
1151 asmparser_dstreg_vs_1
,
1152 asmparser_srcreg_vs_1
,
1154 asmparser_predicate_unsupported
,
1155 asmparser_coissue_unsupported
,
1157 asmparser_dcl_output_unsupported
,
1158 asmparser_dcl_input
,
1159 asmparser_dcl_sampler_unsupported
,
1166 static const struct asmparser_backend parser_vs_2
= {
1171 asmparser_dstreg_vs_2
,
1172 asmparser_srcreg_vs_2
,
1174 asmparser_predicate_supported
,
1175 asmparser_coissue_unsupported
,
1177 asmparser_dcl_output_unsupported
,
1178 asmparser_dcl_input
,
1179 asmparser_dcl_sampler_unsupported
,
1186 static const struct asmparser_backend parser_vs_3
= {
1191 asmparser_dstreg_vs_3
,
1192 asmparser_srcreg_vs_3
,
1194 asmparser_predicate_supported
,
1195 asmparser_coissue_unsupported
,
1197 asmparser_dcl_output
,
1198 asmparser_dcl_input
,
1199 asmparser_dcl_sampler
,
1206 static const struct asmparser_backend parser_ps_1_0123
= {
1211 asmparser_dstreg_ps_1_0123
,
1212 asmparser_srcreg_ps_1_0123
,
1214 asmparser_predicate_unsupported
,
1215 asmparser_coissue_supported
,
1217 asmparser_dcl_output_unsupported
,
1218 asmparser_dcl_input_unsupported
,
1219 asmparser_dcl_sampler_unsupported
,
1226 static const struct asmparser_backend parser_ps_1_4
= {
1231 asmparser_dstreg_ps_1_4
,
1232 asmparser_srcreg_ps_1_4
,
1234 asmparser_predicate_unsupported
,
1235 asmparser_coissue_supported
,
1237 asmparser_dcl_output_unsupported
,
1238 asmparser_dcl_input_unsupported
,
1239 asmparser_dcl_sampler_unsupported
,
1246 static const struct asmparser_backend parser_ps_2
= {
1251 asmparser_dstreg_ps_2
,
1252 asmparser_srcreg_ps_2
,
1254 asmparser_predicate_unsupported
,
1255 asmparser_coissue_unsupported
,
1257 asmparser_dcl_output_unsupported
,
1258 asmparser_dcl_input_ps_2
,
1259 asmparser_dcl_sampler
,
1266 static const struct asmparser_backend parser_ps_2_x
= {
1271 asmparser_dstreg_ps_2_x
,
1272 asmparser_srcreg_ps_2_x
,
1274 asmparser_predicate_supported
,
1275 asmparser_coissue_unsupported
,
1277 asmparser_dcl_output_unsupported
,
1278 asmparser_dcl_input_ps_2
,
1279 asmparser_dcl_sampler
,
1286 static const struct asmparser_backend parser_ps_3
= {
1291 asmparser_dstreg_ps_3
,
1292 asmparser_srcreg_ps_3
,
1294 asmparser_predicate_supported
,
1295 asmparser_coissue_unsupported
,
1297 asmparser_dcl_output_unsupported
,
1298 asmparser_dcl_input
,
1299 asmparser_dcl_sampler
,
1306 static void gen_oldvs_output(struct bwriter_shader
*shader
) {
1307 record_declaration(shader
, BWRITERDECLUSAGE_POSITION
, 0, 0, TRUE
, OPOS_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1308 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 0, 0, TRUE
, OT0_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1309 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 1, 0, TRUE
, OT1_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1310 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 2, 0, TRUE
, OT2_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1311 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 3, 0, TRUE
, OT3_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1312 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 4, 0, TRUE
, OT4_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1313 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 5, 0, TRUE
, OT5_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1314 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 6, 0, TRUE
, OT6_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1315 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 7, 0, TRUE
, OT7_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1316 record_declaration(shader
, BWRITERDECLUSAGE_FOG
, 0, 0, TRUE
, OFOG_REG
, OFOG_WRITEMASK
, TRUE
);
1317 record_declaration(shader
, BWRITERDECLUSAGE_PSIZE
, 0, 0, TRUE
, OPTS_REG
, OPTS_WRITEMASK
, TRUE
);
1318 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 0, 0, TRUE
, OD0_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1319 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 1, 0, TRUE
, OD1_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1322 static void gen_oldps_input(struct bwriter_shader
*shader
, DWORD texcoords
) {
1324 case 8: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 7, 0, FALSE
, T7_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1326 case 7: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 6, 0, FALSE
, T6_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1328 case 6: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 5, 0, FALSE
, T5_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1330 case 5: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 4, 0, FALSE
, T4_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1332 case 4: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 3, 0, FALSE
, T3_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1334 case 3: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 2, 0, FALSE
, T2_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1336 case 2: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 1, 0, FALSE
, T1_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1338 case 1: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 0, 0, FALSE
, T0_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1340 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 0, 0, FALSE
, C0_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1341 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 1, 0, FALSE
, C1_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1344 void create_vs10_parser(struct asm_parser
*ret
) {
1345 TRACE_(parsed_shader
)("vs_1_0\n");
1347 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1349 ERR("Failed to allocate memory for the shader\n");
1350 set_parse_status(&ret
->status
, PARSE_ERR
);
1354 ret
->shader
->type
= ST_VERTEX
;
1355 ret
->shader
->major_version
= 1;
1356 ret
->shader
->minor_version
= 0;
1357 ret
->funcs
= &parser_vs_1
;
1358 gen_oldvs_output(ret
->shader
);
1361 void create_vs11_parser(struct asm_parser
*ret
) {
1362 TRACE_(parsed_shader
)("vs_1_1\n");
1364 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1366 ERR("Failed to allocate memory for the shader\n");
1367 set_parse_status(&ret
->status
, PARSE_ERR
);
1371 ret
->shader
->type
= ST_VERTEX
;
1372 ret
->shader
->major_version
= 1;
1373 ret
->shader
->minor_version
= 1;
1374 ret
->funcs
= &parser_vs_1
;
1375 gen_oldvs_output(ret
->shader
);
1378 void create_vs20_parser(struct asm_parser
*ret
) {
1379 TRACE_(parsed_shader
)("vs_2_0\n");
1381 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1383 ERR("Failed to allocate memory for the shader\n");
1384 set_parse_status(&ret
->status
, PARSE_ERR
);
1388 ret
->shader
->type
= ST_VERTEX
;
1389 ret
->shader
->major_version
= 2;
1390 ret
->shader
->minor_version
= 0;
1391 ret
->funcs
= &parser_vs_2
;
1392 gen_oldvs_output(ret
->shader
);
1395 void create_vs2x_parser(struct asm_parser
*ret
) {
1396 TRACE_(parsed_shader
)("vs_2_x\n");
1398 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1400 ERR("Failed to allocate memory for the shader\n");
1401 set_parse_status(&ret
->status
, PARSE_ERR
);
1405 ret
->shader
->type
= ST_VERTEX
;
1406 ret
->shader
->major_version
= 2;
1407 ret
->shader
->minor_version
= 1;
1408 ret
->funcs
= &parser_vs_2
;
1409 gen_oldvs_output(ret
->shader
);
1412 void create_vs30_parser(struct asm_parser
*ret
) {
1413 TRACE_(parsed_shader
)("vs_3_0\n");
1415 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1417 ERR("Failed to allocate memory for the shader\n");
1418 set_parse_status(&ret
->status
, PARSE_ERR
);
1422 ret
->shader
->type
= ST_VERTEX
;
1423 ret
->shader
->major_version
= 3;
1424 ret
->shader
->minor_version
= 0;
1425 ret
->funcs
= &parser_vs_3
;
1428 void create_ps10_parser(struct asm_parser
*ret
) {
1429 TRACE_(parsed_shader
)("ps_1_0\n");
1431 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1433 ERR("Failed to allocate memory for the shader\n");
1434 set_parse_status(&ret
->status
, PARSE_ERR
);
1438 ret
->shader
->type
= ST_PIXEL
;
1439 ret
->shader
->major_version
= 1;
1440 ret
->shader
->minor_version
= 0;
1441 ret
->funcs
= &parser_ps_1_0123
;
1442 gen_oldps_input(ret
->shader
, 4);
1445 void create_ps11_parser(struct asm_parser
*ret
) {
1446 TRACE_(parsed_shader
)("ps_1_1\n");
1448 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1450 ERR("Failed to allocate memory for the shader\n");
1451 set_parse_status(&ret
->status
, PARSE_ERR
);
1455 ret
->shader
->type
= ST_PIXEL
;
1456 ret
->shader
->major_version
= 1;
1457 ret
->shader
->minor_version
= 1;
1458 ret
->funcs
= &parser_ps_1_0123
;
1459 gen_oldps_input(ret
->shader
, 4);
1462 void create_ps12_parser(struct asm_parser
*ret
) {
1463 TRACE_(parsed_shader
)("ps_1_2\n");
1465 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1467 ERR("Failed to allocate memory for the shader\n");
1468 set_parse_status(&ret
->status
, PARSE_ERR
);
1472 ret
->shader
->type
= ST_PIXEL
;
1473 ret
->shader
->major_version
= 1;
1474 ret
->shader
->minor_version
= 2;
1475 ret
->funcs
= &parser_ps_1_0123
;
1476 gen_oldps_input(ret
->shader
, 4);
1479 void create_ps13_parser(struct asm_parser
*ret
) {
1480 TRACE_(parsed_shader
)("ps_1_3\n");
1482 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1484 ERR("Failed to allocate memory for the shader\n");
1485 set_parse_status(&ret
->status
, PARSE_ERR
);
1489 ret
->shader
->type
= ST_PIXEL
;
1490 ret
->shader
->major_version
= 1;
1491 ret
->shader
->minor_version
= 3;
1492 ret
->funcs
= &parser_ps_1_0123
;
1493 gen_oldps_input(ret
->shader
, 4);
1496 void create_ps14_parser(struct asm_parser
*ret
) {
1497 TRACE_(parsed_shader
)("ps_1_4\n");
1499 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1501 ERR("Failed to allocate memory for the shader\n");
1502 set_parse_status(&ret
->status
, PARSE_ERR
);
1506 ret
->shader
->type
= ST_PIXEL
;
1507 ret
->shader
->major_version
= 1;
1508 ret
->shader
->minor_version
= 4;
1509 ret
->funcs
= &parser_ps_1_4
;
1510 gen_oldps_input(ret
->shader
, 6);
1513 void create_ps20_parser(struct asm_parser
*ret
) {
1514 TRACE_(parsed_shader
)("ps_2_0\n");
1516 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1518 ERR("Failed to allocate memory for the shader\n");
1519 set_parse_status(&ret
->status
, PARSE_ERR
);
1523 ret
->shader
->type
= ST_PIXEL
;
1524 ret
->shader
->major_version
= 2;
1525 ret
->shader
->minor_version
= 0;
1526 ret
->funcs
= &parser_ps_2
;
1527 gen_oldps_input(ret
->shader
, 8);
1530 void create_ps2x_parser(struct asm_parser
*ret
) {
1531 TRACE_(parsed_shader
)("ps_2_x\n");
1533 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1535 ERR("Failed to allocate memory for the shader\n");
1536 set_parse_status(&ret
->status
, PARSE_ERR
);
1540 ret
->shader
->type
= ST_PIXEL
;
1541 ret
->shader
->major_version
= 2;
1542 ret
->shader
->minor_version
= 1;
1543 ret
->funcs
= &parser_ps_2_x
;
1544 gen_oldps_input(ret
->shader
, 8);
1547 void create_ps30_parser(struct asm_parser
*ret
) {
1548 TRACE_(parsed_shader
)("ps_3_0\n");
1550 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1552 ERR("Failed to allocate memory for the shader\n");
1553 set_parse_status(&ret
->status
, PARSE_ERR
);
1557 ret
->shader
->type
= ST_PIXEL
;
1558 ret
->shader
->major_version
= 3;
1559 ret
->shader
->minor_version
= 0;
1560 ret
->funcs
= &parser_ps_3
;