d3dx9: Allow modifiers on the ps dcl input instruction.
[wine/hacks.git] / dlls / d3dx9_36 / asmparser.c
blob3c29da8faa42cf19a4c3a6113609bf0c40d8587b
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 "d3dx9_36_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
30 WINE_DECLARE_DEBUG_CHANNEL(parsed_shader);
33 /* How to map vs 1.0 and 2.0 varyings to 3.0 ones
34 * oTx is mapped to ox, which happens to be an
35 * identical mapping since BWRITERSPR_TEXCRDOUT == BWRITERSPR_OUTPUT
36 * oPos, oFog and point size are mapped to general output regs as well.
37 * the vs 1.x and 2.x parser functions add varying declarations
38 * to the shader, and the 1.x and 2.x output functions check those varyings
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->writemask)) {
114 ERR("Out of memory\n");
115 set_parse_status(This, PARSE_ERR);
119 static void asmparser_dcl_input(struct asm_parser *This, DWORD usage, DWORD num,
120 DWORD mod, const struct shader_reg *reg) {
121 if(!This->shader) return;
122 if(mod != 0 &&
123 (This->shader->version != BWRITERPS_VERSION(3, 0) ||
124 (mod != BWRITERSPDM_MSAMPCENTROID &&
125 mod != BWRITERSPDM_PARTIALPRECISION))) {
126 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
127 set_parse_status(This, PARSE_ERR);
128 return;
130 if(!record_declaration(This->shader, usage, num, mod, FALSE, reg->regnum, reg->writemask)) {
131 ERR("Out of memory\n");
132 set_parse_status(This, PARSE_ERR);
136 static void asmparser_dcl_sampler(struct asm_parser *This, DWORD samptype, DWORD regnum, unsigned int line_no) {
137 if(!This->shader) return;
138 if(!record_sampler(This->shader, samptype, regnum)) {
139 ERR("Out of memory\n");
140 set_parse_status(This, PARSE_ERR);
144 static void asmparser_sincos(struct asm_parser *This, DWORD mod, DWORD shift,
145 const struct shader_reg *dst,
146 const struct src_regs *srcs) {
147 struct instruction *instr;
149 if(!srcs || srcs->count != 3) {
150 asmparser_message(This, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This->line_no);
151 set_parse_status(This, PARSE_ERR);
152 return;
155 instr = alloc_instr(3);
156 if(!instr) {
157 ERR("Error allocating memory for the instruction\n");
158 set_parse_status(This, PARSE_ERR);
159 return;
162 instr->opcode = BWRITERSIO_SINCOS;
163 instr->dstmod = mod;
164 instr->shift = shift;
165 instr->comptype = 0;
167 This->funcs->dstreg(This, instr, dst);
168 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
169 This->funcs->srcreg(This, instr, 1, &srcs->reg[1]);
170 This->funcs->srcreg(This, instr, 2, &srcs->reg[2]);
172 if(!add_instruction(This->shader, instr)) {
173 ERR("Out of memory\n");
174 set_parse_status(This, PARSE_ERR);
178 static void asmparser_instr(struct asm_parser *This, DWORD opcode,
179 DWORD mod, DWORD shift,
180 BWRITER_COMPARISON_TYPE comp,
181 const struct shader_reg *dst,
182 const struct src_regs *srcs, int expectednsrcs) {
183 struct instruction *instr;
184 unsigned int i;
185 BOOL firstreg = TRUE;
186 unsigned int src_count = srcs ? srcs->count : 0;
188 if(!This->shader) return;
190 TRACE_(parsed_shader)("%s%s%s ", debug_print_opcode(opcode),
191 debug_print_dstmod(mod),
192 debug_print_comp(comp));
193 if(dst) {
194 TRACE_(parsed_shader)("%s", debug_print_dstreg(dst, This->shader->type));
195 firstreg = FALSE;
197 for(i = 0; i < src_count; i++) {
198 if(!firstreg) TRACE_(parsed_shader)(", ");
199 else firstreg = FALSE;
200 TRACE_(parsed_shader)("%s", debug_print_srcreg(&srcs->reg[i],
201 This->shader->type));
203 TRACE_(parsed_shader)("\n");
205 /* Check for instructions with different syntaxes in different shader versio
206 ns */
207 switch(opcode) {
208 case BWRITERSIO_SINCOS:
209 /* The syntax changes between vs 2 and the other shader versions */
210 if(This->shader->version == BWRITERVS_VERSION(2, 0) ||
211 This->shader->version == BWRITERVS_VERSION(2, 1)) {
212 asmparser_sincos(This, mod, shift, dst, srcs);
213 return;
215 /* Use the default handling */
216 break;
219 if(src_count != expectednsrcs) {
220 asmparser_message(This, "Line %u: Wrong number of source registers\n", This->line_no);
221 set_parse_status(This, PARSE_ERR);
222 return;
225 instr = alloc_instr(src_count);
226 if(!instr) {
227 ERR("Error allocating memory for the instruction\n");
228 set_parse_status(This, PARSE_ERR);
229 return;
232 instr->opcode = opcode;
233 instr->dstmod = mod;
234 instr->shift = shift;
235 instr->comptype = comp;
236 if(dst) This->funcs->dstreg(This, instr, dst);
237 for(i = 0; i < src_count; i++) {
238 This->funcs->srcreg(This, instr, i, &srcs->reg[i]);
241 if(!add_instruction(This->shader, instr)) {
242 ERR("Out of memory\n");
243 set_parse_status(This, PARSE_ERR);
247 static struct shader_reg map_oldvs_register(const struct shader_reg *reg) {
248 struct shader_reg ret;
249 switch(reg->type) {
250 case BWRITERSPR_RASTOUT:
251 ret = *reg;
252 ret.type = BWRITERSPR_OUTPUT;
253 switch(reg->regnum) {
254 case BWRITERSRO_POSITION:
255 ret.regnum = OPOS_REG;
256 break;
257 case BWRITERSRO_FOG:
258 ret.regnum = OFOG_REG;
259 ret.writemask = OFOG_WRITEMASK;
260 break;
261 case BWRITERSRO_POINT_SIZE:
262 ret.regnum = OPTS_REG;
263 ret.writemask = OPTS_WRITEMASK;
264 break;
265 default:
266 FIXME("Unhandled RASTOUT register %u\n", reg->regnum);
267 return *reg;
269 return ret;
271 case BWRITERSPR_TEXCRDOUT:
272 ret = *reg;
273 ret.type = BWRITERSPR_OUTPUT;
274 switch(reg->regnum) {
275 case 0: ret.regnum = OT0_REG; break;
276 case 1: ret.regnum = OT1_REG; break;
277 case 2: ret.regnum = OT2_REG; break;
278 case 3: ret.regnum = OT3_REG; break;
279 case 4: ret.regnum = OT4_REG; break;
280 case 5: ret.regnum = OT5_REG; break;
281 case 6: ret.regnum = OT6_REG; break;
282 case 7: ret.regnum = OT7_REG; break;
283 default:
284 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg->regnum);
285 return *reg;
287 return ret;
289 case BWRITERSPR_ATTROUT:
290 ret = *reg;
291 ret.type = BWRITERSPR_OUTPUT;
292 switch(reg->regnum) {
293 case 0: ret.regnum = OD0_REG; break;
294 case 1: ret.regnum = OD1_REG; break;
295 default:
296 FIXME("Unhandled ATTROUT regnum %u\n", reg->regnum);
297 return *reg;
299 return ret;
301 default: return *reg;
305 static struct shader_reg map_oldps_register(const struct shader_reg *reg, BOOL tex_varying) {
306 struct shader_reg ret;
307 switch(reg->type) {
308 case BWRITERSPR_TEXTURE:
309 if(tex_varying) {
310 ret = *reg;
311 ret.type = BWRITERSPR_INPUT;
312 switch(reg->regnum) {
313 case 0: ret.regnum = T0_VARYING; break;
314 case 1: ret.regnum = T1_VARYING; break;
315 case 2: ret.regnum = T2_VARYING; break;
316 case 3: ret.regnum = T3_VARYING; break;
317 case 4: ret.regnum = T4_VARYING; break;
318 case 5: ret.regnum = T5_VARYING; break;
319 case 6: ret.regnum = T6_VARYING; break;
320 case 7: ret.regnum = T7_VARYING; break;
321 default:
322 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
323 return *reg;
325 return ret;
326 } else {
327 FIXME("TODO: ps_1_x texture register mapping\n");
328 return *reg;
331 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
332 to 3.0 ones */
334 default: return *reg;
338 /* Checks for unsupported source modifiers in VS (all versions) or
339 PS 2.0 and newer */
340 static void check_legacy_srcmod(struct asm_parser *This, DWORD srcmod) {
341 if(srcmod == BWRITERSPSM_BIAS || srcmod == BWRITERSPSM_BIASNEG ||
342 srcmod == BWRITERSPSM_SIGN || srcmod == BWRITERSPSM_SIGNNEG ||
343 srcmod == BWRITERSPSM_COMP || srcmod == BWRITERSPSM_X2 ||
344 srcmod == BWRITERSPSM_X2NEG || srcmod == BWRITERSPSM_DZ ||
345 srcmod == BWRITERSPSM_DW) {
346 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
347 This->line_no,
348 debug_print_srcmod(srcmod));
349 set_parse_status(This, PARSE_ERR);
353 static void check_abs_srcmod(struct asm_parser *This, DWORD srcmod) {
354 if(srcmod == BWRITERSPSM_ABS || srcmod == BWRITERSPSM_ABSNEG) {
355 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
356 This->line_no,
357 debug_print_srcmod(srcmod));
358 set_parse_status(This, PARSE_ERR);
362 static void check_loop_swizzle(struct asm_parser *This,
363 const struct shader_reg *src) {
364 if((src->type == BWRITERSPR_LOOP && src->swizzle != BWRITERVS_NOSWIZZLE) ||
365 (src->rel_reg && src->rel_reg->type == BWRITERSPR_LOOP &&
366 src->rel_reg->swizzle != BWRITERVS_NOSWIZZLE)) {
367 asmparser_message(This, "Line %u: Swizzle not allowed on aL register\n", This->line_no);
368 set_parse_status(This, PARSE_ERR);
372 static void check_shift_dstmod(struct asm_parser *This, DWORD shift) {
373 if(shift != 0) {
374 asmparser_message(This, "Line %u: Shift modifiers not supported in this shader version\n",
375 This->line_no);
376 set_parse_status(This, PARSE_ERR);
380 static void check_ps_dstmod(struct asm_parser *This, DWORD dstmod) {
381 if(dstmod == BWRITERSPDM_PARTIALPRECISION ||
382 dstmod == BWRITERSPDM_MSAMPCENTROID) {
383 asmparser_message(This, "Line %u: Instruction modifier %s not supported in this shader version\n",
384 This->line_no,
385 debug_print_dstmod(dstmod));
386 set_parse_status(This, PARSE_ERR);
390 struct allowed_reg_type {
391 DWORD type;
392 DWORD count;
393 BOOL reladdr;
396 static BOOL check_reg_type(const struct shader_reg *reg,
397 const struct allowed_reg_type *allowed) {
398 unsigned int i = 0;
400 while(allowed[i].type != ~0U) {
401 if(reg->type == allowed[i].type) {
402 if(reg->rel_reg) {
403 if(allowed[i].reladdr)
404 return TRUE; /* The relative addressing register
405 can have a negative value, we
406 can't check the register index */
407 return FALSE;
409 if(reg->regnum < allowed[i].count) return TRUE;
410 return FALSE;
412 i++;
414 return FALSE;
417 /* Native assembler doesn't do separate checks for src and dst registers */
418 static const struct allowed_reg_type vs_1_reg_allowed[] = {
419 { BWRITERSPR_TEMP, 12, FALSE },
420 { BWRITERSPR_INPUT, 16, FALSE },
421 { BWRITERSPR_CONST, ~0U, TRUE },
422 { BWRITERSPR_ADDR, 1, FALSE },
423 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
424 { BWRITERSPR_ATTROUT, 2, FALSE },
425 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
426 { ~0U, 0 } /* End tag */
429 /* struct instruction *asmparser_srcreg
431 * Records a source register in the instruction and does shader version
432 * specific checks and modifications on it
434 * Parameters:
435 * This: Shader parser instance
436 * instr: instruction to store the register in
437 * num: Number of source register
438 * src: Pointer to source the register structure. The caller can free
439 * it afterwards
441 static void asmparser_srcreg_vs_1(struct asm_parser *This,
442 struct instruction *instr, int num,
443 const struct shader_reg *src) {
444 struct shader_reg reg;
446 if(!check_reg_type(src, vs_1_reg_allowed)) {
447 asmparser_message(This, "Line %u: Source register %s not supported in VS 1\n",
448 This->line_no,
449 debug_print_srcreg(src, ST_VERTEX));
450 set_parse_status(This, PARSE_ERR);
452 check_legacy_srcmod(This, src->srcmod);
453 check_abs_srcmod(This, src->srcmod);
454 reg = map_oldvs_register(src);
455 memcpy(&instr->src[num], &reg, sizeof(reg));
458 static const struct allowed_reg_type vs_2_reg_allowed[] = {
459 { BWRITERSPR_TEMP, 12, FALSE },
460 { BWRITERSPR_INPUT, 16, FALSE },
461 { BWRITERSPR_CONST, ~0U, TRUE },
462 { BWRITERSPR_ADDR, 1, FALSE },
463 { BWRITERSPR_CONSTBOOL, 16, FALSE },
464 { BWRITERSPR_CONSTINT, 16, FALSE },
465 { BWRITERSPR_LOOP, 1, FALSE },
466 { BWRITERSPR_LABEL, 2048, FALSE },
467 { BWRITERSPR_PREDICATE, 1, FALSE },
468 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
469 { BWRITERSPR_ATTROUT, 2, FALSE },
470 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
471 { ~0U, 0 } /* End tag */
474 static void asmparser_srcreg_vs_2(struct asm_parser *This,
475 struct instruction *instr, int num,
476 const struct shader_reg *src) {
477 struct shader_reg reg;
479 if(!check_reg_type(src, vs_2_reg_allowed)) {
480 asmparser_message(This, "Line %u: Source register %s not supported in VS 2\n",
481 This->line_no,
482 debug_print_srcreg(src, ST_VERTEX));
483 set_parse_status(This, PARSE_ERR);
485 check_loop_swizzle(This, src);
486 check_legacy_srcmod(This, src->srcmod);
487 check_abs_srcmod(This, src->srcmod);
488 reg = map_oldvs_register(src);
489 memcpy(&instr->src[num], &reg, sizeof(reg));
492 static const struct allowed_reg_type vs_3_reg_allowed[] = {
493 { BWRITERSPR_TEMP, 32, FALSE },
494 { BWRITERSPR_INPUT, 16, TRUE },
495 { BWRITERSPR_CONST, ~0U, TRUE },
496 { BWRITERSPR_ADDR, 1, FALSE },
497 { BWRITERSPR_CONSTBOOL, 16, FALSE },
498 { BWRITERSPR_CONSTINT, 16, FALSE },
499 { BWRITERSPR_LOOP, 1, FALSE },
500 { BWRITERSPR_LABEL, 2048, FALSE },
501 { BWRITERSPR_PREDICATE, 1, FALSE },
502 { BWRITERSPR_SAMPLER, 4, FALSE },
503 { BWRITERSPR_OUTPUT, 12, TRUE },
504 { ~0U, 0 } /* End tag */
507 static void asmparser_srcreg_vs_3(struct asm_parser *This,
508 struct instruction *instr, int num,
509 const struct shader_reg *src) {
510 if(!check_reg_type(src, vs_3_reg_allowed)) {
511 asmparser_message(This, "Line %u: Source register %s not supported in VS 3.0\n",
512 This->line_no,
513 debug_print_srcreg(src, ST_VERTEX));
514 set_parse_status(This, PARSE_ERR);
516 check_loop_swizzle(This, src);
517 check_legacy_srcmod(This, src->srcmod);
518 memcpy(&instr->src[num], src, sizeof(*src));
521 static const struct allowed_reg_type ps_2_0_reg_allowed[] = {
522 { BWRITERSPR_INPUT, 2, FALSE },
523 { BWRITERSPR_TEMP, 32, FALSE },
524 { BWRITERSPR_CONST, 32, FALSE },
525 { BWRITERSPR_CONSTINT, 16, FALSE },
526 { BWRITERSPR_CONSTBOOL, 16, FALSE },
527 { BWRITERSPR_SAMPLER, 16, FALSE },
528 { BWRITERSPR_TEXTURE, 8, FALSE },
529 { BWRITERSPR_COLOROUT, 4, FALSE },
530 { BWRITERSPR_DEPTHOUT, 1, FALSE },
531 { ~0U, 0 } /* End tag */
534 static void asmparser_srcreg_ps_2(struct asm_parser *This,
535 struct instruction *instr, int num,
536 const struct shader_reg *src) {
537 struct shader_reg reg;
539 if(!check_reg_type(src, ps_2_0_reg_allowed)) {
540 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.0\n",
541 This->line_no,
542 debug_print_srcreg(src, ST_PIXEL));
543 set_parse_status(This, PARSE_ERR);
545 check_legacy_srcmod(This, src->srcmod);
546 check_abs_srcmod(This, src->srcmod);
547 reg = map_oldps_register(src, TRUE);
548 memcpy(&instr->src[num], &reg, sizeof(reg));
551 static const struct allowed_reg_type ps_2_x_reg_allowed[] = {
552 { BWRITERSPR_INPUT, 2, FALSE },
553 { BWRITERSPR_TEMP, 32, FALSE },
554 { BWRITERSPR_CONST, 32, FALSE },
555 { BWRITERSPR_CONSTINT, 16, FALSE },
556 { BWRITERSPR_CONSTBOOL, 16, FALSE },
557 { BWRITERSPR_PREDICATE, 1, FALSE },
558 { BWRITERSPR_SAMPLER, 16, FALSE },
559 { BWRITERSPR_TEXTURE, 8, FALSE },
560 { BWRITERSPR_LABEL, 2048, FALSE },
561 { BWRITERSPR_COLOROUT, 4, FALSE },
562 { BWRITERSPR_DEPTHOUT, 1, FALSE },
563 { ~0U, 0 } /* End tag */
566 static void asmparser_srcreg_ps_2_x(struct asm_parser *This,
567 struct instruction *instr, int num,
568 const struct shader_reg *src) {
569 struct shader_reg reg;
571 if(!check_reg_type(src, ps_2_x_reg_allowed)) {
572 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.x\n",
573 This->line_no,
574 debug_print_srcreg(src, ST_PIXEL));
575 set_parse_status(This, PARSE_ERR);
577 check_legacy_srcmod(This, src->srcmod);
578 check_abs_srcmod(This, src->srcmod);
579 reg = map_oldps_register(src, TRUE);
580 memcpy(&instr->src[num], &reg, sizeof(reg));
583 static const struct allowed_reg_type ps_3_reg_allowed[] = {
584 { BWRITERSPR_INPUT, 10, TRUE },
585 { BWRITERSPR_TEMP, 32, FALSE },
586 { BWRITERSPR_CONST, 224, FALSE },
587 { BWRITERSPR_CONSTINT, 16, FALSE },
588 { BWRITERSPR_CONSTBOOL, 16, FALSE },
589 { BWRITERSPR_PREDICATE, 1, FALSE },
590 { BWRITERSPR_SAMPLER, 16, FALSE },
591 { BWRITERSPR_MISCTYPE, 2, FALSE }, /* vPos and vFace */
592 { BWRITERSPR_LOOP, 1, FALSE },
593 { BWRITERSPR_LABEL, 2048, FALSE },
594 { BWRITERSPR_COLOROUT, 4, FALSE },
595 { BWRITERSPR_DEPTHOUT, 1, FALSE },
596 { ~0U, 0 } /* End tag */
599 static void asmparser_srcreg_ps_3(struct asm_parser *This,
600 struct instruction *instr, int num,
601 const struct shader_reg *src) {
602 if(!check_reg_type(src, ps_3_reg_allowed)) {
603 asmparser_message(This, "Line %u: Source register %s not supported in PS 3.0\n",
604 This->line_no,
605 debug_print_srcreg(src, ST_PIXEL));
606 set_parse_status(This, PARSE_ERR);
608 check_loop_swizzle(This, src);
609 check_legacy_srcmod(This, src->srcmod);
610 memcpy(&instr->src[num], src, sizeof(*src));
613 static void asmparser_dstreg_vs_1(struct asm_parser *This,
614 struct instruction *instr,
615 const struct shader_reg *dst) {
616 struct shader_reg reg;
618 if(!check_reg_type(dst, vs_1_reg_allowed)) {
619 asmparser_message(This, "Line %u: Destination register %s not supported in VS 1\n",
620 This->line_no,
621 debug_print_dstreg(dst, ST_VERTEX));
622 set_parse_status(This, PARSE_ERR);
624 check_ps_dstmod(This, instr->dstmod);
625 check_shift_dstmod(This, instr->shift);
626 reg = map_oldvs_register(dst);
627 memcpy(&instr->dst, &reg, sizeof(reg));
628 instr->has_dst = TRUE;
631 static void asmparser_dstreg_vs_2(struct asm_parser *This,
632 struct instruction *instr,
633 const struct shader_reg *dst) {
634 struct shader_reg reg;
636 if(!check_reg_type(dst, vs_2_reg_allowed)) {
637 asmparser_message(This, "Line %u: Destination register %s not supported in VS 2.0\n",
638 This->line_no,
639 debug_print_dstreg(dst, ST_VERTEX));
640 set_parse_status(This, PARSE_ERR);
642 check_ps_dstmod(This, instr->dstmod);
643 check_shift_dstmod(This, instr->shift);
644 reg = map_oldvs_register(dst);
645 memcpy(&instr->dst, &reg, sizeof(reg));
646 instr->has_dst = TRUE;
649 static void asmparser_dstreg_vs_3(struct asm_parser *This,
650 struct instruction *instr,
651 const struct shader_reg *dst) {
652 if(!check_reg_type(dst, vs_3_reg_allowed)) {
653 asmparser_message(This, "Line %u: Destination register %s not supported in VS 3.0\n",
654 This->line_no,
655 debug_print_dstreg(dst, ST_VERTEX));
656 set_parse_status(This, PARSE_ERR);
658 check_ps_dstmod(This, instr->dstmod);
659 check_shift_dstmod(This, instr->shift);
660 memcpy(&instr->dst, dst, sizeof(*dst));
661 instr->has_dst = TRUE;
664 static void asmparser_dstreg_ps_2(struct asm_parser *This,
665 struct instruction *instr,
666 const struct shader_reg *dst) {
667 struct shader_reg reg;
669 if(!check_reg_type(dst, ps_2_0_reg_allowed)) {
670 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.0\n",
671 This->line_no,
672 debug_print_dstreg(dst, ST_PIXEL));
673 set_parse_status(This, PARSE_ERR);
675 check_shift_dstmod(This, instr->shift);
676 reg = map_oldps_register(dst, TRUE);
677 memcpy(&instr->dst, &reg, sizeof(reg));
678 instr->has_dst = TRUE;
681 static void asmparser_dstreg_ps_2_x(struct asm_parser *This,
682 struct instruction *instr,
683 const struct shader_reg *dst) {
684 struct shader_reg reg;
686 if(!check_reg_type(dst, ps_2_x_reg_allowed)) {
687 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.x\n",
688 This->line_no,
689 debug_print_dstreg(dst, ST_PIXEL));
690 set_parse_status(This, PARSE_ERR);
692 check_shift_dstmod(This, instr->shift);
693 reg = map_oldps_register(dst, TRUE);
694 memcpy(&instr->dst, &reg, sizeof(reg));
695 instr->has_dst = TRUE;
698 static void asmparser_dstreg_ps_3(struct asm_parser *This,
699 struct instruction *instr,
700 const struct shader_reg *dst) {
701 if(!check_reg_type(dst, ps_3_reg_allowed)) {
702 asmparser_message(This, "Line %u: Destination register %s not supported in PS 3.0\n",
703 This->line_no,
704 debug_print_dstreg(dst, ST_PIXEL));
705 set_parse_status(This, PARSE_ERR);
707 check_shift_dstmod(This, instr->shift);
708 memcpy(&instr->dst, dst, sizeof(*dst));
709 instr->has_dst = TRUE;
712 static void asmparser_predicate_supported(struct asm_parser *This,
713 const struct shader_reg *predicate) {
714 /* this sets the predicate of the last instruction added to the shader */
715 if(!This->shader) return;
716 if(This->shader->num_instrs == 0) ERR("Predicate without an instruction\n");
717 This->shader->instr[This->shader->num_instrs - 1]->has_predicate = TRUE;
718 memcpy(&This->shader->instr[This->shader->num_instrs - 1]->predicate, predicate, sizeof(*predicate));
721 static void asmparser_predicate_unsupported(struct asm_parser *This,
722 const struct shader_reg *predicate) {
723 asmparser_message(This, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This->line_no);
724 set_parse_status(This, PARSE_ERR);
727 static void asmparser_coissue_unsupported(struct asm_parser *This) {
728 asmparser_message(This, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This->line_no);
729 set_parse_status(This, PARSE_ERR);
732 static const struct asmparser_backend parser_vs_1 = {
733 asmparser_constF,
734 asmparser_constI,
735 asmparser_constB,
737 asmparser_dstreg_vs_1,
738 asmparser_srcreg_vs_1,
740 asmparser_predicate_unsupported,
741 asmparser_coissue_unsupported,
743 asmparser_dcl_output,
744 asmparser_dcl_input,
745 asmparser_dcl_sampler,
747 asmparser_end,
749 asmparser_instr,
752 static const struct asmparser_backend parser_vs_2 = {
753 asmparser_constF,
754 asmparser_constI,
755 asmparser_constB,
757 asmparser_dstreg_vs_2,
758 asmparser_srcreg_vs_2,
760 asmparser_predicate_supported,
761 asmparser_coissue_unsupported,
763 asmparser_dcl_output,
764 asmparser_dcl_input,
765 asmparser_dcl_sampler,
767 asmparser_end,
769 asmparser_instr,
772 static const struct asmparser_backend parser_vs_3 = {
773 asmparser_constF,
774 asmparser_constI,
775 asmparser_constB,
777 asmparser_dstreg_vs_3,
778 asmparser_srcreg_vs_3,
780 asmparser_predicate_supported,
781 asmparser_coissue_unsupported,
783 asmparser_dcl_output,
784 asmparser_dcl_input,
785 asmparser_dcl_sampler,
787 asmparser_end,
789 asmparser_instr,
792 static const struct asmparser_backend parser_ps_2 = {
793 asmparser_constF,
794 asmparser_constI,
795 asmparser_constB,
797 asmparser_dstreg_ps_2,
798 asmparser_srcreg_ps_2,
800 asmparser_predicate_unsupported,
801 asmparser_coissue_unsupported,
803 asmparser_dcl_output,
804 asmparser_dcl_input,
805 asmparser_dcl_sampler,
807 asmparser_end,
809 asmparser_instr,
812 static const struct asmparser_backend parser_ps_2_x = {
813 asmparser_constF,
814 asmparser_constI,
815 asmparser_constB,
817 asmparser_dstreg_ps_2_x,
818 asmparser_srcreg_ps_2_x,
820 asmparser_predicate_supported,
821 asmparser_coissue_unsupported,
823 asmparser_dcl_output,
824 asmparser_dcl_input,
825 asmparser_dcl_sampler,
827 asmparser_end,
829 asmparser_instr,
832 static const struct asmparser_backend parser_ps_3 = {
833 asmparser_constF,
834 asmparser_constI,
835 asmparser_constB,
837 asmparser_dstreg_ps_3,
838 asmparser_srcreg_ps_3,
840 asmparser_predicate_supported,
841 asmparser_coissue_unsupported,
843 asmparser_dcl_output,
844 asmparser_dcl_input,
845 asmparser_dcl_sampler,
847 asmparser_end,
849 asmparser_instr,
852 static void gen_oldvs_output(struct bwriter_shader *shader) {
853 record_declaration(shader, BWRITERDECLUSAGE_POSITION, 0, 0, TRUE, OPOS_REG, BWRITERSP_WRITEMASK_ALL);
854 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, TRUE, OT0_REG, BWRITERSP_WRITEMASK_ALL);
855 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, TRUE, OT1_REG, BWRITERSP_WRITEMASK_ALL);
856 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, TRUE, OT2_REG, BWRITERSP_WRITEMASK_ALL);
857 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, TRUE, OT3_REG, BWRITERSP_WRITEMASK_ALL);
858 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, TRUE, OT4_REG, BWRITERSP_WRITEMASK_ALL);
859 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, TRUE, OT5_REG, BWRITERSP_WRITEMASK_ALL);
860 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, TRUE, OT6_REG, BWRITERSP_WRITEMASK_ALL);
861 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, TRUE, OT7_REG, BWRITERSP_WRITEMASK_ALL);
862 record_declaration(shader, BWRITERDECLUSAGE_FOG, 0, 0, TRUE, OFOG_REG, OFOG_WRITEMASK);
863 record_declaration(shader, BWRITERDECLUSAGE_PSIZE, 0, 0, TRUE, OPTS_REG, OPTS_WRITEMASK);
864 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, TRUE, OD0_REG, BWRITERSP_WRITEMASK_ALL);
865 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, TRUE, OD1_REG, BWRITERSP_WRITEMASK_ALL);
868 static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) {
869 switch(texcoords) {
870 case 8: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, FALSE, T7_VARYING, BWRITERSP_WRITEMASK_ALL);
871 case 7: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, FALSE, T6_VARYING, BWRITERSP_WRITEMASK_ALL);
872 case 6: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, FALSE, T5_VARYING, BWRITERSP_WRITEMASK_ALL);
873 case 5: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, FALSE, T4_VARYING, BWRITERSP_WRITEMASK_ALL);
874 case 4: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, FALSE, T3_VARYING, BWRITERSP_WRITEMASK_ALL);
875 case 3: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, FALSE, T2_VARYING, BWRITERSP_WRITEMASK_ALL);
876 case 2: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, FALSE, T1_VARYING, BWRITERSP_WRITEMASK_ALL);
877 case 1: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, FALSE, T0_VARYING, BWRITERSP_WRITEMASK_ALL);
879 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, FALSE, C0_VARYING, BWRITERSP_WRITEMASK_ALL);
880 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL);
883 void create_vs10_parser(struct asm_parser *ret) {
884 TRACE_(parsed_shader)("vs_1_0\n");
886 ret->shader = asm_alloc(sizeof(*ret->shader));
887 if(!ret->shader) {
888 ERR("Failed to allocate memory for the shader\n");
889 set_parse_status(ret, PARSE_ERR);
890 return;
893 ret->shader->type = ST_VERTEX;
894 ret->shader->version = BWRITERVS_VERSION(1, 0);
895 ret->funcs = &parser_vs_1;
896 gen_oldvs_output(ret->shader);
899 void create_vs11_parser(struct asm_parser *ret) {
900 TRACE_(parsed_shader)("vs_1_1\n");
902 ret->shader = asm_alloc(sizeof(*ret->shader));
903 if(!ret->shader) {
904 ERR("Failed to allocate memory for the shader\n");
905 set_parse_status(ret, PARSE_ERR);
906 return;
909 ret->shader->type = ST_VERTEX;
910 ret->shader->version = BWRITERVS_VERSION(1, 1);
911 ret->funcs = &parser_vs_1;
912 gen_oldvs_output(ret->shader);
915 void create_vs20_parser(struct asm_parser *ret) {
916 TRACE_(parsed_shader)("vs_2_0\n");
918 ret->shader = asm_alloc(sizeof(*ret->shader));
919 if(!ret->shader) {
920 ERR("Failed to allocate memory for the shader\n");
921 set_parse_status(ret, PARSE_ERR);
922 return;
925 ret->shader->type = ST_VERTEX;
926 ret->shader->version = BWRITERVS_VERSION(2, 0);
927 ret->funcs = &parser_vs_2;
928 gen_oldvs_output(ret->shader);
931 void create_vs2x_parser(struct asm_parser *ret) {
932 TRACE_(parsed_shader)("vs_2_x\n");
934 ret->shader = asm_alloc(sizeof(*ret->shader));
935 if(!ret->shader) {
936 ERR("Failed to allocate memory for the shader\n");
937 set_parse_status(ret, PARSE_ERR);
938 return;
941 ret->shader->type = ST_VERTEX;
942 ret->shader->version = BWRITERVS_VERSION(2, 1);
943 ret->funcs = &parser_vs_2;
944 gen_oldvs_output(ret->shader);
947 void create_vs30_parser(struct asm_parser *ret) {
948 TRACE_(parsed_shader)("vs_3_0\n");
950 ret->shader = asm_alloc(sizeof(*ret->shader));
951 if(!ret->shader) {
952 ERR("Failed to allocate memory for the shader\n");
953 set_parse_status(ret, PARSE_ERR);
954 return;
957 ret->shader->type = ST_VERTEX;
958 ret->shader->version = BWRITERVS_VERSION(3, 0);
959 ret->funcs = &parser_vs_3;
962 void create_ps20_parser(struct asm_parser *ret) {
963 TRACE_(parsed_shader)("ps_2_0\n");
965 ret->shader = asm_alloc(sizeof(*ret->shader));
966 if(!ret->shader) {
967 ERR("Failed to allocate memory for the shader\n");
968 set_parse_status(ret, PARSE_ERR);
969 return;
972 ret->shader->type = ST_PIXEL;
973 ret->shader->version = BWRITERPS_VERSION(2, 0);
974 ret->funcs = &parser_ps_2;
975 gen_oldps_input(ret->shader, 8);
978 void create_ps2x_parser(struct asm_parser *ret) {
979 TRACE_(parsed_shader)("ps_2_x\n");
981 ret->shader = asm_alloc(sizeof(*ret->shader));
982 if(!ret->shader) {
983 ERR("Failed to allocate memory for the shader\n");
984 set_parse_status(ret, PARSE_ERR);
985 return;
988 ret->shader->type = ST_PIXEL;
989 ret->shader->version = BWRITERPS_VERSION(2, 1);
990 ret->funcs = &parser_ps_2_x;
991 gen_oldps_input(ret->shader, 8);
994 void create_ps30_parser(struct asm_parser *ret) {
995 TRACE_(parsed_shader)("ps_3_0\n");
997 ret->shader = asm_alloc(sizeof(*ret->shader));
998 if(!ret->shader) {
999 ERR("Failed to allocate memory for the shader\n");
1000 set_parse_status(ret, PARSE_ERR);
1001 return;
1004 ret->shader->type = ST_PIXEL;
1005 ret->shader->version = BWRITERPS_VERSION(3, 0);
1006 ret->funcs = &parser_ps_3;