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;
129 (This
->shader
->version
!= BWRITERPS_VERSION(3, 0) ||
130 (mod
!= BWRITERSPDM_MSAMPCENTROID
&&
131 mod
!= BWRITERSPDM_PARTIALPRECISION
))) {
132 asmparser_message(This
, "Line %u: Unsupported modifier in dcl instruction\n", This
->line_no
);
133 set_parse_status(&This
->status
, PARSE_ERR
);
137 /* Check register type and modifiers */
140 This
->funcs
->dstreg(This
, &instr
, reg
);
142 if(!record_declaration(This
->shader
, usage
, num
, mod
, FALSE
, reg
->regnum
, reg
->u
.writemask
, FALSE
)) {
143 ERR("Out of memory\n");
144 set_parse_status(&This
->status
, PARSE_ERR
);
148 static void asmparser_dcl_input_ps_2(struct asm_parser
*This
, DWORD usage
, DWORD num
,
149 DWORD mod
, const struct shader_reg
*reg
) {
150 struct instruction instr
;
152 if(!This
->shader
) return;
155 This
->funcs
->dstreg(This
, &instr
, reg
);
156 if(!record_declaration(This
->shader
, usage
, num
, mod
, FALSE
, instr
.dst
.regnum
, instr
.dst
.u
.writemask
, FALSE
)) {
157 ERR("Out of memory\n");
158 set_parse_status(&This
->status
, PARSE_ERR
);
162 static void asmparser_dcl_input_unsupported(struct asm_parser
*This
,
163 DWORD usage
, DWORD num
, DWORD mod
, const struct shader_reg
*reg
)
165 asmparser_message(This
, "Line %u: Input declaration unsupported in this shader version\n", This
->line_no
);
166 set_parse_status(&This
->status
, PARSE_ERR
);
169 static void asmparser_dcl_sampler(struct asm_parser
*This
, DWORD samptype
,
170 DWORD mod
, DWORD regnum
,
171 unsigned int line_no
) {
172 if(!This
->shader
) return;
174 (This
->shader
->version
!= BWRITERPS_VERSION(3, 0) ||
175 (mod
!= BWRITERSPDM_MSAMPCENTROID
&&
176 mod
!= BWRITERSPDM_PARTIALPRECISION
))) {
177 asmparser_message(This
, "Line %u: Unsupported modifier in dcl instruction\n", This
->line_no
);
178 set_parse_status(&This
->status
, PARSE_ERR
);
181 if(!record_sampler(This
->shader
, samptype
, mod
, regnum
)) {
182 ERR("Out of memory\n");
183 set_parse_status(&This
->status
, PARSE_ERR
);
187 static void asmparser_dcl_sampler_unsupported(struct asm_parser
*This
,
188 DWORD samptype
, DWORD mod
, DWORD regnum
, unsigned int line_no
)
190 asmparser_message(This
, "Line %u: Sampler declaration unsupported in this shader version\n", This
->line_no
);
191 set_parse_status(&This
->status
, PARSE_ERR
);
194 static void asmparser_sincos(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
195 const struct shader_reg
*dst
,
196 const struct src_regs
*srcs
) {
197 struct instruction
*instr
;
199 if(!srcs
|| srcs
->count
!= 3) {
200 asmparser_message(This
, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This
->line_no
);
201 set_parse_status(&This
->status
, PARSE_ERR
);
205 instr
= alloc_instr(3);
207 ERR("Error allocating memory for the instruction\n");
208 set_parse_status(&This
->status
, PARSE_ERR
);
212 instr
->opcode
= BWRITERSIO_SINCOS
;
214 instr
->shift
= shift
;
217 This
->funcs
->dstreg(This
, instr
, dst
);
218 This
->funcs
->srcreg(This
, instr
, 0, &srcs
->reg
[0]);
219 This
->funcs
->srcreg(This
, instr
, 1, &srcs
->reg
[1]);
220 This
->funcs
->srcreg(This
, instr
, 2, &srcs
->reg
[2]);
222 if(!add_instruction(This
->shader
, instr
)) {
223 ERR("Out of memory\n");
224 set_parse_status(&This
->status
, PARSE_ERR
);
228 static struct shader_reg
map_oldps_register(const struct shader_reg
*reg
, BOOL tex_varying
) {
229 struct shader_reg ret
;
231 case BWRITERSPR_TEXTURE
:
234 ret
.type
= BWRITERSPR_INPUT
;
235 switch(reg
->regnum
) {
236 case 0: ret
.regnum
= T0_VARYING
; break;
237 case 1: ret
.regnum
= T1_VARYING
; break;
238 case 2: ret
.regnum
= T2_VARYING
; break;
239 case 3: ret
.regnum
= T3_VARYING
; break;
240 case 4: ret
.regnum
= T4_VARYING
; break;
241 case 5: ret
.regnum
= T5_VARYING
; break;
242 case 6: ret
.regnum
= T6_VARYING
; break;
243 case 7: ret
.regnum
= T7_VARYING
; break;
245 FIXME("Unexpected TEXTURE register t%u\n", reg
->regnum
);
251 ret
.type
= BWRITERSPR_TEMP
;
252 switch(reg
->regnum
) {
253 case 0: ret
.regnum
= T0_REG
; break;
254 case 1: ret
.regnum
= T1_REG
; break;
255 case 2: ret
.regnum
= T2_REG
; break;
256 case 3: ret
.regnum
= T3_REG
; break;
258 FIXME("Unexpected TEXTURE register t%u\n", reg
->regnum
);
264 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
267 default: return *reg
;
271 static void asmparser_texcoord(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
272 const struct shader_reg
*dst
,
273 const struct src_regs
*srcs
) {
274 struct instruction
*instr
;
277 asmparser_message(This
, "Line %u: Source registers in texcoord instruction\n", This
->line_no
);
278 set_parse_status(&This
->status
, PARSE_ERR
);
282 instr
= alloc_instr(1);
284 ERR("Error allocating memory for the instruction\n");
285 set_parse_status(&This
->status
, PARSE_ERR
);
289 /* texcoord copies the texture coord data into a temporary register-like
290 * readable form. In newer shader models this equals a MOV from v0 to r0,
293 instr
->opcode
= BWRITERSIO_MOV
;
294 instr
->dstmod
= mod
| BWRITERSPDM_SATURATE
; /* texcoord clamps to [0;1] */
295 instr
->shift
= shift
;
298 This
->funcs
->dstreg(This
, instr
, dst
);
299 /* The src reg needs special care */
300 instr
->src
[0] = map_oldps_register(dst
, TRUE
);
302 if(!add_instruction(This
->shader
, instr
)) {
303 ERR("Out of memory\n");
304 set_parse_status(&This
->status
, PARSE_ERR
);
308 static void asmparser_texcrd(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
309 const struct shader_reg
*dst
,
310 const struct src_regs
*srcs
) {
311 struct instruction
*instr
;
313 if(!srcs
|| srcs
->count
!= 1) {
314 asmparser_message(This
, "Line %u: Wrong number of source registers in texcrd instruction\n", This
->line_no
);
315 set_parse_status(&This
->status
, PARSE_ERR
);
319 instr
= alloc_instr(1);
321 ERR("Error allocating memory for the instruction\n");
322 set_parse_status(&This
->status
, PARSE_ERR
);
326 /* The job of texcrd is done by mov in later shader versions */
327 instr
->opcode
= BWRITERSIO_MOV
;
329 instr
->shift
= shift
;
332 This
->funcs
->dstreg(This
, instr
, dst
);
333 This
->funcs
->srcreg(This
, instr
, 0, &srcs
->reg
[0]);
335 if(!add_instruction(This
->shader
, instr
)) {
336 ERR("Out of memory\n");
337 set_parse_status(&This
->status
, PARSE_ERR
);
341 static void asmparser_texkill(struct asm_parser
*This
,
342 const struct shader_reg
*dst
) {
343 struct instruction
*instr
= alloc_instr(0);
346 ERR("Error allocating memory for the instruction\n");
347 set_parse_status(&This
->status
, PARSE_ERR
);
351 instr
->opcode
= BWRITERSIO_TEXKILL
;
356 /* Do not run the dst register through the normal
357 * register conversion. If used with ps_1_0 to ps_1_3
358 * the texture coordinate from that register is used,
359 * not the temporary register value. In ps_1_4 and
360 * ps_2_0 t0 is always a varying and temporaries can
361 * be used with texkill.
363 instr
->dst
= map_oldps_register(dst
, TRUE
);
364 instr
->has_dst
= TRUE
;
366 if(!add_instruction(This
->shader
, instr
)) {
367 ERR("Out of memory\n");
368 set_parse_status(&This
->status
, PARSE_ERR
);
372 static void asmparser_texhelper(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
373 const struct shader_reg
*dst
,
374 const struct shader_reg
*src0
) {
375 struct instruction
*instr
= alloc_instr(2);
378 ERR("Error allocating memory for the instruction\n");
379 set_parse_status(&This
->status
, PARSE_ERR
);
383 instr
->opcode
= BWRITERSIO_TEX
;
385 instr
->shift
= shift
;
387 /* The dest register can be mapped normally to a temporary register */
388 This
->funcs
->dstreg(This
, instr
, dst
);
389 /* Use the src passed as parameter by the specific instruction handler */
390 instr
->src
[0] = *src0
;
392 /* The 2nd source register is the sampler register with the
393 * destination's regnum
395 ZeroMemory(&instr
->src
[1], sizeof(instr
->src
[1]));
396 instr
->src
[1].type
= BWRITERSPR_SAMPLER
;
397 instr
->src
[1].regnum
= dst
->regnum
;
398 instr
->src
[1].u
.swizzle
= BWRITERVS_NOSWIZZLE
;
399 instr
->src
[1].srcmod
= BWRITERSPSM_NONE
;
400 instr
->src
[1].rel_reg
= NULL
;
402 if(!add_instruction(This
->shader
, instr
)) {
403 ERR("Out of memory\n");
404 set_parse_status(&This
->status
, PARSE_ERR
);
408 static void asmparser_tex(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
409 const struct shader_reg
*dst
) {
410 struct shader_reg src
;
412 /* The first source register is the varying containing the coordinate */
413 src
= map_oldps_register(dst
, TRUE
);
414 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
417 static void asmparser_texld14(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
418 const struct shader_reg
*dst
,
419 const struct src_regs
*srcs
) {
420 struct instruction
*instr
;
422 if(!srcs
|| srcs
->count
!= 1) {
423 asmparser_message(This
, "Line %u: texld (PS 1.4) has a wrong number of source registers\n", This
->line_no
);
424 set_parse_status(&This
->status
, PARSE_ERR
);
428 instr
= alloc_instr(2);
430 ERR("Error allocating memory for the instruction\n");
431 set_parse_status(&This
->status
, PARSE_ERR
);
435 /* This code is recording a texld instruction, not tex. However,
436 * texld borrows the opcode of tex
438 instr
->opcode
= BWRITERSIO_TEX
;
440 instr
->shift
= shift
;
443 This
->funcs
->dstreg(This
, instr
, dst
);
444 This
->funcs
->srcreg(This
, instr
, 0, &srcs
->reg
[0]);
446 /* The 2nd source register is the sampler register with the
447 * destination's regnum
449 ZeroMemory(&instr
->src
[1], sizeof(instr
->src
[1]));
450 instr
->src
[1].type
= BWRITERSPR_SAMPLER
;
451 instr
->src
[1].regnum
= dst
->regnum
;
452 instr
->src
[1].u
.swizzle
= BWRITERVS_NOSWIZZLE
;
453 instr
->src
[1].srcmod
= BWRITERSPSM_NONE
;
454 instr
->src
[1].rel_reg
= NULL
;
456 if(!add_instruction(This
->shader
, instr
)) {
457 ERR("Out of memory\n");
458 set_parse_status(&This
->status
, PARSE_ERR
);
462 static void asmparser_texreg2ar(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
463 const struct shader_reg
*dst
,
464 const struct shader_reg
*src0
) {
465 struct shader_reg src
;
467 src
= map_oldps_register(src0
, FALSE
);
468 /* Supply the correct swizzle */
469 src
.u
.swizzle
= BWRITERVS_X_W
| BWRITERVS_Y_X
| BWRITERVS_Z_X
| BWRITERVS_W_X
;
470 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
473 static void asmparser_texreg2gb(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
474 const struct shader_reg
*dst
,
475 const struct shader_reg
*src0
) {
476 struct shader_reg src
;
478 src
= map_oldps_register(src0
, FALSE
);
479 /* Supply the correct swizzle */
480 src
.u
.swizzle
= BWRITERVS_X_Y
| BWRITERVS_Y_Z
| BWRITERVS_Z_Z
| BWRITERVS_W_Z
;
481 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
484 static void asmparser_texreg2rgb(struct asm_parser
*This
, DWORD mod
, DWORD shift
,
485 const struct shader_reg
*dst
,
486 const struct shader_reg
*src0
) {
487 struct shader_reg src
;
489 src
= map_oldps_register(src0
, FALSE
);
490 /* Supply the correct swizzle */
491 src
.u
.swizzle
= BWRITERVS_X_X
| BWRITERVS_Y_Y
| BWRITERVS_Z_Z
| BWRITERVS_W_Z
;
492 asmparser_texhelper(This
, mod
, shift
, dst
, &src
);
495 /* Complex pixel shader 1.3 instructions like texm3x3tex are tricky - the
496 * bytecode writer works instruction by instruction, so we can't properly
497 * convert these from/to equivalent ps_3_0 instructions. Then simply keep using
498 * the ps_1_3 opcodes and just adapt the registers in the common fashion (i.e.
499 * go through asmparser_instr).
502 static void asmparser_instr(struct asm_parser
*This
, DWORD opcode
, DWORD mod
, DWORD shift
,
503 enum bwriter_comparison_type comp
, const struct shader_reg
*dst
,
504 const struct src_regs
*srcs
, int expectednsrcs
)
506 struct instruction
*instr
;
508 BOOL firstreg
= TRUE
;
509 unsigned int src_count
= srcs
? srcs
->count
: 0;
511 if(!This
->shader
) return;
513 TRACE_(parsed_shader
)("%s%s%s%s ", debug_print_opcode(opcode
),
514 debug_print_dstmod(mod
),
515 debug_print_shift(shift
),
516 debug_print_comp(comp
));
518 TRACE_(parsed_shader
)("%s", debug_print_dstreg(dst
));
521 for(i
= 0; i
< src_count
; i
++) {
522 if(!firstreg
) TRACE_(parsed_shader
)(", ");
523 else firstreg
= FALSE
;
524 TRACE_(parsed_shader
)("%s", debug_print_srcreg(&srcs
->reg
[i
]));
526 TRACE_(parsed_shader
)("\n");
528 /* Check for instructions with different syntaxes in different shader versions */
530 case BWRITERSIO_SINCOS
:
531 /* The syntax changes between vs 2 and the other shader versions */
532 if(This
->shader
->version
== BWRITERVS_VERSION(2, 0) ||
533 This
->shader
->version
== BWRITERVS_VERSION(2, 1)) {
534 asmparser_sincos(This
, mod
, shift
, dst
, srcs
);
537 /* Use the default handling */
539 case BWRITERSIO_TEXCOORD
:
540 /* texcoord/texcrd are two instructions present only in PS <= 1.3 and PS 1.4 respectively */
541 if(This
->shader
->version
== BWRITERPS_VERSION(1, 4))
542 asmparser_texcrd(This
, mod
, shift
, dst
, srcs
);
543 else 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(This
->shader
->version
== BWRITERPS_VERSION(1, 0) ||
549 This
->shader
->version
== BWRITERPS_VERSION(1, 1) ||
550 This
->shader
->version
== BWRITERPS_VERSION(1, 2) ||
551 This
->shader
->version
== BWRITERPS_VERSION(1, 3)) {
552 asmparser_tex(This
, mod
, shift
, dst
);
555 else if(This
->shader
->version
== BWRITERPS_VERSION(1, 4)) {
556 asmparser_texld14(This
, mod
, shift
, dst
, srcs
);
559 /* else fallback to the standard behavior */
563 if(src_count
!= expectednsrcs
) {
564 asmparser_message(This
, "Line %u: Wrong number of source registers\n", This
->line_no
);
565 set_parse_status(&This
->status
, PARSE_ERR
);
569 /* Handle PS 1.x instructions, "regularizing" them */
571 case BWRITERSIO_TEXKILL
:
572 asmparser_texkill(This
, dst
);
574 case BWRITERSIO_TEXREG2AR
:
575 asmparser_texreg2ar(This
, mod
, shift
, dst
, &srcs
->reg
[0]);
577 case BWRITERSIO_TEXREG2GB
:
578 asmparser_texreg2gb(This
, mod
, shift
, dst
, &srcs
->reg
[0]);
580 case BWRITERSIO_TEXREG2RGB
:
581 asmparser_texreg2rgb(This
, mod
, shift
, dst
, &srcs
->reg
[0]);
585 instr
= alloc_instr(src_count
);
587 ERR("Error allocating memory for the instruction\n");
588 set_parse_status(&This
->status
, PARSE_ERR
);
592 instr
->opcode
= opcode
;
594 instr
->shift
= shift
;
595 instr
->comptype
= comp
;
596 if(dst
) This
->funcs
->dstreg(This
, instr
, dst
);
597 for(i
= 0; i
< src_count
; i
++) {
598 This
->funcs
->srcreg(This
, instr
, i
, &srcs
->reg
[i
]);
601 if(!add_instruction(This
->shader
, instr
)) {
602 ERR("Out of memory\n");
603 set_parse_status(&This
->status
, PARSE_ERR
);
607 static struct shader_reg
map_oldvs_register(const struct shader_reg
*reg
) {
608 struct shader_reg ret
;
610 case BWRITERSPR_RASTOUT
:
612 ret
.type
= BWRITERSPR_OUTPUT
;
613 switch(reg
->regnum
) {
614 case BWRITERSRO_POSITION
:
615 ret
.regnum
= OPOS_REG
;
618 ret
.regnum
= OFOG_REG
;
619 ret
.u
.writemask
= OFOG_WRITEMASK
;
621 case BWRITERSRO_POINT_SIZE
:
622 ret
.regnum
= OPTS_REG
;
623 ret
.u
.writemask
= OPTS_WRITEMASK
;
626 FIXME("Unhandled RASTOUT register %u\n", reg
->regnum
);
631 case BWRITERSPR_TEXCRDOUT
:
633 ret
.type
= BWRITERSPR_OUTPUT
;
634 switch(reg
->regnum
) {
635 case 0: ret
.regnum
= OT0_REG
; break;
636 case 1: ret
.regnum
= OT1_REG
; break;
637 case 2: ret
.regnum
= OT2_REG
; break;
638 case 3: ret
.regnum
= OT3_REG
; break;
639 case 4: ret
.regnum
= OT4_REG
; break;
640 case 5: ret
.regnum
= OT5_REG
; break;
641 case 6: ret
.regnum
= OT6_REG
; break;
642 case 7: ret
.regnum
= OT7_REG
; break;
644 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg
->regnum
);
649 case BWRITERSPR_ATTROUT
:
651 ret
.type
= BWRITERSPR_OUTPUT
;
652 switch(reg
->regnum
) {
653 case 0: ret
.regnum
= OD0_REG
; break;
654 case 1: ret
.regnum
= OD1_REG
; break;
656 FIXME("Unhandled ATTROUT regnum %u\n", reg
->regnum
);
661 default: return *reg
;
665 /* Checks for unsupported source modifiers in VS (all versions) or
667 static void check_legacy_srcmod(struct asm_parser
*This
, DWORD srcmod
) {
668 if(srcmod
== BWRITERSPSM_BIAS
|| srcmod
== BWRITERSPSM_BIASNEG
||
669 srcmod
== BWRITERSPSM_SIGN
|| srcmod
== BWRITERSPSM_SIGNNEG
||
670 srcmod
== BWRITERSPSM_COMP
|| srcmod
== BWRITERSPSM_X2
||
671 srcmod
== BWRITERSPSM_X2NEG
|| srcmod
== BWRITERSPSM_DZ
||
672 srcmod
== BWRITERSPSM_DW
) {
673 asmparser_message(This
, "Line %u: Source modifier %s not supported in this shader version\n",
675 debug_print_srcmod(srcmod
));
676 set_parse_status(&This
->status
, PARSE_ERR
);
680 static void check_abs_srcmod(struct asm_parser
*This
, DWORD srcmod
) {
681 if(srcmod
== BWRITERSPSM_ABS
|| srcmod
== BWRITERSPSM_ABSNEG
) {
682 asmparser_message(This
, "Line %u: Source modifier %s not supported in this shader version\n",
684 debug_print_srcmod(srcmod
));
685 set_parse_status(&This
->status
, PARSE_ERR
);
689 static void check_loop_swizzle(struct asm_parser
*This
,
690 const struct shader_reg
*src
) {
691 if((src
->type
== BWRITERSPR_LOOP
&& src
->u
.swizzle
!= BWRITERVS_NOSWIZZLE
) ||
692 (src
->rel_reg
&& src
->rel_reg
->type
== BWRITERSPR_LOOP
&&
693 src
->rel_reg
->u
.swizzle
!= BWRITERVS_NOSWIZZLE
)) {
694 asmparser_message(This
, "Line %u: Swizzle not allowed on aL register\n", This
->line_no
);
695 set_parse_status(&This
->status
, PARSE_ERR
);
699 static void check_shift_dstmod(struct asm_parser
*This
, DWORD shift
) {
701 asmparser_message(This
, "Line %u: Shift modifiers not supported in this shader version\n",
703 set_parse_status(&This
->status
, PARSE_ERR
);
707 static void check_ps_dstmod(struct asm_parser
*This
, DWORD dstmod
) {
708 if(dstmod
== BWRITERSPDM_PARTIALPRECISION
||
709 dstmod
== BWRITERSPDM_MSAMPCENTROID
) {
710 asmparser_message(This
, "Line %u: Instruction modifier %s not supported in this shader version\n",
712 debug_print_dstmod(dstmod
));
713 set_parse_status(&This
->status
, PARSE_ERR
);
717 struct allowed_reg_type
{
723 static BOOL
check_reg_type(const struct shader_reg
*reg
,
724 const struct allowed_reg_type
*allowed
) {
727 while(allowed
[i
].type
!= ~0U) {
728 if(reg
->type
== allowed
[i
].type
) {
730 if(allowed
[i
].reladdr
)
731 return TRUE
; /* The relative addressing register
732 can have a negative value, we
733 can't check the register index */
736 if(reg
->regnum
< allowed
[i
].count
) return TRUE
;
744 /* Native assembler doesn't do separate checks for src and dst registers */
745 static const struct allowed_reg_type vs_1_reg_allowed
[] = {
746 { BWRITERSPR_TEMP
, 12, FALSE
},
747 { BWRITERSPR_INPUT
, 16, FALSE
},
748 { BWRITERSPR_CONST
, ~0U, TRUE
},
749 { BWRITERSPR_ADDR
, 1, FALSE
},
750 { BWRITERSPR_RASTOUT
, 3, FALSE
}, /* oPos, oFog and oPts */
751 { BWRITERSPR_ATTROUT
, 2, FALSE
},
752 { BWRITERSPR_TEXCRDOUT
, 8, FALSE
},
753 { ~0U, 0 } /* End tag */
756 /* struct instruction *asmparser_srcreg
758 * Records a source register in the instruction and does shader version
759 * specific checks and modifications on it
762 * This: Shader parser instance
763 * instr: instruction to store the register in
764 * num: Number of source register
765 * src: Pointer to source the register structure. The caller can free
768 static void asmparser_srcreg_vs_1(struct asm_parser
*This
,
769 struct instruction
*instr
, int num
,
770 const struct shader_reg
*src
) {
771 struct shader_reg reg
;
773 if(!check_reg_type(src
, vs_1_reg_allowed
)) {
774 asmparser_message(This
, "Line %u: Source register %s not supported in VS 1\n",
776 debug_print_srcreg(src
));
777 set_parse_status(&This
->status
, PARSE_ERR
);
779 check_legacy_srcmod(This
, src
->srcmod
);
780 check_abs_srcmod(This
, src
->srcmod
);
781 reg
= map_oldvs_register(src
);
782 instr
->src
[num
] = reg
;
785 static const struct allowed_reg_type vs_2_reg_allowed
[] = {
786 { BWRITERSPR_TEMP
, 12, FALSE
},
787 { BWRITERSPR_INPUT
, 16, FALSE
},
788 { BWRITERSPR_CONST
, ~0U, TRUE
},
789 { BWRITERSPR_ADDR
, 1, FALSE
},
790 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
791 { BWRITERSPR_CONSTINT
, 16, FALSE
},
792 { BWRITERSPR_LOOP
, 1, FALSE
},
793 { BWRITERSPR_LABEL
, 2048, FALSE
},
794 { BWRITERSPR_PREDICATE
, 1, FALSE
},
795 { BWRITERSPR_RASTOUT
, 3, FALSE
}, /* oPos, oFog and oPts */
796 { BWRITERSPR_ATTROUT
, 2, FALSE
},
797 { BWRITERSPR_TEXCRDOUT
, 8, FALSE
},
798 { ~0U, 0 } /* End tag */
801 static void asmparser_srcreg_vs_2(struct asm_parser
*This
,
802 struct instruction
*instr
, int num
,
803 const struct shader_reg
*src
) {
804 struct shader_reg reg
;
806 if(!check_reg_type(src
, vs_2_reg_allowed
)) {
807 asmparser_message(This
, "Line %u: Source register %s not supported in VS 2\n",
809 debug_print_srcreg(src
));
810 set_parse_status(&This
->status
, PARSE_ERR
);
812 check_loop_swizzle(This
, src
);
813 check_legacy_srcmod(This
, src
->srcmod
);
814 check_abs_srcmod(This
, src
->srcmod
);
815 reg
= map_oldvs_register(src
);
816 instr
->src
[num
] = reg
;
819 static const struct allowed_reg_type vs_3_reg_allowed
[] = {
820 { BWRITERSPR_TEMP
, 32, FALSE
},
821 { BWRITERSPR_INPUT
, 16, TRUE
},
822 { BWRITERSPR_CONST
, ~0U, TRUE
},
823 { BWRITERSPR_ADDR
, 1, FALSE
},
824 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
825 { BWRITERSPR_CONSTINT
, 16, FALSE
},
826 { BWRITERSPR_LOOP
, 1, FALSE
},
827 { BWRITERSPR_LABEL
, 2048, FALSE
},
828 { BWRITERSPR_PREDICATE
, 1, FALSE
},
829 { BWRITERSPR_SAMPLER
, 4, FALSE
},
830 { BWRITERSPR_OUTPUT
, 12, TRUE
},
831 { ~0U, 0 } /* End tag */
834 static void asmparser_srcreg_vs_3(struct asm_parser
*This
,
835 struct instruction
*instr
, int num
,
836 const struct shader_reg
*src
) {
837 if(!check_reg_type(src
, vs_3_reg_allowed
)) {
838 asmparser_message(This
, "Line %u: Source register %s not supported in VS 3.0\n",
840 debug_print_srcreg(src
));
841 set_parse_status(&This
->status
, PARSE_ERR
);
843 check_loop_swizzle(This
, src
);
844 check_legacy_srcmod(This
, src
->srcmod
);
845 instr
->src
[num
] = *src
;
848 static const struct allowed_reg_type ps_1_0123_reg_allowed
[] = {
849 { BWRITERSPR_CONST
, 8, FALSE
},
850 { BWRITERSPR_TEMP
, 2, FALSE
},
851 { BWRITERSPR_TEXTURE
, 4, FALSE
},
852 { BWRITERSPR_INPUT
, 2, FALSE
},
853 { ~0U, 0 } /* End tag */
856 static void asmparser_srcreg_ps_1_0123(struct asm_parser
*This
,
857 struct instruction
*instr
, int num
,
858 const struct shader_reg
*src
) {
859 struct shader_reg reg
;
861 if(!check_reg_type(src
, ps_1_0123_reg_allowed
)) {
862 asmparser_message(This
, "Line %u: Source register %s not supported in <== PS 1.3\n",
864 debug_print_srcreg(src
));
865 set_parse_status(&This
->status
, PARSE_ERR
);
867 check_abs_srcmod(This
, src
->srcmod
);
868 reg
= map_oldps_register(src
, FALSE
);
869 instr
->src
[num
] = reg
;
872 static const struct allowed_reg_type ps_1_4_reg_allowed
[] = {
873 { BWRITERSPR_CONST
, 8, FALSE
},
874 { BWRITERSPR_TEMP
, 6, FALSE
},
875 { BWRITERSPR_TEXTURE
, 6, FALSE
},
876 { BWRITERSPR_INPUT
, 2, FALSE
},
877 { ~0U, 0 } /* End tag */
880 static void asmparser_srcreg_ps_1_4(struct asm_parser
*This
,
881 struct instruction
*instr
, int num
,
882 const struct shader_reg
*src
) {
883 struct shader_reg reg
;
885 if(!check_reg_type(src
, ps_1_4_reg_allowed
)) {
886 asmparser_message(This
, "Line %u: Source register %s not supported in PS 1.4\n",
888 debug_print_srcreg(src
));
889 set_parse_status(&This
->status
, PARSE_ERR
);
891 check_abs_srcmod(This
, src
->srcmod
);
892 reg
= map_oldps_register(src
, TRUE
);
893 instr
->src
[num
] = reg
;
896 static const struct allowed_reg_type ps_2_0_reg_allowed
[] = {
897 { BWRITERSPR_INPUT
, 2, FALSE
},
898 { BWRITERSPR_TEMP
, 32, FALSE
},
899 { BWRITERSPR_CONST
, 32, FALSE
},
900 { BWRITERSPR_CONSTINT
, 16, FALSE
},
901 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
902 { BWRITERSPR_SAMPLER
, 16, FALSE
},
903 { BWRITERSPR_TEXTURE
, 8, FALSE
},
904 { BWRITERSPR_COLOROUT
, 4, FALSE
},
905 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
906 { ~0U, 0 } /* End tag */
909 static void asmparser_srcreg_ps_2(struct asm_parser
*This
,
910 struct instruction
*instr
, int num
,
911 const struct shader_reg
*src
) {
912 struct shader_reg reg
;
914 if(!check_reg_type(src
, ps_2_0_reg_allowed
)) {
915 asmparser_message(This
, "Line %u: Source register %s not supported in PS 2.0\n",
917 debug_print_srcreg(src
));
918 set_parse_status(&This
->status
, PARSE_ERR
);
920 check_legacy_srcmod(This
, src
->srcmod
);
921 check_abs_srcmod(This
, src
->srcmod
);
922 reg
= map_oldps_register(src
, TRUE
);
923 instr
->src
[num
] = reg
;
926 static const struct allowed_reg_type ps_2_x_reg_allowed
[] = {
927 { BWRITERSPR_INPUT
, 2, FALSE
},
928 { BWRITERSPR_TEMP
, 32, FALSE
},
929 { BWRITERSPR_CONST
, 32, FALSE
},
930 { BWRITERSPR_CONSTINT
, 16, FALSE
},
931 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
932 { BWRITERSPR_PREDICATE
, 1, FALSE
},
933 { BWRITERSPR_SAMPLER
, 16, FALSE
},
934 { BWRITERSPR_TEXTURE
, 8, FALSE
},
935 { BWRITERSPR_LABEL
, 2048, FALSE
},
936 { BWRITERSPR_COLOROUT
, 4, FALSE
},
937 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
938 { ~0U, 0 } /* End tag */
941 static void asmparser_srcreg_ps_2_x(struct asm_parser
*This
,
942 struct instruction
*instr
, int num
,
943 const struct shader_reg
*src
) {
944 struct shader_reg reg
;
946 if(!check_reg_type(src
, ps_2_x_reg_allowed
)) {
947 asmparser_message(This
, "Line %u: Source register %s not supported in PS 2.x\n",
949 debug_print_srcreg(src
));
950 set_parse_status(&This
->status
, PARSE_ERR
);
952 check_legacy_srcmod(This
, src
->srcmod
);
953 check_abs_srcmod(This
, src
->srcmod
);
954 reg
= map_oldps_register(src
, TRUE
);
955 instr
->src
[num
] = reg
;
958 static const struct allowed_reg_type ps_3_reg_allowed
[] = {
959 { BWRITERSPR_INPUT
, 10, TRUE
},
960 { BWRITERSPR_TEMP
, 32, FALSE
},
961 { BWRITERSPR_CONST
, 224, FALSE
},
962 { BWRITERSPR_CONSTINT
, 16, FALSE
},
963 { BWRITERSPR_CONSTBOOL
, 16, FALSE
},
964 { BWRITERSPR_PREDICATE
, 1, FALSE
},
965 { BWRITERSPR_SAMPLER
, 16, FALSE
},
966 { BWRITERSPR_MISCTYPE
, 2, FALSE
}, /* vPos and vFace */
967 { BWRITERSPR_LOOP
, 1, FALSE
},
968 { BWRITERSPR_LABEL
, 2048, FALSE
},
969 { BWRITERSPR_COLOROUT
, 4, FALSE
},
970 { BWRITERSPR_DEPTHOUT
, 1, FALSE
},
971 { ~0U, 0 } /* End tag */
974 static void asmparser_srcreg_ps_3(struct asm_parser
*This
,
975 struct instruction
*instr
, int num
,
976 const struct shader_reg
*src
) {
977 if(!check_reg_type(src
, ps_3_reg_allowed
)) {
978 asmparser_message(This
, "Line %u: Source register %s not supported in PS 3.0\n",
980 debug_print_srcreg(src
));
981 set_parse_status(&This
->status
, PARSE_ERR
);
983 check_loop_swizzle(This
, src
);
984 check_legacy_srcmod(This
, src
->srcmod
);
985 instr
->src
[num
] = *src
;
988 static void asmparser_dstreg_vs_1(struct asm_parser
*This
,
989 struct instruction
*instr
,
990 const struct shader_reg
*dst
) {
991 struct shader_reg reg
;
993 if(!check_reg_type(dst
, vs_1_reg_allowed
)) {
994 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 1\n",
996 debug_print_dstreg(dst
));
997 set_parse_status(&This
->status
, PARSE_ERR
);
999 check_ps_dstmod(This
, instr
->dstmod
);
1000 check_shift_dstmod(This
, instr
->shift
);
1001 reg
= map_oldvs_register(dst
);
1003 instr
->has_dst
= TRUE
;
1006 static void asmparser_dstreg_vs_2(struct asm_parser
*This
,
1007 struct instruction
*instr
,
1008 const struct shader_reg
*dst
) {
1009 struct shader_reg reg
;
1011 if(!check_reg_type(dst
, vs_2_reg_allowed
)) {
1012 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 2.0\n",
1014 debug_print_dstreg(dst
));
1015 set_parse_status(&This
->status
, PARSE_ERR
);
1017 check_ps_dstmod(This
, instr
->dstmod
);
1018 check_shift_dstmod(This
, instr
->shift
);
1019 reg
= map_oldvs_register(dst
);
1021 instr
->has_dst
= TRUE
;
1024 static void asmparser_dstreg_vs_3(struct asm_parser
*This
,
1025 struct instruction
*instr
,
1026 const struct shader_reg
*dst
) {
1027 if(!check_reg_type(dst
, vs_3_reg_allowed
)) {
1028 asmparser_message(This
, "Line %u: Destination register %s not supported in VS 3.0\n",
1030 debug_print_dstreg(dst
));
1031 set_parse_status(&This
->status
, PARSE_ERR
);
1033 check_ps_dstmod(This
, instr
->dstmod
);
1034 check_shift_dstmod(This
, instr
->shift
);
1036 instr
->has_dst
= TRUE
;
1039 static void asmparser_dstreg_ps_1_0123(struct asm_parser
*This
,
1040 struct instruction
*instr
,
1041 const struct shader_reg
*dst
) {
1042 struct shader_reg reg
;
1044 if(!check_reg_type(dst
, ps_1_0123_reg_allowed
)) {
1045 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 1\n",
1047 debug_print_dstreg(dst
));
1048 set_parse_status(&This
->status
, PARSE_ERR
);
1050 reg
= map_oldps_register(dst
, FALSE
);
1052 instr
->has_dst
= TRUE
;
1055 static void asmparser_dstreg_ps_1_4(struct asm_parser
*This
,
1056 struct instruction
*instr
,
1057 const struct shader_reg
*dst
) {
1058 struct shader_reg reg
;
1060 if(!check_reg_type(dst
, ps_1_4_reg_allowed
)) {
1061 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 1\n",
1063 debug_print_dstreg(dst
));
1064 set_parse_status(&This
->status
, PARSE_ERR
);
1066 reg
= map_oldps_register(dst
, TRUE
);
1068 instr
->has_dst
= TRUE
;
1071 static void asmparser_dstreg_ps_2(struct asm_parser
*This
,
1072 struct instruction
*instr
,
1073 const struct shader_reg
*dst
) {
1074 struct shader_reg reg
;
1076 if(!check_reg_type(dst
, ps_2_0_reg_allowed
)) {
1077 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 2.0\n",
1079 debug_print_dstreg(dst
));
1080 set_parse_status(&This
->status
, PARSE_ERR
);
1082 check_shift_dstmod(This
, instr
->shift
);
1083 reg
= map_oldps_register(dst
, TRUE
);
1085 instr
->has_dst
= TRUE
;
1088 static void asmparser_dstreg_ps_2_x(struct asm_parser
*This
,
1089 struct instruction
*instr
,
1090 const struct shader_reg
*dst
) {
1091 struct shader_reg reg
;
1093 if(!check_reg_type(dst
, ps_2_x_reg_allowed
)) {
1094 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 2.x\n",
1096 debug_print_dstreg(dst
));
1097 set_parse_status(&This
->status
, PARSE_ERR
);
1099 check_shift_dstmod(This
, instr
->shift
);
1100 reg
= map_oldps_register(dst
, TRUE
);
1102 instr
->has_dst
= TRUE
;
1105 static void asmparser_dstreg_ps_3(struct asm_parser
*This
,
1106 struct instruction
*instr
,
1107 const struct shader_reg
*dst
) {
1108 if(!check_reg_type(dst
, ps_3_reg_allowed
)) {
1109 asmparser_message(This
, "Line %u: Destination register %s not supported in PS 3.0\n",
1111 debug_print_dstreg(dst
));
1112 set_parse_status(&This
->status
, PARSE_ERR
);
1114 check_shift_dstmod(This
, instr
->shift
);
1116 instr
->has_dst
= TRUE
;
1119 static void asmparser_predicate_supported(struct asm_parser
*This
,
1120 const struct shader_reg
*predicate
) {
1121 /* this sets the predicate of the last instruction added to the shader */
1122 if(!This
->shader
) return;
1123 if(This
->shader
->num_instrs
== 0) ERR("Predicate without an instruction\n");
1124 This
->shader
->instr
[This
->shader
->num_instrs
- 1]->has_predicate
= TRUE
;
1125 This
->shader
->instr
[This
->shader
->num_instrs
- 1]->predicate
= *predicate
;
1128 static void asmparser_predicate_unsupported(struct asm_parser
*This
,
1129 const struct shader_reg
*predicate
) {
1130 asmparser_message(This
, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This
->line_no
);
1131 set_parse_status(&This
->status
, PARSE_ERR
);
1134 static void asmparser_coissue_supported(struct asm_parser
*This
) {
1135 /* this sets the coissue flag of the last instruction added to the shader */
1136 if(!This
->shader
) return;
1137 if(This
->shader
->num_instrs
== 0){
1138 asmparser_message(This
, "Line %u: Coissue flag on the first shader instruction\n", This
->line_no
);
1139 set_parse_status(&This
->status
, PARSE_ERR
);
1141 This
->shader
->instr
[This
->shader
->num_instrs
-1]->coissue
= TRUE
;
1144 static void asmparser_coissue_unsupported(struct asm_parser
*This
) {
1145 asmparser_message(This
, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This
->line_no
);
1146 set_parse_status(&This
->status
, PARSE_ERR
);
1149 static const struct asmparser_backend parser_vs_1
= {
1154 asmparser_dstreg_vs_1
,
1155 asmparser_srcreg_vs_1
,
1157 asmparser_predicate_unsupported
,
1158 asmparser_coissue_unsupported
,
1160 asmparser_dcl_output_unsupported
,
1161 asmparser_dcl_input
,
1162 asmparser_dcl_sampler_unsupported
,
1169 static const struct asmparser_backend parser_vs_2
= {
1174 asmparser_dstreg_vs_2
,
1175 asmparser_srcreg_vs_2
,
1177 asmparser_predicate_supported
,
1178 asmparser_coissue_unsupported
,
1180 asmparser_dcl_output_unsupported
,
1181 asmparser_dcl_input
,
1182 asmparser_dcl_sampler_unsupported
,
1189 static const struct asmparser_backend parser_vs_3
= {
1194 asmparser_dstreg_vs_3
,
1195 asmparser_srcreg_vs_3
,
1197 asmparser_predicate_supported
,
1198 asmparser_coissue_unsupported
,
1200 asmparser_dcl_output
,
1201 asmparser_dcl_input
,
1202 asmparser_dcl_sampler
,
1209 static const struct asmparser_backend parser_ps_1_0123
= {
1214 asmparser_dstreg_ps_1_0123
,
1215 asmparser_srcreg_ps_1_0123
,
1217 asmparser_predicate_unsupported
,
1218 asmparser_coissue_supported
,
1220 asmparser_dcl_output_unsupported
,
1221 asmparser_dcl_input_unsupported
,
1222 asmparser_dcl_sampler_unsupported
,
1229 static const struct asmparser_backend parser_ps_1_4
= {
1234 asmparser_dstreg_ps_1_4
,
1235 asmparser_srcreg_ps_1_4
,
1237 asmparser_predicate_unsupported
,
1238 asmparser_coissue_supported
,
1240 asmparser_dcl_output_unsupported
,
1241 asmparser_dcl_input_unsupported
,
1242 asmparser_dcl_sampler_unsupported
,
1249 static const struct asmparser_backend parser_ps_2
= {
1254 asmparser_dstreg_ps_2
,
1255 asmparser_srcreg_ps_2
,
1257 asmparser_predicate_unsupported
,
1258 asmparser_coissue_unsupported
,
1260 asmparser_dcl_output_unsupported
,
1261 asmparser_dcl_input_ps_2
,
1262 asmparser_dcl_sampler
,
1269 static const struct asmparser_backend parser_ps_2_x
= {
1274 asmparser_dstreg_ps_2_x
,
1275 asmparser_srcreg_ps_2_x
,
1277 asmparser_predicate_supported
,
1278 asmparser_coissue_unsupported
,
1280 asmparser_dcl_output_unsupported
,
1281 asmparser_dcl_input_ps_2
,
1282 asmparser_dcl_sampler
,
1289 static const struct asmparser_backend parser_ps_3
= {
1294 asmparser_dstreg_ps_3
,
1295 asmparser_srcreg_ps_3
,
1297 asmparser_predicate_supported
,
1298 asmparser_coissue_unsupported
,
1300 asmparser_dcl_output_unsupported
,
1301 asmparser_dcl_input
,
1302 asmparser_dcl_sampler
,
1309 static void gen_oldvs_output(struct bwriter_shader
*shader
) {
1310 record_declaration(shader
, BWRITERDECLUSAGE_POSITION
, 0, 0, TRUE
, OPOS_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1311 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 0, 0, TRUE
, OT0_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1312 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 1, 0, TRUE
, OT1_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1313 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 2, 0, TRUE
, OT2_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1314 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 3, 0, TRUE
, OT3_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1315 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 4, 0, TRUE
, OT4_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1316 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 5, 0, TRUE
, OT5_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1317 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 6, 0, TRUE
, OT6_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1318 record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 7, 0, TRUE
, OT7_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1319 record_declaration(shader
, BWRITERDECLUSAGE_FOG
, 0, 0, TRUE
, OFOG_REG
, OFOG_WRITEMASK
, TRUE
);
1320 record_declaration(shader
, BWRITERDECLUSAGE_PSIZE
, 0, 0, TRUE
, OPTS_REG
, OPTS_WRITEMASK
, TRUE
);
1321 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 0, 0, TRUE
, OD0_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1322 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 1, 0, TRUE
, OD1_REG
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1325 static void gen_oldps_input(struct bwriter_shader
*shader
, DWORD texcoords
) {
1327 case 8: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 7, 0, FALSE
, T7_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1329 case 7: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 6, 0, FALSE
, T6_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1331 case 6: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 5, 0, FALSE
, T5_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1333 case 5: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 4, 0, FALSE
, T4_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1335 case 4: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 3, 0, FALSE
, T3_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1337 case 3: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 2, 0, FALSE
, T2_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1339 case 2: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 1, 0, FALSE
, T1_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1341 case 1: record_declaration(shader
, BWRITERDECLUSAGE_TEXCOORD
, 0, 0, FALSE
, T0_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1343 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 0, 0, FALSE
, C0_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1344 record_declaration(shader
, BWRITERDECLUSAGE_COLOR
, 1, 0, FALSE
, C1_VARYING
, BWRITERSP_WRITEMASK_ALL
, TRUE
);
1347 void create_vs10_parser(struct asm_parser
*ret
) {
1348 TRACE_(parsed_shader
)("vs_1_0\n");
1350 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1352 ERR("Failed to allocate memory for the shader\n");
1353 set_parse_status(&ret
->status
, PARSE_ERR
);
1357 ret
->shader
->type
= ST_VERTEX
;
1358 ret
->shader
->version
= BWRITERVS_VERSION(1, 0);
1359 ret
->funcs
= &parser_vs_1
;
1360 gen_oldvs_output(ret
->shader
);
1363 void create_vs11_parser(struct asm_parser
*ret
) {
1364 TRACE_(parsed_shader
)("vs_1_1\n");
1366 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1368 ERR("Failed to allocate memory for the shader\n");
1369 set_parse_status(&ret
->status
, PARSE_ERR
);
1373 ret
->shader
->type
= ST_VERTEX
;
1374 ret
->shader
->version
= BWRITERVS_VERSION(1, 1);
1375 ret
->funcs
= &parser_vs_1
;
1376 gen_oldvs_output(ret
->shader
);
1379 void create_vs20_parser(struct asm_parser
*ret
) {
1380 TRACE_(parsed_shader
)("vs_2_0\n");
1382 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1384 ERR("Failed to allocate memory for the shader\n");
1385 set_parse_status(&ret
->status
, PARSE_ERR
);
1389 ret
->shader
->type
= ST_VERTEX
;
1390 ret
->shader
->version
= BWRITERVS_VERSION(2, 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
->version
= BWRITERVS_VERSION(2, 1);
1407 ret
->funcs
= &parser_vs_2
;
1408 gen_oldvs_output(ret
->shader
);
1411 void create_vs30_parser(struct asm_parser
*ret
) {
1412 TRACE_(parsed_shader
)("vs_3_0\n");
1414 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1416 ERR("Failed to allocate memory for the shader\n");
1417 set_parse_status(&ret
->status
, PARSE_ERR
);
1421 ret
->shader
->type
= ST_VERTEX
;
1422 ret
->shader
->version
= BWRITERVS_VERSION(3, 0);
1423 ret
->funcs
= &parser_vs_3
;
1426 void create_ps10_parser(struct asm_parser
*ret
) {
1427 TRACE_(parsed_shader
)("ps_1_0\n");
1429 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1431 ERR("Failed to allocate memory for the shader\n");
1432 set_parse_status(&ret
->status
, PARSE_ERR
);
1436 ret
->shader
->type
= ST_PIXEL
;
1437 ret
->shader
->version
= BWRITERPS_VERSION(1, 0);
1438 ret
->funcs
= &parser_ps_1_0123
;
1439 gen_oldps_input(ret
->shader
, 4);
1442 void create_ps11_parser(struct asm_parser
*ret
) {
1443 TRACE_(parsed_shader
)("ps_1_1\n");
1445 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1447 ERR("Failed to allocate memory for the shader\n");
1448 set_parse_status(&ret
->status
, PARSE_ERR
);
1452 ret
->shader
->type
= ST_PIXEL
;
1453 ret
->shader
->version
= BWRITERPS_VERSION(1, 1);
1454 ret
->funcs
= &parser_ps_1_0123
;
1455 gen_oldps_input(ret
->shader
, 4);
1458 void create_ps12_parser(struct asm_parser
*ret
) {
1459 TRACE_(parsed_shader
)("ps_1_2\n");
1461 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1463 ERR("Failed to allocate memory for the shader\n");
1464 set_parse_status(&ret
->status
, PARSE_ERR
);
1468 ret
->shader
->type
= ST_PIXEL
;
1469 ret
->shader
->version
= BWRITERPS_VERSION(1, 2);
1470 ret
->funcs
= &parser_ps_1_0123
;
1471 gen_oldps_input(ret
->shader
, 4);
1474 void create_ps13_parser(struct asm_parser
*ret
) {
1475 TRACE_(parsed_shader
)("ps_1_3\n");
1477 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1479 ERR("Failed to allocate memory for the shader\n");
1480 set_parse_status(&ret
->status
, PARSE_ERR
);
1484 ret
->shader
->type
= ST_PIXEL
;
1485 ret
->shader
->version
= BWRITERPS_VERSION(1, 3);
1486 ret
->funcs
= &parser_ps_1_0123
;
1487 gen_oldps_input(ret
->shader
, 4);
1490 void create_ps14_parser(struct asm_parser
*ret
) {
1491 TRACE_(parsed_shader
)("ps_1_4\n");
1493 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1495 ERR("Failed to allocate memory for the shader\n");
1496 set_parse_status(&ret
->status
, PARSE_ERR
);
1500 ret
->shader
->type
= ST_PIXEL
;
1501 ret
->shader
->version
= BWRITERPS_VERSION(1, 4);
1502 ret
->funcs
= &parser_ps_1_4
;
1503 gen_oldps_input(ret
->shader
, 6);
1506 void create_ps20_parser(struct asm_parser
*ret
) {
1507 TRACE_(parsed_shader
)("ps_2_0\n");
1509 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1511 ERR("Failed to allocate memory for the shader\n");
1512 set_parse_status(&ret
->status
, PARSE_ERR
);
1516 ret
->shader
->type
= ST_PIXEL
;
1517 ret
->shader
->version
= BWRITERPS_VERSION(2, 0);
1518 ret
->funcs
= &parser_ps_2
;
1519 gen_oldps_input(ret
->shader
, 8);
1522 void create_ps2x_parser(struct asm_parser
*ret
) {
1523 TRACE_(parsed_shader
)("ps_2_x\n");
1525 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1527 ERR("Failed to allocate memory for the shader\n");
1528 set_parse_status(&ret
->status
, PARSE_ERR
);
1532 ret
->shader
->type
= ST_PIXEL
;
1533 ret
->shader
->version
= BWRITERPS_VERSION(2, 1);
1534 ret
->funcs
= &parser_ps_2_x
;
1535 gen_oldps_input(ret
->shader
, 8);
1538 void create_ps30_parser(struct asm_parser
*ret
) {
1539 TRACE_(parsed_shader
)("ps_3_0\n");
1541 ret
->shader
= d3dcompiler_alloc(sizeof(*ret
->shader
));
1543 ERR("Failed to allocate memory for the shader\n");
1544 set_parse_status(&ret
->status
, PARSE_ERR
);
1548 ret
->shader
->type
= ST_PIXEL
;
1549 ret
->shader
->version
= BWRITERPS_VERSION(3, 0);
1550 ret
->funcs
= &parser_ps_3
;