ddraw: Use unsafe_impl_from_IDirect3DViewport for application provided interfaces.
[wine/multimedia.git] / dlls / d3dcompiler_43 / asmparser.c
blob4d712374cb699e351ef50f1dc6bbc53a1f0b69b5
1 /*
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 "config.h"
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
40 #define OT0_REG 0
41 #define OT1_REG 1
42 #define OT2_REG 2
43 #define OT3_REG 3
44 #define OT4_REG 4
45 #define OT5_REG 5
46 #define OT6_REG 6
47 #define OT7_REG 7
48 #define OPOS_REG 8
49 #define OFOG_REG 9
50 #define OFOG_WRITEMASK BWRITERSP_WRITEMASK_0
51 #define OPTS_REG 9
52 #define OPTS_WRITEMASK BWRITERSP_WRITEMASK_1
53 #define OD0_REG 10
54 #define OD1_REG 11
56 /* Input color registers 0-1 are identically mapped */
57 #define C0_VARYING 0
58 #define C1_VARYING 1
59 #define T0_VARYING 2
60 #define T1_VARYING 3
61 #define T2_VARYING 4
62 #define T3_VARYING 5
63 #define T4_VARYING 6
64 #define T5_VARYING 7
65 #define T6_VARYING 8
66 #define T7_VARYING 9
68 /****************************************************************
69 * Common(non-version specific) shader parser control code *
70 ****************************************************************/
72 static void asmparser_end(struct asm_parser *This) {
73 TRACE("Finalizing shader\n");
76 static void asmparser_constF(struct asm_parser *This, DWORD reg, float x, float y, float z, float w) {
77 if(!This->shader) return;
78 TRACE("Adding float constant %u at pos %u\n", reg, This->shader->num_cf);
79 TRACE_(parsed_shader)("def c%u, %f, %f, %f, %f\n", reg, x, y, z, w);
80 if(!add_constF(This->shader, reg, x, y, z, w)) {
81 ERR("Out of memory\n");
82 set_parse_status(This, PARSE_ERR);
86 static void asmparser_constB(struct asm_parser *This, DWORD reg, BOOL x) {
87 if(!This->shader) return;
88 TRACE("Adding boolean constant %u at pos %u\n", reg, This->shader->num_cb);
89 TRACE_(parsed_shader)("def b%u, %s\n", reg, x ? "true" : "false");
90 if(!add_constB(This->shader, reg, x)) {
91 ERR("Out of memory\n");
92 set_parse_status(This, PARSE_ERR);
96 static void asmparser_constI(struct asm_parser *This, DWORD reg, INT x, INT y, INT z, INT w) {
97 if(!This->shader) return;
98 TRACE("Adding integer constant %u at pos %u\n", reg, This->shader->num_ci);
99 TRACE_(parsed_shader)("def i%u, %d, %d, %d, %d\n", reg, x, y, z, w);
100 if(!add_constI(This->shader, reg, x, y, z, w)) {
101 ERR("Out of memory\n");
102 set_parse_status(This, PARSE_ERR);
106 static void asmparser_dcl_output(struct asm_parser *This, DWORD usage, DWORD num,
107 const struct shader_reg *reg) {
108 if(!This->shader) return;
109 if(This->shader->type == ST_PIXEL) {
110 asmparser_message(This, "Line %u: Output register declared in a pixel shader\n", This->line_no);
111 set_parse_status(This, PARSE_ERR);
113 if(!record_declaration(This->shader, usage, num, 0, TRUE, reg->regnum, reg->u.writemask, FALSE)) {
114 ERR("Out of memory\n");
115 set_parse_status(This, 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, 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;
130 if(mod != 0 &&
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, PARSE_ERR);
136 return;
139 /* Check register type and modifiers */
140 instr.dstmod = mod;
141 instr.shift = 0;
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, 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;
155 instr.dstmod = mod;
156 instr.shift = 0;
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, 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, 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;
175 if(mod != 0 &&
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, PARSE_ERR);
181 return;
183 if(!record_sampler(This->shader, samptype, mod, regnum)) {
184 ERR("Out of memory\n");
185 set_parse_status(This, 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, 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, PARSE_ERR);
204 return;
207 instr = alloc_instr(3);
208 if(!instr) {
209 ERR("Error allocating memory for the instruction\n");
210 set_parse_status(This, PARSE_ERR);
211 return;
214 instr->opcode = BWRITERSIO_SINCOS;
215 instr->dstmod = mod;
216 instr->shift = shift;
217 instr->comptype = 0;
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, PARSE_ERR);
230 static struct shader_reg map_oldps_register(const struct shader_reg *reg, BOOL tex_varying) {
231 struct shader_reg ret;
232 switch(reg->type) {
233 case BWRITERSPR_TEXTURE:
234 if(tex_varying) {
235 ret = *reg;
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;
246 default:
247 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
248 return *reg;
250 return ret;
251 } else {
252 ret = *reg;
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;
259 default:
260 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
261 return *reg;
263 return ret;
266 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
267 to 3.0 ones */
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;
278 if(srcs) {
279 asmparser_message(This, "Line %u: Source registers in texcoord instruction\n", This->line_no);
280 set_parse_status(This, PARSE_ERR);
281 return;
284 instr = alloc_instr(1);
285 if(!instr) {
286 ERR("Error allocating memory for the instruction\n");
287 set_parse_status(This, PARSE_ERR);
288 return;
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,
293 * record it as this.
295 instr->opcode = BWRITERSIO_MOV;
296 instr->dstmod = mod | BWRITERSPDM_SATURATE; /* texcoord clamps to [0;1] */
297 instr->shift = shift;
298 instr->comptype = 0;
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, 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, PARSE_ERR);
318 return;
321 instr = alloc_instr(1);
322 if(!instr) {
323 ERR("Error allocating memory for the instruction\n");
324 set_parse_status(This, PARSE_ERR);
325 return;
328 /* The job of texcrd is done by mov in later shader versions */
329 instr->opcode = BWRITERSIO_MOV;
330 instr->dstmod = mod;
331 instr->shift = shift;
332 instr->comptype = 0;
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, PARSE_ERR);
343 static void asmparser_texkill(struct asm_parser *This,
344 const struct shader_reg *dst) {
345 struct instruction *instr = alloc_instr(0);
347 if(!instr) {
348 ERR("Error allocating memory for the instruction\n");
349 set_parse_status(This, PARSE_ERR);
350 return;
353 instr->opcode = BWRITERSIO_TEXKILL;
354 instr->dstmod = 0;
355 instr->shift = 0;
356 instr->comptype = 0;
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, 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);
379 if(!instr) {
380 ERR("Error allocating memory for the instruction\n");
381 set_parse_status(This, PARSE_ERR);
382 return;
385 instr->opcode = BWRITERSIO_TEX;
386 instr->dstmod = mod;
387 instr->shift = shift;
388 instr->comptype = 0;
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, 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, PARSE_ERR);
427 return;
430 instr = alloc_instr(2);
431 if(!instr) {
432 ERR("Error allocating memory for the instruction\n");
433 set_parse_status(This, PARSE_ERR);
434 return;
437 /* This code is recording a texld instruction, not tex. However,
438 * texld borrows the opcode of tex
440 instr->opcode = BWRITERSIO_TEX;
441 instr->dstmod = mod;
442 instr->shift = shift;
443 instr->comptype = 0;
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, 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,
505 DWORD mod, DWORD shift,
506 BWRITER_COMPARISON_TYPE comp,
507 const struct shader_reg *dst,
508 const struct src_regs *srcs, int expectednsrcs) {
509 struct instruction *instr;
510 unsigned int i;
511 BOOL firstreg = TRUE;
512 unsigned int src_count = srcs ? srcs->count : 0;
514 if(!This->shader) return;
516 TRACE_(parsed_shader)("%s%s%s%s ", debug_print_opcode(opcode),
517 debug_print_dstmod(mod),
518 debug_print_shift(shift),
519 debug_print_comp(comp));
520 if(dst) {
521 TRACE_(parsed_shader)("%s", debug_print_dstreg(dst));
522 firstreg = FALSE;
524 for(i = 0; i < src_count; i++) {
525 if(!firstreg) TRACE_(parsed_shader)(", ");
526 else firstreg = FALSE;
527 TRACE_(parsed_shader)("%s", debug_print_srcreg(&srcs->reg[i]));
529 TRACE_(parsed_shader)("\n");
531 /* Check for instructions with different syntaxes in different shader versions */
532 switch(opcode) {
533 case BWRITERSIO_SINCOS:
534 /* The syntax changes between vs 2 and the other shader versions */
535 if(This->shader->version == BWRITERVS_VERSION(2, 0) ||
536 This->shader->version == BWRITERVS_VERSION(2, 1)) {
537 asmparser_sincos(This, mod, shift, dst, srcs);
538 return;
540 /* Use the default handling */
541 break;
542 case BWRITERSIO_TEXCOORD:
543 /* texcoord/texcrd are two instructions present only in PS <= 1.3 and PS 1.4 respectively */
544 if(This->shader->version == BWRITERPS_VERSION(1, 4))
545 asmparser_texcrd(This, mod, shift, dst, srcs);
546 else asmparser_texcoord(This, mod, shift, dst, srcs);
547 return;
548 case BWRITERSIO_TEX:
549 /* this encodes both the tex PS 1.x instruction and the
550 texld 1.4/2.0+ instruction */
551 if(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);
555 return;
557 else if(This->shader->version == BWRITERPS_VERSION(1, 4)) {
558 asmparser_texld14(This, mod, shift, dst, srcs);
559 return;
561 /* else fallback to the standard behavior */
562 break;
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, PARSE_ERR);
568 return;
571 /* Handle PS 1.x instructions, "regularizing" them */
572 switch(opcode) {
573 case BWRITERSIO_TEXKILL:
574 asmparser_texkill(This, dst);
575 return;
576 case BWRITERSIO_TEXREG2AR:
577 asmparser_texreg2ar(This, mod, shift, dst, &srcs->reg[0]);
578 return;
579 case BWRITERSIO_TEXREG2GB:
580 asmparser_texreg2gb(This, mod, shift, dst, &srcs->reg[0]);
581 return;
582 case BWRITERSIO_TEXREG2RGB:
583 asmparser_texreg2rgb(This, mod, shift, dst, &srcs->reg[0]);
584 return;
587 instr = alloc_instr(src_count);
588 if(!instr) {
589 ERR("Error allocating memory for the instruction\n");
590 set_parse_status(This, PARSE_ERR);
591 return;
594 instr->opcode = opcode;
595 instr->dstmod = mod;
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, PARSE_ERR);
609 static struct shader_reg map_oldvs_register(const struct shader_reg *reg) {
610 struct shader_reg ret;
611 switch(reg->type) {
612 case BWRITERSPR_RASTOUT:
613 ret = *reg;
614 ret.type = BWRITERSPR_OUTPUT;
615 switch(reg->regnum) {
616 case BWRITERSRO_POSITION:
617 ret.regnum = OPOS_REG;
618 break;
619 case BWRITERSRO_FOG:
620 ret.regnum = OFOG_REG;
621 ret.u.writemask = OFOG_WRITEMASK;
622 break;
623 case BWRITERSRO_POINT_SIZE:
624 ret.regnum = OPTS_REG;
625 ret.u.writemask = OPTS_WRITEMASK;
626 break;
627 default:
628 FIXME("Unhandled RASTOUT register %u\n", reg->regnum);
629 return *reg;
631 return ret;
633 case BWRITERSPR_TEXCRDOUT:
634 ret = *reg;
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;
645 default:
646 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg->regnum);
647 return *reg;
649 return ret;
651 case BWRITERSPR_ATTROUT:
652 ret = *reg;
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;
657 default:
658 FIXME("Unhandled ATTROUT regnum %u\n", reg->regnum);
659 return *reg;
661 return ret;
663 default: return *reg;
667 /* Checks for unsupported source modifiers in VS (all versions) or
668 PS 2.0 and newer */
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",
676 This->line_no,
677 debug_print_srcmod(srcmod));
678 set_parse_status(This, 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",
685 This->line_no,
686 debug_print_srcmod(srcmod));
687 set_parse_status(This, 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, PARSE_ERR);
701 static void check_shift_dstmod(struct asm_parser *This, DWORD shift) {
702 if(shift != 0) {
703 asmparser_message(This, "Line %u: Shift modifiers not supported in this shader version\n",
704 This->line_no);
705 set_parse_status(This, 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",
713 This->line_no,
714 debug_print_dstmod(dstmod));
715 set_parse_status(This, PARSE_ERR);
719 struct allowed_reg_type {
720 DWORD type;
721 DWORD count;
722 BOOL reladdr;
725 static BOOL check_reg_type(const struct shader_reg *reg,
726 const struct allowed_reg_type *allowed) {
727 unsigned int i = 0;
729 while(allowed[i].type != ~0U) {
730 if(reg->type == allowed[i].type) {
731 if(reg->rel_reg) {
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 */
736 return FALSE;
738 if(reg->regnum < allowed[i].count) return TRUE;
739 return FALSE;
741 i++;
743 return FALSE;
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
763 * Parameters:
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
768 * it afterwards
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",
777 This->line_no,
778 debug_print_srcreg(src));
779 set_parse_status(This, PARSE_ERR);
781 check_legacy_srcmod(This, src->srcmod);
782 check_abs_srcmod(This, src->srcmod);
783 reg = map_oldvs_register(src);
784 memcpy(&instr->src[num], &reg, sizeof(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",
810 This->line_no,
811 debug_print_srcreg(src));
812 set_parse_status(This, 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 memcpy(&instr->src[num], &reg, sizeof(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",
841 This->line_no,
842 debug_print_srcreg(src));
843 set_parse_status(This, PARSE_ERR);
845 check_loop_swizzle(This, src);
846 check_legacy_srcmod(This, src->srcmod);
847 memcpy(&instr->src[num], src, sizeof(*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",
865 This->line_no,
866 debug_print_srcreg(src));
867 set_parse_status(This, PARSE_ERR);
869 check_abs_srcmod(This, src->srcmod);
870 reg = map_oldps_register(src, FALSE);
871 memcpy(&instr->src[num], &reg, sizeof(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",
889 This->line_no,
890 debug_print_srcreg(src));
891 set_parse_status(This, PARSE_ERR);
893 check_abs_srcmod(This, src->srcmod);
894 reg = map_oldps_register(src, TRUE);
895 memcpy(&instr->src[num], &reg, sizeof(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",
918 This->line_no,
919 debug_print_srcreg(src));
920 set_parse_status(This, PARSE_ERR);
922 check_legacy_srcmod(This, src->srcmod);
923 check_abs_srcmod(This, src->srcmod);
924 reg = map_oldps_register(src, TRUE);
925 memcpy(&instr->src[num], &reg, sizeof(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",
950 This->line_no,
951 debug_print_srcreg(src));
952 set_parse_status(This, PARSE_ERR);
954 check_legacy_srcmod(This, src->srcmod);
955 check_abs_srcmod(This, src->srcmod);
956 reg = map_oldps_register(src, TRUE);
957 memcpy(&instr->src[num], &reg, sizeof(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",
981 This->line_no,
982 debug_print_srcreg(src));
983 set_parse_status(This, PARSE_ERR);
985 check_loop_swizzle(This, src);
986 check_legacy_srcmod(This, src->srcmod);
987 memcpy(&instr->src[num], src, sizeof(*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",
997 This->line_no,
998 debug_print_dstreg(dst));
999 set_parse_status(This, PARSE_ERR);
1001 check_ps_dstmod(This, instr->dstmod);
1002 check_shift_dstmod(This, instr->shift);
1003 reg = map_oldvs_register(dst);
1004 memcpy(&instr->dst, &reg, sizeof(reg));
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",
1015 This->line_no,
1016 debug_print_dstreg(dst));
1017 set_parse_status(This, PARSE_ERR);
1019 check_ps_dstmod(This, instr->dstmod);
1020 check_shift_dstmod(This, instr->shift);
1021 reg = map_oldvs_register(dst);
1022 memcpy(&instr->dst, &reg, sizeof(reg));
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",
1031 This->line_no,
1032 debug_print_dstreg(dst));
1033 set_parse_status(This, PARSE_ERR);
1035 check_ps_dstmod(This, instr->dstmod);
1036 check_shift_dstmod(This, instr->shift);
1037 memcpy(&instr->dst, dst, sizeof(*dst));
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",
1048 This->line_no,
1049 debug_print_dstreg(dst));
1050 set_parse_status(This, PARSE_ERR);
1052 reg = map_oldps_register(dst, FALSE);
1053 memcpy(&instr->dst, &reg, sizeof(reg));
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",
1064 This->line_no,
1065 debug_print_dstreg(dst));
1066 set_parse_status(This, PARSE_ERR);
1068 reg = map_oldps_register(dst, TRUE);
1069 memcpy(&instr->dst, &reg, sizeof(reg));
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",
1080 This->line_no,
1081 debug_print_dstreg(dst));
1082 set_parse_status(This, PARSE_ERR);
1084 check_shift_dstmod(This, instr->shift);
1085 reg = map_oldps_register(dst, TRUE);
1086 memcpy(&instr->dst, &reg, sizeof(reg));
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",
1097 This->line_no,
1098 debug_print_dstreg(dst));
1099 set_parse_status(This, PARSE_ERR);
1101 check_shift_dstmod(This, instr->shift);
1102 reg = map_oldps_register(dst, TRUE);
1103 memcpy(&instr->dst, &reg, sizeof(reg));
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",
1112 This->line_no,
1113 debug_print_dstreg(dst));
1114 set_parse_status(This, PARSE_ERR);
1116 check_shift_dstmod(This, instr->shift);
1117 memcpy(&instr->dst, dst, sizeof(*dst));
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 memcpy(&This->shader->instr[This->shader->num_instrs - 1]->predicate, predicate, sizeof(*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, 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, 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, PARSE_ERR);
1151 static const struct asmparser_backend parser_vs_1 = {
1152 asmparser_constF,
1153 asmparser_constI,
1154 asmparser_constB,
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,
1166 asmparser_end,
1168 asmparser_instr,
1171 static const struct asmparser_backend parser_vs_2 = {
1172 asmparser_constF,
1173 asmparser_constI,
1174 asmparser_constB,
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,
1186 asmparser_end,
1188 asmparser_instr,
1191 static const struct asmparser_backend parser_vs_3 = {
1192 asmparser_constF,
1193 asmparser_constI,
1194 asmparser_constB,
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,
1206 asmparser_end,
1208 asmparser_instr,
1211 static const struct asmparser_backend parser_ps_1_0123 = {
1212 asmparser_constF,
1213 asmparser_constI,
1214 asmparser_constB,
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,
1226 asmparser_end,
1228 asmparser_instr,
1231 static const struct asmparser_backend parser_ps_1_4 = {
1232 asmparser_constF,
1233 asmparser_constI,
1234 asmparser_constB,
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,
1246 asmparser_end,
1248 asmparser_instr,
1251 static const struct asmparser_backend parser_ps_2 = {
1252 asmparser_constF,
1253 asmparser_constI,
1254 asmparser_constB,
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,
1266 asmparser_end,
1268 asmparser_instr,
1271 static const struct asmparser_backend parser_ps_2_x = {
1272 asmparser_constF,
1273 asmparser_constI,
1274 asmparser_constB,
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,
1286 asmparser_end,
1288 asmparser_instr,
1291 static const struct asmparser_backend parser_ps_3 = {
1292 asmparser_constF,
1293 asmparser_constI,
1294 asmparser_constB,
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,
1306 asmparser_end,
1308 asmparser_instr,
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) {
1328 switch(texcoords) {
1329 case 8: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, FALSE, T7_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1330 /* fall through */
1331 case 7: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, FALSE, T6_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1332 /* fall through */
1333 case 6: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, FALSE, T5_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1334 /* fall through */
1335 case 5: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, FALSE, T4_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1336 /* fall through */
1337 case 4: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, FALSE, T3_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1338 /* fall through */
1339 case 3: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, FALSE, T2_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1340 /* fall through */
1341 case 2: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, FALSE, T1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
1342 /* fall through */
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 = asm_alloc(sizeof(*ret->shader));
1353 if(!ret->shader) {
1354 ERR("Failed to allocate memory for the shader\n");
1355 set_parse_status(ret, PARSE_ERR);
1356 return;
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 = asm_alloc(sizeof(*ret->shader));
1369 if(!ret->shader) {
1370 ERR("Failed to allocate memory for the shader\n");
1371 set_parse_status(ret, PARSE_ERR);
1372 return;
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 = asm_alloc(sizeof(*ret->shader));
1385 if(!ret->shader) {
1386 ERR("Failed to allocate memory for the shader\n");
1387 set_parse_status(ret, PARSE_ERR);
1388 return;
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 = asm_alloc(sizeof(*ret->shader));
1401 if(!ret->shader) {
1402 ERR("Failed to allocate memory for the shader\n");
1403 set_parse_status(ret, PARSE_ERR);
1404 return;
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 = asm_alloc(sizeof(*ret->shader));
1417 if(!ret->shader) {
1418 ERR("Failed to allocate memory for the shader\n");
1419 set_parse_status(ret, PARSE_ERR);
1420 return;
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 = asm_alloc(sizeof(*ret->shader));
1432 if(!ret->shader) {
1433 ERR("Failed to allocate memory for the shader\n");
1434 set_parse_status(ret, PARSE_ERR);
1435 return;
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 = asm_alloc(sizeof(*ret->shader));
1448 if(!ret->shader) {
1449 ERR("Failed to allocate memory for the shader\n");
1450 set_parse_status(ret, PARSE_ERR);
1451 return;
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 = asm_alloc(sizeof(*ret->shader));
1464 if(!ret->shader) {
1465 ERR("Failed to allocate memory for the shader\n");
1466 set_parse_status(ret, PARSE_ERR);
1467 return;
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 = asm_alloc(sizeof(*ret->shader));
1480 if(!ret->shader) {
1481 ERR("Failed to allocate memory for the shader\n");
1482 set_parse_status(ret, PARSE_ERR);
1483 return;
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 = asm_alloc(sizeof(*ret->shader));
1496 if(!ret->shader) {
1497 ERR("Failed to allocate memory for the shader\n");
1498 set_parse_status(ret, PARSE_ERR);
1499 return;
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 = asm_alloc(sizeof(*ret->shader));
1512 if(!ret->shader) {
1513 ERR("Failed to allocate memory for the shader\n");
1514 set_parse_status(ret, PARSE_ERR);
1515 return;
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 = asm_alloc(sizeof(*ret->shader));
1528 if(!ret->shader) {
1529 ERR("Failed to allocate memory for the shader\n");
1530 set_parse_status(ret, PARSE_ERR);
1531 return;
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 = asm_alloc(sizeof(*ret->shader));
1544 if(!ret->shader) {
1545 ERR("Failed to allocate memory for the shader\n");
1546 set_parse_status(ret, PARSE_ERR);
1547 return;
1550 ret->shader->type = ST_PIXEL;
1551 ret->shader->version = BWRITERPS_VERSION(3, 0);
1552 ret->funcs = &parser_ps_3;