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 "d3dcompiler_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
->status
, 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
->status
, 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
->status
, 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
->status
, PARSE_ERR
);
113 if(!record_declaration(This
->shader
, usage
, num
, 0, TRUE
, reg
->regnum
, reg
->u
.writemask
, FALSE
)) {
114 ERR("Out of memory\n");
115 set_parse_status(&This
->status
, PARSE_ERR
);
119 static void asmparser_dcl_output_unsupported(struct asm_parser
*This
, DWORD usage
, DWORD num
,
120 const struct shader_reg
*reg
) {
121 asmparser_message(This
, "Line %u: Output declaration unsupported in this shader version\n", This
->line_no
);
122 set_parse_status(&This
->status
, PARSE_ERR
);
125 static void asmparser_dcl_input(struct asm_parser
*This
, DWORD usage
, DWORD num
,
126 DWORD mod
, const struct shader_reg
*reg
) {
127 struct instruction instr
;
129 if(!This
->shader
) return;
131 (This
->shader
->version
!= BWRITERPS_VERSION(3, 0) ||
132 (mod
!= BWRITERSPDM_MSAMPCENTROID
&&
133 mod
!= BWRITERSPDM_PARTIALPRECISION
))) {
134 asmparser_message(This
, "Line %u: Unsupported modifier in dcl instruction\n", This
->line_no
);
135 set_parse_status(&This
->status
, PARSE_ERR
);
139 /* Check register type and modifiers */
142 This
->funcs
->dstreg(This
, &instr
, reg
);
144 if(!record_declaration(This
->shader
, usage
, num
, mod
, FALSE
, reg
->regnum
, reg
->u
.writemask
, FALSE
)) {
145 ERR("Out of memory\n");
146 set_parse_status(&This
->status
, PARSE_ERR
);
150 static void asmparser_dcl_input_ps_2(struct asm_parser
*This
, DWORD usage
, DWORD num
,
151 DWORD mod
, const struct shader_reg
*reg
) {
152 struct instruction instr
;
154 if(!This
->shader
) return;
157 This
->funcs
->dstreg(This
, &instr
, reg
);
158 if(!record_declaration(This
->shader
, usage
, num
, mod
, FALSE
, instr
.dst
.regnum
, instr
.dst
.u
.writemask
, FALSE
)) {
159 ERR("Out of memory\n");
160 set_parse_status(&This
->status
, PARSE_ERR
);
164 static void asmparser_dcl_input_unsupported(struct asm_parser
*This
,
165 DWORD usage
, DWORD num
, DWORD mod
, const struct shader_reg
*reg
)
167 asmparser_message(This
, "Line %u: Input declaration unsupported in this shader version\n", This
->line_no
);
168 set_parse_status(&This
->status
, PARSE_ERR
);
171 static void asmparser_dcl_sampler(struct asm_parser
*This
, DWORD samptype
,
172 DWORD mod
, DWORD regnum
,
173 unsigned int line_no
) {
174 if(!This
->shader
) return;
176 (This
->shader
->version
!= BWRITERPS_VERSION(3, 0) ||
177 (mod
!= BWRITERSPDM_MSAMPCENTROID
&&
178 mod
!= BWRITERSPDM_PARTIALPRECISION
))) {
179 asmparser_message(This
, "Line %u: Unsupported modifier in dcl instruction\n", This
->line_no
);
180 set_parse_status(&This
->status
, PARSE_ERR
);
183 if(!record_sampler(This
->shader
, samptype
, mod
, regnum
)) {
184 ERR("Out of memory\n");
185 set_parse_status(&This
->status
, PARSE_ERR
);
189 static void asmparser_dcl_sampler_unsupported(struct asm_parser
*This
,
190 DWORD samptype
, DWORD mod
, DWORD regnum
, unsigned int line_no
)
192 asmparser_message(This
, "Line %u: Sampler declaration unsupported in this shader version\n", This
->line_no
);
193 set_parse_status(&This
->status
, PARSE_ERR
);
196 static void asmparser_sincos(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
197 const struct shader_reg
*dst
,
198 const struct src_regs
*srcs
) {
199 struct instruction
*instr
;
201 if(!srcs
|| srcs
->count
!= 3) {
202 asmparser_message(This
, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This
->line_no
);
203 set_parse_status(&This
->status
, PARSE_ERR
);
207 instr
= alloc_instr(3);
209 ERR("Error allocating memory for the instruction\n");
210 set_parse_status(&This
->status
, PARSE_ERR
);
214 instr
->opcode
= BWRITERSIO_SINCOS
;
216 instr
->shift
= shift
;
219 This
->funcs
->dstreg(This
, instr
, dst
);
220 This
->funcs
->srcreg(This
, instr
, 0, &srcs
->reg
[0]);
221 This
->funcs
->srcreg(This
, instr
, 1, &srcs
->reg
[1]);
222 This
->funcs
->srcreg(This
, instr
, 2, &srcs
->reg
[2]);
224 if(!add_instruction(This
->shader
, instr
)) {
225 ERR("Out of memory\n");
226 set_parse_status(&This
->status
, PARSE_ERR
);
230 static struct shader_reg
map_oldps_register(const struct shader_reg
*reg
, BOOL tex_varying
) {
231 struct shader_reg ret
;
233 case BWRITERSPR_TEXTURE
:
236 ret
.type
= BWRITERSPR_INPUT
;
237 switch(reg
->regnum
) {
238 case 0: ret
.regnum
= T0_VARYING
; break;
239 case 1: ret
.regnum
= T1_VARYING
; break;
240 case 2: ret
.regnum
= T2_VARYING
; break;
241 case 3: ret
.regnum
= T3_VARYING
; break;
242 case 4: ret
.regnum
= T4_VARYING
; break;
243 case 5: ret
.regnum
= T5_VARYING
; break;
244 case 6: ret
.regnum
= T6_VARYING
; break;
245 case 7: ret
.regnum
= T7_VARYING
; break;
247 FIXME("Unexpected TEXTURE register t%u\n", reg
->regnum
);
253 ret
.type
= BWRITERSPR_TEMP
;
254 switch(reg
->regnum
) {
255 case 0: ret
.regnum
= T0_REG
; break;
256 case 1: ret
.regnum
= T1_REG
; break;
257 case 2: ret
.regnum
= T2_REG
; break;
258 case 3: ret
.regnum
= T3_REG
; break;
260 FIXME("Unexpected TEXTURE register t%u\n", reg
->regnum
);
266 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
269 default: return *reg
;
273 static void asmparser_texcoord(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
274 const struct shader_reg
*dst
,
275 const struct src_regs
*srcs
) {
276 struct instruction
*instr
;
279 asmparser_message(This
, "Line %u: Source registers in texcoord instruction\n", This
->line_no
);
280 set_parse_status(&This
->status
, PARSE_ERR
);
284 instr
= alloc_instr(1);
286 ERR("Error allocating memory for the instruction\n");
287 set_parse_status(&This
->status
, PARSE_ERR
);
291 /* texcoord copies the texture coord data into a temporary register-like
292 * readable form. In newer shader models this equals a MOV from v0 to r0,
295 instr
->opcode
= BWRITERSIO_MOV
;
296 instr
->dstmod
= mod
| BWRITERSPDM_SATURATE
; /* texcoord clamps to [0;1] */
297 instr
->shift
= shift
;
300 This
->funcs
->dstreg(This
, instr
, dst
);
301 /* The src reg needs special care */
302 instr
->src
[0] = map_oldps_register(dst
, TRUE
);
304 if(!add_instruction(This
->shader
, instr
)) {
305 ERR("Out of memory\n");
306 set_parse_status(&This
->status
, PARSE_ERR
);
310 static void asmparser_texcrd(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
311 const struct shader_reg
*dst
,
312 const struct src_regs
*srcs
) {
313 struct instruction
*instr
;
315 if(!srcs
|| srcs
->count
!= 1) {
316 asmparser_message(This
, "Line %u: Wrong number of source registers in texcrd instruction\n", This
->line_no
);
317 set_parse_status(&This
->status
, PARSE_ERR
);
321 instr
= alloc_instr(1);
323 ERR("Error allocating memory for the instruction\n");
324 set_parse_status(&This
->status
, PARSE_ERR
);
328 /* The job of texcrd is done by mov in later shader versions */
329 instr
->opcode
= BWRITERSIO_MOV
;
331 instr
->shift
= shift
;
334 This
->funcs
->dstreg(This
, instr
, dst
);
335 This
->funcs
->srcreg(This
, instr
, 0, &srcs
->reg
[0]);
337 if(!add_instruction(This
->shader
, instr
)) {
338 ERR("Out of memory\n");
339 set_parse_status(&This
->status
, PARSE_ERR
);
343 static void asmparser_texkill(struct asm_parser
*This
,
344 const struct shader_reg
*dst
) {
345 struct instruction
*instr
= alloc_instr(0);
348 ERR("Error allocating memory for the instruction\n");
349 set_parse_status(&This
->status
, PARSE_ERR
);
353 instr
->opcode
= BWRITERSIO_TEXKILL
;
358 /* Do not run the dst register through the normal
359 * register conversion. If used with ps_1_0 to ps_1_3
360 * the texture coordinate from that register is used,
361 * not the temporary register value. In ps_1_4 and
362 * ps_2_0 t0 is always a varying and temporaries can
363 * be used with texkill.
365 instr
->dst
= map_oldps_register(dst
, TRUE
);
366 instr
->has_dst
= TRUE
;
368 if(!add_instruction(This
->shader
, instr
)) {
369 ERR("Out of memory\n");
370 set_parse_status(&This
->status
, PARSE_ERR
);
374 static void asmparser_texhelper(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
375 const struct shader_reg
*dst
,
376 const struct shader_reg
*src0
) {
377 struct instruction
*instr
= alloc_instr(2);
380 ERR("Error allocating memory for the instruction\n");
381 set_parse_status(&This
->status
, PARSE_ERR
);
385 instr
->opcode
= BWRITERSIO_TEX
;
387 instr
->shift
= shift
;
389 /* The dest register can be mapped normally to a temporary register */
390 This
->funcs
->dstreg(This
, instr
, dst
);
391 /* Use the src passed as parameter by the specific instruction handler */
392 instr
->src
[0] = *src0
;
394 /* The 2nd source register is the sampler register with the
395 * destination's regnum
397 ZeroMemory(&instr
->src
[1], sizeof(instr
->src
[1]));
398 instr
->src
[1].type
= BWRITERSPR_SAMPLER
;
399 instr
->src
[1].regnum
= dst
->regnum
;
400 instr
->src
[1].u
.swizzle
= BWRITERVS_NOSWIZZLE
;
401 instr
->src
[1].srcmod
= BWRITERSPSM_NONE
;
402 instr
->src
[1].rel_reg
= NULL
;
404 if(!add_instruction(This
->shader
, instr
)) {
405 ERR("Out of memory\n");
406 set_parse_status(&This
->status
, PARSE_ERR
);
410 static void asmparser_tex(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
411 const struct shader_reg
*dst
) {
412 struct shader_reg src
;
414 /* The first source register is the varying containing the coordinate */
415 src
= map_oldps_register(dst
, TRUE
);
416 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
419 static void asmparser_texld14(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
420 const struct shader_reg
*dst
,
421 const struct src_regs
*srcs
) {
422 struct instruction
*instr
;
424 if(!srcs
|| srcs
->count
!= 1) {
425 asmparser_message(This
, "Line %u: texld (PS 1.4) has a wrong number of source registers\n", This
->line_no
);
426 set_parse_status(&This
->status
, PARSE_ERR
);
430 instr
= alloc_instr(2);
432 ERR("Error allocating memory for the instruction\n");
433 set_parse_status(&This
->status
, PARSE_ERR
);
437 /* This code is recording a texld instruction, not tex. However,
438 * texld borrows the opcode of tex
440 instr
->opcode
= BWRITERSIO_TEX
;
442 instr
->shift
= shift
;
445 This
->funcs
->dstreg(This
, instr
, dst
);
446 This
->funcs
->srcreg(This
, instr
, 0, &srcs
->reg
[0]);
448 /* The 2nd source register is the sampler register with the
449 * destination's regnum
451 ZeroMemory(&instr
->src
[1], sizeof(instr
->src
[1]));
452 instr
->src
[1].type
= BWRITERSPR_SAMPLER
;
453 instr
->src
[1].regnum
= dst
->regnum
;
454 instr
->src
[1].u
.swizzle
= BWRITERVS_NOSWIZZLE
;
455 instr
->src
[1].srcmod
= BWRITERSPSM_NONE
;
456 instr
->src
[1].rel_reg
= NULL
;
458 if(!add_instruction(This
->shader
, instr
)) {
459 ERR("Out of memory\n");
460 set_parse_status(&This
->status
, PARSE_ERR
);
464 static void asmparser_texreg2ar(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
465 const struct shader_reg
*dst
,
466 const struct shader_reg
*src0
) {
467 struct shader_reg src
;
469 src
= map_oldps_register(src0
, FALSE
);
470 /* Supply the correct swizzle */
471 src
.u
.swizzle
= BWRITERVS_X_W
| BWRITERVS_Y_X
| BWRITERVS_Z_X
| BWRITERVS_W_X
;
472 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
475 static void asmparser_texreg2gb(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
476 const struct shader_reg
*dst
,
477 const struct shader_reg
*src0
) {
478 struct shader_reg src
;
480 src
= map_oldps_register(src0
, FALSE
);
481 /* Supply the correct swizzle */
482 src
.u
.swizzle
= BWRITERVS_X_Y
| BWRITERVS_Y_Z
| BWRITERVS_Z_Z
| BWRITERVS_W_Z
;
483 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
486 static void asmparser_texreg2rgb(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
487 const struct shader_reg
*dst
,
488 const struct shader_reg
*src0
) {
489 struct shader_reg src
;
491 src
= map_oldps_register(src0
, FALSE
);
492 /* Supply the correct swizzle */
493 src
.u
.swizzle
= BWRITERVS_X_X
| BWRITERVS_Y_Y
| BWRITERVS_Z_Z
| BWRITERVS_W_Z
;
494 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
497 /* Complex pixel shader 1.3 instructions like texm3x3tex are tricky - the
498 * bytecode writer works instruction by instruction, so we can't properly
499 * convert these from/to equivalent ps_3_0 instructions. Then simply keep using
500 * the ps_1_3 opcodes and just adapt the registers in the common fashion (i.e.
501 * go through asmparser_instr).
504 static void asmparser_instr(struct asm_parser
*This
, DWORD opcode
, DWORD mod
, DWORD shift
,
505 enum bwriter_comparison_type comp
, const struct shader_reg
*dst
,
506 const struct src_regs
*srcs
, int expectednsrcs
)
508 struct instruction
*instr
;
510 BOOL firstreg
= TRUE
;
511 unsigned int src_count
= srcs
? srcs
->count
: 0;
513 if(!This
->shader
) return;
515 TRACE_(parsed_shader
)("%s%s%s%s ", debug_print_opcode(opcode
),
516 debug_print_dstmod(mod
),
517 debug_print_shift(shift
),
518 debug_print_comp(comp
));
520 TRACE_(parsed_shader
)("%s", debug_print_dstreg(dst
));
523 for(i
= 0; i
< src_count
; i
++) {
524 if(!firstreg
) TRACE_(parsed_shader
)(", ");
525 else firstreg
= FALSE
;
526 TRACE_(parsed_shader
)("%s", debug_print_srcreg(&srcs
->reg
[i
]));
528 TRACE_(parsed_shader
)("\n");
530 /* Check for instructions with different syntaxes in different shader versions */
532 case BWRITERSIO_SINCOS
:
533 /* The syntax changes between vs 2 and the other shader versions */
534 if(This
->shader
->version
== BWRITERVS_VERSION(2, 0) ||
535 This
->shader
->version
== BWRITERVS_VERSION(2, 1)) {
536 asmparser_sincos(This
, mod
, shift
, dst
, srcs
);
539 /* Use the default handling */
541 case BWRITERSIO_TEXCOORD
:
542 /* texcoord/texcrd are two instructions present only in PS <= 1.3 and PS 1.4 respectively */
543 if(This
->shader
->version
== BWRITERPS_VERSION(1, 4))
544 asmparser_texcrd(This
, mod
, shift
, dst
, srcs
);
545 else asmparser_texcoord(This
, mod
, shift
, dst
, srcs
);
548 /* this encodes both the tex PS 1.x instruction and the
549 texld 1.4/2.0+ instruction */
550 if(This
->shader
->version
== BWRITERPS_VERSION(1, 0) ||
551 This
->shader
->version
== BWRITERPS_VERSION(1, 1) ||
552 This
->shader
->version
== BWRITERPS_VERSION(1, 2) ||
553 This
->shader
->version
== BWRITERPS_VERSION(1, 3)) {
554 asmparser_tex(This
, mod
, shift
, dst
);
557 else if(This
->shader
->version
== BWRITERPS_VERSION(1, 4)) {
558 asmparser_texld14(This
, mod
, shift
, dst
, srcs
);
561 /* else fallback to the standard behavior */
565 if(src_count
!= expectednsrcs
) {
566 asmparser_message(This
, "Line %u: Wrong number of source registers\n", This
->line_no
);
567 set_parse_status(&This
->status
, PARSE_ERR
);
571 /* Handle PS 1.x instructions, "regularizing" them */
573 case BWRITERSIO_TEXKILL
:
574 asmparser_texkill(This
, dst
);
576 case BWRITERSIO_TEXREG2AR
:
577 asmparser_texreg2ar(This
, mod
, shift
, dst
, &srcs
->reg
[0]);
579 case BWRITERSIO_TEXREG2GB
:
580 asmparser_texreg2gb(This
, mod
, shift
, dst
, &srcs
->reg
[0]);
582 case BWRITERSIO_TEXREG2RGB
:
583 asmparser_texreg2rgb(This
, mod
, shift
, dst
, &srcs
->reg
[0]);
587 instr
= alloc_instr(src_count
);
589 ERR("Error allocating memory for the instruction\n");
590 set_parse_status(&This
->status
, PARSE_ERR
);
594 instr
->opcode
= opcode
;
596 instr
->shift
= shift
;
597 instr
->comptype
= comp
;
598 if(dst
) This
->funcs
->dstreg(This
, instr
, dst
);
599 for(i
= 0; i
< src_count
; i
++) {
600 This
->funcs
->srcreg(This
, instr
, i
, &srcs
->reg
[i
]);
603 if(!add_instruction(This
->shader
, instr
)) {
604 ERR("Out of memory\n");
605 set_parse_status(&This
->status
, PARSE_ERR
);
609 static struct shader_reg
map_oldvs_register(const struct shader_reg
*reg
) {
610 struct shader_reg ret
;
612 case BWRITERSPR_RASTOUT
:
614 ret
.type
= BWRITERSPR_OUTPUT
;
615 switch(reg
->regnum
) {
616 case BWRITERSRO_POSITION
:
617 ret
.regnum
= OPOS_REG
;
620 ret
.regnum
= OFOG_REG
;
621 ret
.u
.writemask
= OFOG_WRITEMASK
;
623 case BWRITERSRO_POINT_SIZE
:
624 ret
.regnum
= OPTS_REG
;
625 ret
.u
.writemask
= OPTS_WRITEMASK
;
628 FIXME("Unhandled RASTOUT register %u\n", reg
->regnum
);
633 case BWRITERSPR_TEXCRDOUT
:
635 ret
.type
= BWRITERSPR_OUTPUT
;
636 switch(reg
->regnum
) {
637 case 0: ret
.regnum
= OT0_REG
; break;
638 case 1: ret
.regnum
= OT1_REG
; break;
639 case 2: ret
.regnum
= OT2_REG
; break;
640 case 3: ret
.regnum
= OT3_REG
; break;
641 case 4: ret
.regnum
= OT4_REG
; break;
642 case 5: ret
.regnum
= OT5_REG
; break;
643 case 6: ret
.regnum
= OT6_REG
; break;
644 case 7: ret
.regnum
= OT7_REG
; break;
646 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg
->regnum
);
651 case BWRITERSPR_ATTROUT
:
653 ret
.type
= BWRITERSPR_OUTPUT
;
654 switch(reg
->regnum
) {
655 case 0: ret
.regnum
= OD0_REG
; break;
656 case 1: ret
.regnum
= OD1_REG
; break;
658 FIXME("Unhandled ATTROUT regnum %u\n", reg
->regnum
);
663 default: return *reg
;
667 /* Checks for unsupported source modifiers in VS (all versions) or
669 static void check_legacy_srcmod(struct asm_parser
*This
, DWORD srcmod
) {
670 if(srcmod
== BWRITERSPSM_BIAS
|| srcmod
== BWRITERSPSM_BIASNEG
||
671 srcmod
== BWRITERSPSM_SIGN
|| srcmod
== BWRITERSPSM_SIGNNEG
||
672 srcmod
== BWRITERSPSM_COMP
|| srcmod
== BWRITERSPSM_X2
||
673 srcmod
== BWRITERSPSM_X2NEG
|| srcmod
== BWRITERSPSM_DZ
||
674 srcmod
== BWRITERSPSM_DW
) {
675 asmparser_message(This
, "Line %u: Source modifier %s not supported in this shader version\n",
677 debug_print_srcmod(srcmod
));
678 set_parse_status(&This
->status
, PARSE_ERR
);
682 static void check_abs_srcmod(struct asm_parser
*This
, DWORD srcmod
) {
683 if(srcmod
== BWRITERSPSM_ABS
|| srcmod
== BWRITERSPSM_ABSNEG
) {
684 asmparser_message(This
, "Line %u: Source modifier %s not supported in this shader version\n",
686 debug_print_srcmod(srcmod
));
687 set_parse_status(&This
->status
, PARSE_ERR
);
691 static void check_loop_swizzle(struct asm_parser
*This
,
692 const struct shader_reg
*src
) {
693 if((src
->type
== BWRITERSPR_LOOP
&& src
->u
.swizzle
!= BWRITERVS_NOSWIZZLE
) ||
694 (src
->rel_reg
&& src
->rel_reg
->type
== BWRITERSPR_LOOP
&&
695 src
->rel_reg
->u
.swizzle
!= BWRITERVS_NOSWIZZLE
)) {
696 asmparser_message(This
, "Line %u: Swizzle not allowed on aL register\n", This
->line_no
);
697 set_parse_status(&This
->status
, PARSE_ERR
);
701 static void check_shift_dstmod(struct asm_parser
*This
, DWORD shift
) {
703 asmparser_message(This
, "Line %u: Shift modifiers not supported in this shader version\n",
705 set_parse_status(&This
->status
, PARSE_ERR
);
709 static void check_ps_dstmod(struct asm_parser
*This
, DWORD dstmod
) {
710 if(dstmod
== BWRITERSPDM_PARTIALPRECISION
||
711 dstmod
== BWRITERSPDM_MSAMPCENTROID
) {
712 asmparser_message(This
, "Line %u: Instruction modifier %s not supported in this shader version\n",
714 debug_print_dstmod(dstmod
));
715 set_parse_status(&This
->status
, PARSE_ERR
);
719 struct allowed_reg_type
{
725 static BOOL
check_reg_type(const struct shader_reg
*reg
,
726 const struct allowed_reg_type
*allowed
) {
729 while(allowed
[i
].type
!= ~0U) {
730 if(reg
->type
== allowed
[i
].type
) {
732 if(allowed
[i
].reladdr
)
733 return TRUE
; /* The relative addressing register
734 can have a negative value, we
735 can't check the register index */
738 if(reg
->regnum
< allowed
[i
].count
) return TRUE
;
746 /* Native assembler doesn't do separate checks for src and dst registers */
747 static const struct allowed_reg_type vs_1_reg_allowed
[] = {
748 { BWRITERSPR_TEMP
, 12, FALSE
},
749 { BWRITERSPR_INPUT
, 16, FALSE
},
750 { BWRITERSPR_CONST
, ~0U, TRUE
},
751 { BWRITERSPR_ADDR
, 1, FALSE
},
752 { BWRITERSPR_RASTOUT
, 3, FALSE
}, /* oPos, oFog and oPts */
753 { BWRITERSPR_ATTROUT
, 2, FALSE
},
754 { BWRITERSPR_TEXCRDOUT
, 8, FALSE
},
755 { ~0U, 0 } /* End tag */
758 /* struct instruction *asmparser_srcreg
760 * Records a source register in the instruction and does shader version
761 * specific checks and modifications on it
764 * This: Shader parser instance
765 * instr: instruction to store the register in
766 * num: Number of source register
767 * src: Pointer to source the register structure. The caller can free
770 static void asmparser_srcreg_vs_1(struct asm_parser
*This
,
771 struct instruction
*instr
, int num
,
772 const struct shader_reg
*src
) {
773 struct shader_reg reg
;
775 if(!check_reg_type(src
, vs_1_reg_allowed
)) {
776 asmparser_message(This
, "Line %u: Source register %s not supported in VS 1\n",
778 debug_print_srcreg(src
));
779 set_parse_status(&This
->status
, PARSE_ERR
);
781 check_legacy_srcmod(This
, src
->srcmod
);
782 check_abs_srcmod(This
, src
->srcmod
);
783 reg
= map_oldvs_register(src
);
784 instr
->src
[num
] = reg
;
787 static const struct allowed_reg_type vs_2_reg_allowed
[] = {
788 { BWRITERSPR_TEMP
, 12, FALSE
},
789 { BWRITERSPR_INPUT
, 16, FALSE
},
790 { BWRITERSPR_CONST
, ~0U, TRUE
},
791 { BWRITERSPR_ADDR
, 1, FALSE
},
792 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
793 { BWRITERSPR_CONSTINT
, 16, FALSE
},
794 { BWRITERSPR_LOOP
, 1, FALSE
},
795 { BWRITERSPR_LABEL
, 2048, FALSE
},
796 { BWRITERSPR_PREDICATE
, 1, FALSE
},
797 { BWRITERSPR_RASTOUT
, 3, FALSE
}, /* oPos, oFog and oPts */
798 { BWRITERSPR_ATTROUT
, 2, FALSE
},
799 { BWRITERSPR_TEXCRDOUT
, 8, FALSE
},
800 { ~0U, 0 } /* End tag */
803 static void asmparser_srcreg_vs_2(struct asm_parser
*This
,
804 struct instruction
*instr
, int num
,
805 const struct shader_reg
*src
) {
806 struct shader_reg reg
;
808 if(!check_reg_type(src
, vs_2_reg_allowed
)) {
809 asmparser_message(This
, "Line %u: Source register %s not supported in VS 2\n",
811 debug_print_srcreg(src
));
812 set_parse_status(&This
->status
, PARSE_ERR
);
814 check_loop_swizzle(This
, src
);
815 check_legacy_srcmod(This
, src
->srcmod
);
816 check_abs_srcmod(This
, src
->srcmod
);
817 reg
= map_oldvs_register(src
);
818 instr
->src
[num
] = reg
;
821 static const struct allowed_reg_type vs_3_reg_allowed
[] = {
822 { BWRITERSPR_TEMP
, 32, FALSE
},
823 { BWRITERSPR_INPUT
, 16, TRUE
},
824 { BWRITERSPR_CONST
, ~0U, TRUE
},
825 { BWRITERSPR_ADDR
, 1, FALSE
},
826 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
827 { BWRITERSPR_CONSTINT
, 16, FALSE
},
828 { BWRITERSPR_LOOP
, 1, FALSE
},
829 { BWRITERSPR_LABEL
, 2048, FALSE
},
830 { BWRITERSPR_PREDICATE
, 1, FALSE
},
831 { BWRITERSPR_SAMPLER
, 4, FALSE
},
832 { BWRITERSPR_OUTPUT
, 12, TRUE
},
833 { ~0U, 0 } /* End tag */
836 static void asmparser_srcreg_vs_3(struct asm_parser
*This
,
837 struct instruction
*instr
, int num
,
838 const struct shader_reg
*src
) {
839 if(!check_reg_type(src
, vs_3_reg_allowed
)) {
840 asmparser_message(This
, "Line %u: Source register %s not supported in VS 3.0\n",
842 debug_print_srcreg(src
));
843 set_parse_status(&This
->status
, PARSE_ERR
);
845 check_loop_swizzle(This
, src
);
846 check_legacy_srcmod(This
, src
->srcmod
);
847 instr
->src
[num
] = *src
;
850 static const struct allowed_reg_type ps_1_0123_reg_allowed
[] = {
851 { BWRITERSPR_CONST
, 8, FALSE
},
852 { BWRITERSPR_TEMP
, 2, FALSE
},
853 { BWRITERSPR_TEXTURE
, 4, FALSE
},
854 { BWRITERSPR_INPUT
, 2, FALSE
},
855 { ~0U, 0 } /* End tag */
858 static void asmparser_srcreg_ps_1_0123(struct asm_parser
*This
,
859 struct instruction
*instr
, int num
,
860 const struct shader_reg
*src
) {
861 struct shader_reg reg
;
863 if(!check_reg_type(src
, ps_1_0123_reg_allowed
)) {
864 asmparser_message(This
, "Line %u: Source register %s not supported in <== PS 1.3\n",
866 debug_print_srcreg(src
));
867 set_parse_status(&This
->status
, PARSE_ERR
);
869 check_abs_srcmod(This
, src
->srcmod
);
870 reg
= map_oldps_register(src
, FALSE
);
871 instr
->src
[num
] = reg
;
874 static const struct allowed_reg_type ps_1_4_reg_allowed
[] = {
875 { BWRITERSPR_CONST
, 8, FALSE
},
876 { BWRITERSPR_TEMP
, 6, FALSE
},
877 { BWRITERSPR_TEXTURE
, 6, FALSE
},
878 { BWRITERSPR_INPUT
, 2, FALSE
},
879 { ~0U, 0 } /* End tag */
882 static void asmparser_srcreg_ps_1_4(struct asm_parser
*This
,
883 struct instruction
*instr
, int num
,
884 const struct shader_reg
*src
) {
885 struct shader_reg reg
;
887 if(!check_reg_type(src
, ps_1_4_reg_allowed
)) {
888 asmparser_message(This
, "Line %u: Source register %s not supported in PS 1.4\n",
890 debug_print_srcreg(src
));
891 set_parse_status(&This
->status
, PARSE_ERR
);
893 check_abs_srcmod(This
, src
->srcmod
);
894 reg
= map_oldps_register(src
, TRUE
);
895 instr
->src
[num
] = reg
;
898 static const struct allowed_reg_type ps_2_0_reg_allowed
[] = {
899 { BWRITERSPR_INPUT
, 2, FALSE
},
900 { BWRITERSPR_TEMP
, 32, FALSE
},
901 { BWRITERSPR_CONST
, 32, FALSE
},
902 { BWRITERSPR_CONSTINT
, 16, FALSE
},
903 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
904 { BWRITERSPR_SAMPLER
, 16, FALSE
},
905 { BWRITERSPR_TEXTURE
, 8, FALSE
},
906 { BWRITERSPR_COLOROUT
, 4, FALSE
},
907 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
908 { ~0U, 0 } /* End tag */
911 static void asmparser_srcreg_ps_2(struct asm_parser
*This
,
912 struct instruction
*instr
, int num
,
913 const struct shader_reg
*src
) {
914 struct shader_reg reg
;
916 if(!check_reg_type(src
, ps_2_0_reg_allowed
)) {
917 asmparser_message(This
, "Line %u: Source register %s not supported in PS 2.0\n",
919 debug_print_srcreg(src
));
920 set_parse_status(&This
->status
, PARSE_ERR
);
922 check_legacy_srcmod(This
, src
->srcmod
);
923 check_abs_srcmod(This
, src
->srcmod
);
924 reg
= map_oldps_register(src
, TRUE
);
925 instr
->src
[num
] = reg
;
928 static const struct allowed_reg_type ps_2_x_reg_allowed
[] = {
929 { BWRITERSPR_INPUT
, 2, FALSE
},
930 { BWRITERSPR_TEMP
, 32, FALSE
},
931 { BWRITERSPR_CONST
, 32, FALSE
},
932 { BWRITERSPR_CONSTINT
, 16, FALSE
},
933 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
934 { BWRITERSPR_PREDICATE
, 1, FALSE
},
935 { BWRITERSPR_SAMPLER
, 16, FALSE
},
936 { BWRITERSPR_TEXTURE
, 8, FALSE
},
937 { BWRITERSPR_LABEL
, 2048, FALSE
},
938 { BWRITERSPR_COLOROUT
, 4, FALSE
},
939 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
940 { ~0U, 0 } /* End tag */
943 static void asmparser_srcreg_ps_2_x(struct asm_parser
*This
,
944 struct instruction
*instr
, int num
,
945 const struct shader_reg
*src
) {
946 struct shader_reg reg
;
948 if(!check_reg_type(src
, ps_2_x_reg_allowed
)) {
949 asmparser_message(This
, "Line %u: Source register %s not supported in PS 2.x\n",
951 debug_print_srcreg(src
));
952 set_parse_status(&This
->status
, PARSE_ERR
);
954 check_legacy_srcmod(This
, src
->srcmod
);
955 check_abs_srcmod(This
, src
->srcmod
);
956 reg
= map_oldps_register(src
, TRUE
);
957 instr
->src
[num
] = reg
;
960 static const struct allowed_reg_type ps_3_reg_allowed
[] = {
961 { BWRITERSPR_INPUT
, 10, TRUE
},
962 { BWRITERSPR_TEMP
, 32, FALSE
},
963 { BWRITERSPR_CONST
, 224, FALSE
},
964 { BWRITERSPR_CONSTINT
, 16, FALSE
},
965 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
966 { BWRITERSPR_PREDICATE
, 1, FALSE
},
967 { BWRITERSPR_SAMPLER
, 16, FALSE
},
968 { BWRITERSPR_MISCTYPE
, 2, FALSE
}, /* vPos and vFace */
969 { BWRITERSPR_LOOP
, 1, FALSE
},
970 { BWRITERSPR_LABEL
, 2048, FALSE
},
971 { BWRITERSPR_COLOROUT
, 4, FALSE
},
972 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
973 { ~0U, 0 } /* End tag */
976 static void asmparser_srcreg_ps_3(struct asm_parser
*This
,
977 struct instruction
*instr
, int num
,
978 const struct shader_reg
*src
) {
979 if(!check_reg_type(src
, ps_3_reg_allowed
)) {
980 asmparser_message(This
, "Line %u: Source register %s not supported in PS 3.0\n",
982 debug_print_srcreg(src
));
983 set_parse_status(&This
->status
, PARSE_ERR
);
985 check_loop_swizzle(This
, src
);
986 check_legacy_srcmod(This
, src
->srcmod
);
987 instr
->src
[num
] = *src
;
990 static void asmparser_dstreg_vs_1(struct asm_parser
*This
,
991 struct instruction
*instr
,
992 const struct shader_reg
*dst
) {
993 struct shader_reg reg
;
995 if(!check_reg_type(dst
, vs_1_reg_allowed
)) {
996 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 1\n",
998 debug_print_dstreg(dst
));
999 set_parse_status(&This
->status
, PARSE_ERR
);
1001 check_ps_dstmod(This
, instr
->dstmod
);
1002 check_shift_dstmod(This
, instr
->shift
);
1003 reg
= map_oldvs_register(dst
);
1005 instr
->has_dst
= TRUE
;
1008 static void asmparser_dstreg_vs_2(struct asm_parser
*This
,
1009 struct instruction
*instr
,
1010 const struct shader_reg
*dst
) {
1011 struct shader_reg reg
;
1013 if(!check_reg_type(dst
, vs_2_reg_allowed
)) {
1014 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 2.0\n",
1016 debug_print_dstreg(dst
));
1017 set_parse_status(&This
->status
, PARSE_ERR
);
1019 check_ps_dstmod(This
, instr
->dstmod
);
1020 check_shift_dstmod(This
, instr
->shift
);
1021 reg
= map_oldvs_register(dst
);
1023 instr
->has_dst
= TRUE
;
1026 static void asmparser_dstreg_vs_3(struct asm_parser
*This
,
1027 struct instruction
*instr
,
1028 const struct shader_reg
*dst
) {
1029 if(!check_reg_type(dst
, vs_3_reg_allowed
)) {
1030 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 3.0\n",
1032 debug_print_dstreg(dst
));
1033 set_parse_status(&This
->status
, PARSE_ERR
);
1035 check_ps_dstmod(This
, instr
->dstmod
);
1036 check_shift_dstmod(This
, instr
->shift
);
1038 instr
->has_dst
= TRUE
;
1041 static void asmparser_dstreg_ps_1_0123(struct asm_parser
*This
,
1042 struct instruction
*instr
,
1043 const struct shader_reg
*dst
) {
1044 struct shader_reg reg
;
1046 if(!check_reg_type(dst
, ps_1_0123_reg_allowed
)) {
1047 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 1\n",
1049 debug_print_dstreg(dst
));
1050 set_parse_status(&This
->status
, PARSE_ERR
);
1052 reg
= map_oldps_register(dst
, FALSE
);
1054 instr
->has_dst
= TRUE
;
1057 static void asmparser_dstreg_ps_1_4(struct asm_parser
*This
,
1058 struct instruction
*instr
,
1059 const struct shader_reg
*dst
) {
1060 struct shader_reg reg
;
1062 if(!check_reg_type(dst
, ps_1_4_reg_allowed
)) {
1063 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 1\n",
1065 debug_print_dstreg(dst
));
1066 set_parse_status(&This
->status
, PARSE_ERR
);
1068 reg
= map_oldps_register(dst
, TRUE
);
1070 instr
->has_dst
= TRUE
;
1073 static void asmparser_dstreg_ps_2(struct asm_parser
*This
,
1074 struct instruction
*instr
,
1075 const struct shader_reg
*dst
) {
1076 struct shader_reg reg
;
1078 if(!check_reg_type(dst
, ps_2_0_reg_allowed
)) {
1079 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 2.0\n",
1081 debug_print_dstreg(dst
));
1082 set_parse_status(&This
->status
, PARSE_ERR
);
1084 check_shift_dstmod(This
, instr
->shift
);
1085 reg
= map_oldps_register(dst
, TRUE
);
1087 instr
->has_dst
= TRUE
;
1090 static void asmparser_dstreg_ps_2_x(struct asm_parser
*This
,
1091 struct instruction
*instr
,
1092 const struct shader_reg
*dst
) {
1093 struct shader_reg reg
;
1095 if(!check_reg_type(dst
, ps_2_x_reg_allowed
)) {
1096 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 2.x\n",
1098 debug_print_dstreg(dst
));
1099 set_parse_status(&This
->status
, PARSE_ERR
);
1101 check_shift_dstmod(This
, instr
->shift
);
1102 reg
= map_oldps_register(dst
, TRUE
);
1104 instr
->has_dst
= TRUE
;
1107 static void asmparser_dstreg_ps_3(struct asm_parser
*This
,
1108 struct instruction
*instr
,
1109 const struct shader_reg
*dst
) {
1110 if(!check_reg_type(dst
, ps_3_reg_allowed
)) {
1111 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 3.0\n",
1113 debug_print_dstreg(dst
));
1114 set_parse_status(&This
->status
, PARSE_ERR
);
1116 check_shift_dstmod(This
, instr
->shift
);
1118 instr
->has_dst
= TRUE
;
1121 static void asmparser_predicate_supported(struct asm_parser
*This
,
1122 const struct shader_reg
*predicate
) {
1123 /* this sets the predicate of the last instruction added to the shader */
1124 if(!This
->shader
) return;
1125 if(This
->shader
->num_instrs
== 0) ERR("Predicate without an instruction\n");
1126 This
->shader
->instr
[This
->shader
->num_instrs
- 1]->has_predicate
= TRUE
;
1127 This
->shader
->instr
[This
->shader
->num_instrs
- 1]->predicate
= *predicate
;
1130 static void asmparser_predicate_unsupported(struct asm_parser
*This
,
1131 const struct shader_reg
*predicate
) {
1132 asmparser_message(This
, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This
->line_no
);
1133 set_parse_status(&This
->status
, PARSE_ERR
);
1136 static void asmparser_coissue_supported(struct asm_parser
*This
) {
1137 /* this sets the coissue flag of the last instruction added to the shader */
1138 if(!This
->shader
) return;
1139 if(This
->shader
->num_instrs
== 0){
1140 asmparser_message(This
, "Line %u: Coissue flag on the first shader instruction\n", This
->line_no
);
1141 set_parse_status(&This
->status
, PARSE_ERR
);
1143 This
->shader
->instr
[This
->shader
->num_instrs
-1]->coissue
= TRUE
;
1146 static void asmparser_coissue_unsupported(struct asm_parser
*This
) {
1147 asmparser_message(This
, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This
->line_no
);
1148 set_parse_status(&This
->status
, PARSE_ERR
);
1151 static const struct asmparser_backend parser_vs_1
= {
1156 asmparser_dstreg_vs_1
,
1157 asmparser_srcreg_vs_1
,
1159 asmparser_predicate_unsupported
,
1160 asmparser_coissue_unsupported
,
1162 asmparser_dcl_output_unsupported
,
1163 asmparser_dcl_input
,
1164 asmparser_dcl_sampler_unsupported
,
1171 static const struct asmparser_backend parser_vs_2
= {
1176 asmparser_dstreg_vs_2
,
1177 asmparser_srcreg_vs_2
,
1179 asmparser_predicate_supported
,
1180 asmparser_coissue_unsupported
,
1182 asmparser_dcl_output_unsupported
,
1183 asmparser_dcl_input
,
1184 asmparser_dcl_sampler_unsupported
,
1191 static const struct asmparser_backend parser_vs_3
= {
1196 asmparser_dstreg_vs_3
,
1197 asmparser_srcreg_vs_3
,
1199 asmparser_predicate_supported
,
1200 asmparser_coissue_unsupported
,
1202 asmparser_dcl_output
,
1203 asmparser_dcl_input
,
1204 asmparser_dcl_sampler
,
1211 static const struct asmparser_backend parser_ps_1_0123
= {
1216 asmparser_dstreg_ps_1_0123
,
1217 asmparser_srcreg_ps_1_0123
,
1219 asmparser_predicate_unsupported
,
1220 asmparser_coissue_supported
,
1222 asmparser_dcl_output_unsupported
,
1223 asmparser_dcl_input_unsupported
,
1224 asmparser_dcl_sampler_unsupported
,
1231 static const struct asmparser_backend parser_ps_1_4
= {
1236 asmparser_dstreg_ps_1_4
,
1237 asmparser_srcreg_ps_1_4
,
1239 asmparser_predicate_unsupported
,
1240 asmparser_coissue_supported
,
1242 asmparser_dcl_output_unsupported
,
1243 asmparser_dcl_input_unsupported
,
1244 asmparser_dcl_sampler_unsupported
,
1251 static const struct asmparser_backend parser_ps_2
= {
1256 asmparser_dstreg_ps_2
,
1257 asmparser_srcreg_ps_2
,
1259 asmparser_predicate_unsupported
,
1260 asmparser_coissue_unsupported
,
1262 asmparser_dcl_output_unsupported
,
1263 asmparser_dcl_input_ps_2
,
1264 asmparser_dcl_sampler
,
1271 static const struct asmparser_backend parser_ps_2_x
= {
1276 asmparser_dstreg_ps_2_x
,
1277 asmparser_srcreg_ps_2_x
,
1279 asmparser_predicate_supported
,
1280 asmparser_coissue_unsupported
,
1282 asmparser_dcl_output_unsupported
,
1283 asmparser_dcl_input_ps_2
,
1284 asmparser_dcl_sampler
,
1291 static const struct asmparser_backend parser_ps_3
= {
1296 asmparser_dstreg_ps_3
,
1297 asmparser_srcreg_ps_3
,
1299 asmparser_predicate_supported
,
1300 asmparser_coissue_unsupported
,
1302 asmparser_dcl_output_unsupported
,
1303 asmparser_dcl_input
,
1304 asmparser_dcl_sampler
,
1311 static void gen_oldvs_output(struct bwriter_shader
*shader
) {
1312 record_declaration(shader
, BWRITERDECLUSAGE_POSITION
, 0, 0, TRUE
, OPOS_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1313 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 0, 0, TRUE
, OT0_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1314 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 1, 0, TRUE
, OT1_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1315 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 2, 0, TRUE
, OT2_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1316 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 3, 0, TRUE
, OT3_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1317 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 4, 0, TRUE
, OT4_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1318 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 5, 0, TRUE
, OT5_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1319 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 6, 0, TRUE
, OT6_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1320 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 7, 0, TRUE
, OT7_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1321 record_declaration(shader
, BWRITERDECLUSAGE_FOG
, 0, 0, TRUE
, OFOG_REG
, OFOG_WRITEMASK
, TRUE
);
1322 record_declaration(shader
, BWRITERDECLUSAGE_PSIZE
, 0, 0, TRUE
, OPTS_REG
, OPTS_WRITEMASK
, TRUE
);
1323 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 0, 0, TRUE
, OD0_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1324 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 1, 0, TRUE
, OD1_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1327 static void gen_oldps_input(struct bwriter_shader
*shader
, DWORD texcoords
) {
1329 case 8: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 7, 0, FALSE
, T7_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1331 case 7: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 6, 0, FALSE
, T6_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1333 case 6: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 5, 0, FALSE
, T5_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1335 case 5: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 4, 0, FALSE
, T4_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1337 case 4: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 3, 0, FALSE
, T3_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1339 case 3: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 2, 0, FALSE
, T2_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1341 case 2: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 1, 0, FALSE
, T1_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1343 case 1: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 0, 0, FALSE
, T0_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1345 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 0, 0, FALSE
, C0_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1346 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 1, 0, FALSE
, C1_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1349 void create_vs10_parser(struct asm_parser
*ret
) {
1350 TRACE_(parsed_shader
)("vs_1_0\n");
1352 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1354 ERR("Failed to allocate memory for the shader\n");
1355 set_parse_status(&ret
->status
, PARSE_ERR
);
1359 ret
->shader
->type
= ST_VERTEX
;
1360 ret
->shader
->version
= BWRITERVS_VERSION(1, 0);
1361 ret
->funcs
= &parser_vs_1
;
1362 gen_oldvs_output(ret
->shader
);
1365 void create_vs11_parser(struct asm_parser
*ret
) {
1366 TRACE_(parsed_shader
)("vs_1_1\n");
1368 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1370 ERR("Failed to allocate memory for the shader\n");
1371 set_parse_status(&ret
->status
, PARSE_ERR
);
1375 ret
->shader
->type
= ST_VERTEX
;
1376 ret
->shader
->version
= BWRITERVS_VERSION(1, 1);
1377 ret
->funcs
= &parser_vs_1
;
1378 gen_oldvs_output(ret
->shader
);
1381 void create_vs20_parser(struct asm_parser
*ret
) {
1382 TRACE_(parsed_shader
)("vs_2_0\n");
1384 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1386 ERR("Failed to allocate memory for the shader\n");
1387 set_parse_status(&ret
->status
, PARSE_ERR
);
1391 ret
->shader
->type
= ST_VERTEX
;
1392 ret
->shader
->version
= BWRITERVS_VERSION(2, 0);
1393 ret
->funcs
= &parser_vs_2
;
1394 gen_oldvs_output(ret
->shader
);
1397 void create_vs2x_parser(struct asm_parser
*ret
) {
1398 TRACE_(parsed_shader
)("vs_2_x\n");
1400 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1402 ERR("Failed to allocate memory for the shader\n");
1403 set_parse_status(&ret
->status
, PARSE_ERR
);
1407 ret
->shader
->type
= ST_VERTEX
;
1408 ret
->shader
->version
= BWRITERVS_VERSION(2, 1);
1409 ret
->funcs
= &parser_vs_2
;
1410 gen_oldvs_output(ret
->shader
);
1413 void create_vs30_parser(struct asm_parser
*ret
) {
1414 TRACE_(parsed_shader
)("vs_3_0\n");
1416 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1418 ERR("Failed to allocate memory for the shader\n");
1419 set_parse_status(&ret
->status
, PARSE_ERR
);
1423 ret
->shader
->type
= ST_VERTEX
;
1424 ret
->shader
->version
= BWRITERVS_VERSION(3, 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
->version
= BWRITERPS_VERSION(1, 0);
1440 ret
->funcs
= &parser_ps_1_0123
;
1441 gen_oldps_input(ret
->shader
, 4);
1444 void create_ps11_parser(struct asm_parser
*ret
) {
1445 TRACE_(parsed_shader
)("ps_1_1\n");
1447 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1449 ERR("Failed to allocate memory for the shader\n");
1450 set_parse_status(&ret
->status
, PARSE_ERR
);
1454 ret
->shader
->type
= ST_PIXEL
;
1455 ret
->shader
->version
= BWRITERPS_VERSION(1, 1);
1456 ret
->funcs
= &parser_ps_1_0123
;
1457 gen_oldps_input(ret
->shader
, 4);
1460 void create_ps12_parser(struct asm_parser
*ret
) {
1461 TRACE_(parsed_shader
)("ps_1_2\n");
1463 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1465 ERR("Failed to allocate memory for the shader\n");
1466 set_parse_status(&ret
->status
, PARSE_ERR
);
1470 ret
->shader
->type
= ST_PIXEL
;
1471 ret
->shader
->version
= BWRITERPS_VERSION(1, 2);
1472 ret
->funcs
= &parser_ps_1_0123
;
1473 gen_oldps_input(ret
->shader
, 4);
1476 void create_ps13_parser(struct asm_parser
*ret
) {
1477 TRACE_(parsed_shader
)("ps_1_3\n");
1479 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1481 ERR("Failed to allocate memory for the shader\n");
1482 set_parse_status(&ret
->status
, PARSE_ERR
);
1486 ret
->shader
->type
= ST_PIXEL
;
1487 ret
->shader
->version
= BWRITERPS_VERSION(1, 3);
1488 ret
->funcs
= &parser_ps_1_0123
;
1489 gen_oldps_input(ret
->shader
, 4);
1492 void create_ps14_parser(struct asm_parser
*ret
) {
1493 TRACE_(parsed_shader
)("ps_1_4\n");
1495 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1497 ERR("Failed to allocate memory for the shader\n");
1498 set_parse_status(&ret
->status
, PARSE_ERR
);
1502 ret
->shader
->type
= ST_PIXEL
;
1503 ret
->shader
->version
= BWRITERPS_VERSION(1, 4);
1504 ret
->funcs
= &parser_ps_1_4
;
1505 gen_oldps_input(ret
->shader
, 6);
1508 void create_ps20_parser(struct asm_parser
*ret
) {
1509 TRACE_(parsed_shader
)("ps_2_0\n");
1511 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1513 ERR("Failed to allocate memory for the shader\n");
1514 set_parse_status(&ret
->status
, PARSE_ERR
);
1518 ret
->shader
->type
= ST_PIXEL
;
1519 ret
->shader
->version
= BWRITERPS_VERSION(2, 0);
1520 ret
->funcs
= &parser_ps_2
;
1521 gen_oldps_input(ret
->shader
, 8);
1524 void create_ps2x_parser(struct asm_parser
*ret
) {
1525 TRACE_(parsed_shader
)("ps_2_x\n");
1527 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1529 ERR("Failed to allocate memory for the shader\n");
1530 set_parse_status(&ret
->status
, PARSE_ERR
);
1534 ret
->shader
->type
= ST_PIXEL
;
1535 ret
->shader
->version
= BWRITERPS_VERSION(2, 1);
1536 ret
->funcs
= &parser_ps_2_x
;
1537 gen_oldps_input(ret
->shader
, 8);
1540 void create_ps30_parser(struct asm_parser
*ret
) {
1541 TRACE_(parsed_shader
)("ps_3_0\n");
1543 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1545 ERR("Failed to allocate memory for the shader\n");
1546 set_parse_status(&ret
->status
, PARSE_ERR
);
1550 ret
->shader
->type
= ST_PIXEL
;
1551 ret
->shader
->version
= BWRITERPS_VERSION(3, 0);
1552 ret
->funcs
= &parser_ps_3
;