pop 82b96efacb3a9cb3edb980e14b32deae44651c0c
[wine/hacks.git] / dlls / d3dx9_36 / asmparser.c
blob0869ee68be63dd79383f6c775b1202f791d28724
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,
137 DWORD mod, DWORD regnum,
138 unsigned int line_no) {
139 if(!This->shader) return;
140 if(mod != 0 &&
141 (This->shader->version != BWRITERPS_VERSION(3, 0) ||
142 (mod != BWRITERSPDM_MSAMPCENTROID &&
143 mod != BWRITERSPDM_PARTIALPRECISION))) {
144 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
145 set_parse_status(This, PARSE_ERR);
146 return;
148 if(!record_sampler(This->shader, samptype, mod, regnum)) {
149 ERR("Out of memory\n");
150 set_parse_status(This, PARSE_ERR);
154 static void asmparser_sincos(struct asm_parser *This, DWORD mod, DWORD shift,
155 const struct shader_reg *dst,
156 const struct src_regs *srcs) {
157 struct instruction *instr;
159 if(!srcs || srcs->count != 3) {
160 asmparser_message(This, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This->line_no);
161 set_parse_status(This, PARSE_ERR);
162 return;
165 instr = alloc_instr(3);
166 if(!instr) {
167 ERR("Error allocating memory for the instruction\n");
168 set_parse_status(This, PARSE_ERR);
169 return;
172 instr->opcode = BWRITERSIO_SINCOS;
173 instr->dstmod = mod;
174 instr->shift = shift;
175 instr->comptype = 0;
177 This->funcs->dstreg(This, instr, dst);
178 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
179 This->funcs->srcreg(This, instr, 1, &srcs->reg[1]);
180 This->funcs->srcreg(This, instr, 2, &srcs->reg[2]);
182 if(!add_instruction(This->shader, instr)) {
183 ERR("Out of memory\n");
184 set_parse_status(This, PARSE_ERR);
188 static void asmparser_instr(struct asm_parser *This, DWORD opcode,
189 DWORD mod, DWORD shift,
190 BWRITER_COMPARISON_TYPE comp,
191 const struct shader_reg *dst,
192 const struct src_regs *srcs, int expectednsrcs) {
193 struct instruction *instr;
194 unsigned int i;
195 BOOL firstreg = TRUE;
196 unsigned int src_count = srcs ? srcs->count : 0;
198 if(!This->shader) return;
200 TRACE_(parsed_shader)("%s%s%s ", debug_print_opcode(opcode),
201 debug_print_dstmod(mod),
202 debug_print_comp(comp));
203 if(dst) {
204 TRACE_(parsed_shader)("%s", debug_print_dstreg(dst, This->shader->type));
205 firstreg = FALSE;
207 for(i = 0; i < src_count; i++) {
208 if(!firstreg) TRACE_(parsed_shader)(", ");
209 else firstreg = FALSE;
210 TRACE_(parsed_shader)("%s", debug_print_srcreg(&srcs->reg[i],
211 This->shader->type));
213 TRACE_(parsed_shader)("\n");
215 /* Check for instructions with different syntaxes in different shader versio
216 ns */
217 switch(opcode) {
218 case BWRITERSIO_SINCOS:
219 /* The syntax changes between vs 2 and the other shader versions */
220 if(This->shader->version == BWRITERVS_VERSION(2, 0) ||
221 This->shader->version == BWRITERVS_VERSION(2, 1)) {
222 asmparser_sincos(This, mod, shift, dst, srcs);
223 return;
225 /* Use the default handling */
226 break;
229 if(src_count != expectednsrcs) {
230 asmparser_message(This, "Line %u: Wrong number of source registers\n", This->line_no);
231 set_parse_status(This, PARSE_ERR);
232 return;
235 instr = alloc_instr(src_count);
236 if(!instr) {
237 ERR("Error allocating memory for the instruction\n");
238 set_parse_status(This, PARSE_ERR);
239 return;
242 instr->opcode = opcode;
243 instr->dstmod = mod;
244 instr->shift = shift;
245 instr->comptype = comp;
246 if(dst) This->funcs->dstreg(This, instr, dst);
247 for(i = 0; i < src_count; i++) {
248 This->funcs->srcreg(This, instr, i, &srcs->reg[i]);
251 if(!add_instruction(This->shader, instr)) {
252 ERR("Out of memory\n");
253 set_parse_status(This, PARSE_ERR);
257 static struct shader_reg map_oldvs_register(const struct shader_reg *reg) {
258 struct shader_reg ret;
259 switch(reg->type) {
260 case BWRITERSPR_RASTOUT:
261 ret = *reg;
262 ret.type = BWRITERSPR_OUTPUT;
263 switch(reg->regnum) {
264 case BWRITERSRO_POSITION:
265 ret.regnum = OPOS_REG;
266 break;
267 case BWRITERSRO_FOG:
268 ret.regnum = OFOG_REG;
269 ret.writemask = OFOG_WRITEMASK;
270 break;
271 case BWRITERSRO_POINT_SIZE:
272 ret.regnum = OPTS_REG;
273 ret.writemask = OPTS_WRITEMASK;
274 break;
275 default:
276 FIXME("Unhandled RASTOUT register %u\n", reg->regnum);
277 return *reg;
279 return ret;
281 case BWRITERSPR_TEXCRDOUT:
282 ret = *reg;
283 ret.type = BWRITERSPR_OUTPUT;
284 switch(reg->regnum) {
285 case 0: ret.regnum = OT0_REG; break;
286 case 1: ret.regnum = OT1_REG; break;
287 case 2: ret.regnum = OT2_REG; break;
288 case 3: ret.regnum = OT3_REG; break;
289 case 4: ret.regnum = OT4_REG; break;
290 case 5: ret.regnum = OT5_REG; break;
291 case 6: ret.regnum = OT6_REG; break;
292 case 7: ret.regnum = OT7_REG; break;
293 default:
294 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg->regnum);
295 return *reg;
297 return ret;
299 case BWRITERSPR_ATTROUT:
300 ret = *reg;
301 ret.type = BWRITERSPR_OUTPUT;
302 switch(reg->regnum) {
303 case 0: ret.regnum = OD0_REG; break;
304 case 1: ret.regnum = OD1_REG; break;
305 default:
306 FIXME("Unhandled ATTROUT regnum %u\n", reg->regnum);
307 return *reg;
309 return ret;
311 default: return *reg;
315 static struct shader_reg map_oldps_register(const struct shader_reg *reg, BOOL tex_varying) {
316 struct shader_reg ret;
317 switch(reg->type) {
318 case BWRITERSPR_TEXTURE:
319 if(tex_varying) {
320 ret = *reg;
321 ret.type = BWRITERSPR_INPUT;
322 switch(reg->regnum) {
323 case 0: ret.regnum = T0_VARYING; break;
324 case 1: ret.regnum = T1_VARYING; break;
325 case 2: ret.regnum = T2_VARYING; break;
326 case 3: ret.regnum = T3_VARYING; break;
327 case 4: ret.regnum = T4_VARYING; break;
328 case 5: ret.regnum = T5_VARYING; break;
329 case 6: ret.regnum = T6_VARYING; break;
330 case 7: ret.regnum = T7_VARYING; break;
331 default:
332 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
333 return *reg;
335 return ret;
336 } else {
337 FIXME("TODO: ps_1_x texture register mapping\n");
338 return *reg;
341 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
342 to 3.0 ones */
344 default: return *reg;
348 /* Checks for unsupported source modifiers in VS (all versions) or
349 PS 2.0 and newer */
350 static void check_legacy_srcmod(struct asm_parser *This, DWORD srcmod) {
351 if(srcmod == BWRITERSPSM_BIAS || srcmod == BWRITERSPSM_BIASNEG ||
352 srcmod == BWRITERSPSM_SIGN || srcmod == BWRITERSPSM_SIGNNEG ||
353 srcmod == BWRITERSPSM_COMP || srcmod == BWRITERSPSM_X2 ||
354 srcmod == BWRITERSPSM_X2NEG || srcmod == BWRITERSPSM_DZ ||
355 srcmod == BWRITERSPSM_DW) {
356 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
357 This->line_no,
358 debug_print_srcmod(srcmod));
359 set_parse_status(This, PARSE_ERR);
363 static void check_abs_srcmod(struct asm_parser *This, DWORD srcmod) {
364 if(srcmod == BWRITERSPSM_ABS || srcmod == BWRITERSPSM_ABSNEG) {
365 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
366 This->line_no,
367 debug_print_srcmod(srcmod));
368 set_parse_status(This, PARSE_ERR);
372 static void check_loop_swizzle(struct asm_parser *This,
373 const struct shader_reg *src) {
374 if((src->type == BWRITERSPR_LOOP && src->swizzle != BWRITERVS_NOSWIZZLE) ||
375 (src->rel_reg && src->rel_reg->type == BWRITERSPR_LOOP &&
376 src->rel_reg->swizzle != BWRITERVS_NOSWIZZLE)) {
377 asmparser_message(This, "Line %u: Swizzle not allowed on aL register\n", This->line_no);
378 set_parse_status(This, PARSE_ERR);
382 static void check_shift_dstmod(struct asm_parser *This, DWORD shift) {
383 if(shift != 0) {
384 asmparser_message(This, "Line %u: Shift modifiers not supported in this shader version\n",
385 This->line_no);
386 set_parse_status(This, PARSE_ERR);
390 static void check_ps_dstmod(struct asm_parser *This, DWORD dstmod) {
391 if(dstmod == BWRITERSPDM_PARTIALPRECISION ||
392 dstmod == BWRITERSPDM_MSAMPCENTROID) {
393 asmparser_message(This, "Line %u: Instruction modifier %s not supported in this shader version\n",
394 This->line_no,
395 debug_print_dstmod(dstmod));
396 set_parse_status(This, PARSE_ERR);
400 struct allowed_reg_type {
401 DWORD type;
402 DWORD count;
403 BOOL reladdr;
406 static BOOL check_reg_type(const struct shader_reg *reg,
407 const struct allowed_reg_type *allowed) {
408 unsigned int i = 0;
410 while(allowed[i].type != ~0U) {
411 if(reg->type == allowed[i].type) {
412 if(reg->rel_reg) {
413 if(allowed[i].reladdr)
414 return TRUE; /* The relative addressing register
415 can have a negative value, we
416 can't check the register index */
417 return FALSE;
419 if(reg->regnum < allowed[i].count) return TRUE;
420 return FALSE;
422 i++;
424 return FALSE;
427 /* Native assembler doesn't do separate checks for src and dst registers */
428 static const struct allowed_reg_type vs_1_reg_allowed[] = {
429 { BWRITERSPR_TEMP, 12, FALSE },
430 { BWRITERSPR_INPUT, 16, FALSE },
431 { BWRITERSPR_CONST, ~0U, TRUE },
432 { BWRITERSPR_ADDR, 1, FALSE },
433 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
434 { BWRITERSPR_ATTROUT, 2, FALSE },
435 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
436 { ~0U, 0 } /* End tag */
439 /* struct instruction *asmparser_srcreg
441 * Records a source register in the instruction and does shader version
442 * specific checks and modifications on it
444 * Parameters:
445 * This: Shader parser instance
446 * instr: instruction to store the register in
447 * num: Number of source register
448 * src: Pointer to source the register structure. The caller can free
449 * it afterwards
451 static void asmparser_srcreg_vs_1(struct asm_parser *This,
452 struct instruction *instr, int num,
453 const struct shader_reg *src) {
454 struct shader_reg reg;
456 if(!check_reg_type(src, vs_1_reg_allowed)) {
457 asmparser_message(This, "Line %u: Source register %s not supported in VS 1\n",
458 This->line_no,
459 debug_print_srcreg(src, ST_VERTEX));
460 set_parse_status(This, PARSE_ERR);
462 check_legacy_srcmod(This, src->srcmod);
463 check_abs_srcmod(This, src->srcmod);
464 reg = map_oldvs_register(src);
465 memcpy(&instr->src[num], &reg, sizeof(reg));
468 static const struct allowed_reg_type vs_2_reg_allowed[] = {
469 { BWRITERSPR_TEMP, 12, FALSE },
470 { BWRITERSPR_INPUT, 16, FALSE },
471 { BWRITERSPR_CONST, ~0U, TRUE },
472 { BWRITERSPR_ADDR, 1, FALSE },
473 { BWRITERSPR_CONSTBOOL, 16, FALSE },
474 { BWRITERSPR_CONSTINT, 16, FALSE },
475 { BWRITERSPR_LOOP, 1, FALSE },
476 { BWRITERSPR_LABEL, 2048, FALSE },
477 { BWRITERSPR_PREDICATE, 1, FALSE },
478 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
479 { BWRITERSPR_ATTROUT, 2, FALSE },
480 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
481 { ~0U, 0 } /* End tag */
484 static void asmparser_srcreg_vs_2(struct asm_parser *This,
485 struct instruction *instr, int num,
486 const struct shader_reg *src) {
487 struct shader_reg reg;
489 if(!check_reg_type(src, vs_2_reg_allowed)) {
490 asmparser_message(This, "Line %u: Source register %s not supported in VS 2\n",
491 This->line_no,
492 debug_print_srcreg(src, ST_VERTEX));
493 set_parse_status(This, PARSE_ERR);
495 check_loop_swizzle(This, src);
496 check_legacy_srcmod(This, src->srcmod);
497 check_abs_srcmod(This, src->srcmod);
498 reg = map_oldvs_register(src);
499 memcpy(&instr->src[num], &reg, sizeof(reg));
502 static const struct allowed_reg_type vs_3_reg_allowed[] = {
503 { BWRITERSPR_TEMP, 32, FALSE },
504 { BWRITERSPR_INPUT, 16, TRUE },
505 { BWRITERSPR_CONST, ~0U, TRUE },
506 { BWRITERSPR_ADDR, 1, FALSE },
507 { BWRITERSPR_CONSTBOOL, 16, FALSE },
508 { BWRITERSPR_CONSTINT, 16, FALSE },
509 { BWRITERSPR_LOOP, 1, FALSE },
510 { BWRITERSPR_LABEL, 2048, FALSE },
511 { BWRITERSPR_PREDICATE, 1, FALSE },
512 { BWRITERSPR_SAMPLER, 4, FALSE },
513 { BWRITERSPR_OUTPUT, 12, TRUE },
514 { ~0U, 0 } /* End tag */
517 static void asmparser_srcreg_vs_3(struct asm_parser *This,
518 struct instruction *instr, int num,
519 const struct shader_reg *src) {
520 if(!check_reg_type(src, vs_3_reg_allowed)) {
521 asmparser_message(This, "Line %u: Source register %s not supported in VS 3.0\n",
522 This->line_no,
523 debug_print_srcreg(src, ST_VERTEX));
524 set_parse_status(This, PARSE_ERR);
526 check_loop_swizzle(This, src);
527 check_legacy_srcmod(This, src->srcmod);
528 memcpy(&instr->src[num], src, sizeof(*src));
531 static const struct allowed_reg_type ps_2_0_reg_allowed[] = {
532 { BWRITERSPR_INPUT, 2, FALSE },
533 { BWRITERSPR_TEMP, 32, FALSE },
534 { BWRITERSPR_CONST, 32, FALSE },
535 { BWRITERSPR_CONSTINT, 16, FALSE },
536 { BWRITERSPR_CONSTBOOL, 16, FALSE },
537 { BWRITERSPR_SAMPLER, 16, FALSE },
538 { BWRITERSPR_TEXTURE, 8, FALSE },
539 { BWRITERSPR_COLOROUT, 4, FALSE },
540 { BWRITERSPR_DEPTHOUT, 1, FALSE },
541 { ~0U, 0 } /* End tag */
544 static void asmparser_srcreg_ps_2(struct asm_parser *This,
545 struct instruction *instr, int num,
546 const struct shader_reg *src) {
547 struct shader_reg reg;
549 if(!check_reg_type(src, ps_2_0_reg_allowed)) {
550 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.0\n",
551 This->line_no,
552 debug_print_srcreg(src, ST_PIXEL));
553 set_parse_status(This, PARSE_ERR);
555 check_legacy_srcmod(This, src->srcmod);
556 check_abs_srcmod(This, src->srcmod);
557 reg = map_oldps_register(src, TRUE);
558 memcpy(&instr->src[num], &reg, sizeof(reg));
561 static const struct allowed_reg_type ps_2_x_reg_allowed[] = {
562 { BWRITERSPR_INPUT, 2, FALSE },
563 { BWRITERSPR_TEMP, 32, FALSE },
564 { BWRITERSPR_CONST, 32, FALSE },
565 { BWRITERSPR_CONSTINT, 16, FALSE },
566 { BWRITERSPR_CONSTBOOL, 16, FALSE },
567 { BWRITERSPR_PREDICATE, 1, FALSE },
568 { BWRITERSPR_SAMPLER, 16, FALSE },
569 { BWRITERSPR_TEXTURE, 8, FALSE },
570 { BWRITERSPR_LABEL, 2048, FALSE },
571 { BWRITERSPR_COLOROUT, 4, FALSE },
572 { BWRITERSPR_DEPTHOUT, 1, FALSE },
573 { ~0U, 0 } /* End tag */
576 static void asmparser_srcreg_ps_2_x(struct asm_parser *This,
577 struct instruction *instr, int num,
578 const struct shader_reg *src) {
579 struct shader_reg reg;
581 if(!check_reg_type(src, ps_2_x_reg_allowed)) {
582 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.x\n",
583 This->line_no,
584 debug_print_srcreg(src, ST_PIXEL));
585 set_parse_status(This, PARSE_ERR);
587 check_legacy_srcmod(This, src->srcmod);
588 check_abs_srcmod(This, src->srcmod);
589 reg = map_oldps_register(src, TRUE);
590 memcpy(&instr->src[num], &reg, sizeof(reg));
593 static const struct allowed_reg_type ps_3_reg_allowed[] = {
594 { BWRITERSPR_INPUT, 10, TRUE },
595 { BWRITERSPR_TEMP, 32, FALSE },
596 { BWRITERSPR_CONST, 224, FALSE },
597 { BWRITERSPR_CONSTINT, 16, FALSE },
598 { BWRITERSPR_CONSTBOOL, 16, FALSE },
599 { BWRITERSPR_PREDICATE, 1, FALSE },
600 { BWRITERSPR_SAMPLER, 16, FALSE },
601 { BWRITERSPR_MISCTYPE, 2, FALSE }, /* vPos and vFace */
602 { BWRITERSPR_LOOP, 1, FALSE },
603 { BWRITERSPR_LABEL, 2048, FALSE },
604 { BWRITERSPR_COLOROUT, 4, FALSE },
605 { BWRITERSPR_DEPTHOUT, 1, FALSE },
606 { ~0U, 0 } /* End tag */
609 static void asmparser_srcreg_ps_3(struct asm_parser *This,
610 struct instruction *instr, int num,
611 const struct shader_reg *src) {
612 if(!check_reg_type(src, ps_3_reg_allowed)) {
613 asmparser_message(This, "Line %u: Source register %s not supported in PS 3.0\n",
614 This->line_no,
615 debug_print_srcreg(src, ST_PIXEL));
616 set_parse_status(This, PARSE_ERR);
618 check_loop_swizzle(This, src);
619 check_legacy_srcmod(This, src->srcmod);
620 memcpy(&instr->src[num], src, sizeof(*src));
623 static void asmparser_dstreg_vs_1(struct asm_parser *This,
624 struct instruction *instr,
625 const struct shader_reg *dst) {
626 struct shader_reg reg;
628 if(!check_reg_type(dst, vs_1_reg_allowed)) {
629 asmparser_message(This, "Line %u: Destination register %s not supported in VS 1\n",
630 This->line_no,
631 debug_print_dstreg(dst, ST_VERTEX));
632 set_parse_status(This, PARSE_ERR);
634 check_ps_dstmod(This, instr->dstmod);
635 check_shift_dstmod(This, instr->shift);
636 reg = map_oldvs_register(dst);
637 memcpy(&instr->dst, &reg, sizeof(reg));
638 instr->has_dst = TRUE;
641 static void asmparser_dstreg_vs_2(struct asm_parser *This,
642 struct instruction *instr,
643 const struct shader_reg *dst) {
644 struct shader_reg reg;
646 if(!check_reg_type(dst, vs_2_reg_allowed)) {
647 asmparser_message(This, "Line %u: Destination register %s not supported in VS 2.0\n",
648 This->line_no,
649 debug_print_dstreg(dst, ST_VERTEX));
650 set_parse_status(This, PARSE_ERR);
652 check_ps_dstmod(This, instr->dstmod);
653 check_shift_dstmod(This, instr->shift);
654 reg = map_oldvs_register(dst);
655 memcpy(&instr->dst, &reg, sizeof(reg));
656 instr->has_dst = TRUE;
659 static void asmparser_dstreg_vs_3(struct asm_parser *This,
660 struct instruction *instr,
661 const struct shader_reg *dst) {
662 if(!check_reg_type(dst, vs_3_reg_allowed)) {
663 asmparser_message(This, "Line %u: Destination register %s not supported in VS 3.0\n",
664 This->line_no,
665 debug_print_dstreg(dst, ST_VERTEX));
666 set_parse_status(This, PARSE_ERR);
668 check_ps_dstmod(This, instr->dstmod);
669 check_shift_dstmod(This, instr->shift);
670 memcpy(&instr->dst, dst, sizeof(*dst));
671 instr->has_dst = TRUE;
674 static void asmparser_dstreg_ps_2(struct asm_parser *This,
675 struct instruction *instr,
676 const struct shader_reg *dst) {
677 struct shader_reg reg;
679 if(!check_reg_type(dst, ps_2_0_reg_allowed)) {
680 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.0\n",
681 This->line_no,
682 debug_print_dstreg(dst, ST_PIXEL));
683 set_parse_status(This, PARSE_ERR);
685 check_shift_dstmod(This, instr->shift);
686 reg = map_oldps_register(dst, TRUE);
687 memcpy(&instr->dst, &reg, sizeof(reg));
688 instr->has_dst = TRUE;
691 static void asmparser_dstreg_ps_2_x(struct asm_parser *This,
692 struct instruction *instr,
693 const struct shader_reg *dst) {
694 struct shader_reg reg;
696 if(!check_reg_type(dst, ps_2_x_reg_allowed)) {
697 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.x\n",
698 This->line_no,
699 debug_print_dstreg(dst, ST_PIXEL));
700 set_parse_status(This, PARSE_ERR);
702 check_shift_dstmod(This, instr->shift);
703 reg = map_oldps_register(dst, TRUE);
704 memcpy(&instr->dst, &reg, sizeof(reg));
705 instr->has_dst = TRUE;
708 static void asmparser_dstreg_ps_3(struct asm_parser *This,
709 struct instruction *instr,
710 const struct shader_reg *dst) {
711 if(!check_reg_type(dst, ps_3_reg_allowed)) {
712 asmparser_message(This, "Line %u: Destination register %s not supported in PS 3.0\n",
713 This->line_no,
714 debug_print_dstreg(dst, ST_PIXEL));
715 set_parse_status(This, PARSE_ERR);
717 check_shift_dstmod(This, instr->shift);
718 memcpy(&instr->dst, dst, sizeof(*dst));
719 instr->has_dst = TRUE;
722 static void asmparser_predicate_supported(struct asm_parser *This,
723 const struct shader_reg *predicate) {
724 /* this sets the predicate of the last instruction added to the shader */
725 if(!This->shader) return;
726 if(This->shader->num_instrs == 0) ERR("Predicate without an instruction\n");
727 This->shader->instr[This->shader->num_instrs - 1]->has_predicate = TRUE;
728 memcpy(&This->shader->instr[This->shader->num_instrs - 1]->predicate, predicate, sizeof(*predicate));
731 static void asmparser_predicate_unsupported(struct asm_parser *This,
732 const struct shader_reg *predicate) {
733 asmparser_message(This, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This->line_no);
734 set_parse_status(This, PARSE_ERR);
737 static void asmparser_coissue_unsupported(struct asm_parser *This) {
738 asmparser_message(This, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This->line_no);
739 set_parse_status(This, PARSE_ERR);
742 static const struct asmparser_backend parser_vs_1 = {
743 asmparser_constF,
744 asmparser_constI,
745 asmparser_constB,
747 asmparser_dstreg_vs_1,
748 asmparser_srcreg_vs_1,
750 asmparser_predicate_unsupported,
751 asmparser_coissue_unsupported,
753 asmparser_dcl_output,
754 asmparser_dcl_input,
755 asmparser_dcl_sampler,
757 asmparser_end,
759 asmparser_instr,
762 static const struct asmparser_backend parser_vs_2 = {
763 asmparser_constF,
764 asmparser_constI,
765 asmparser_constB,
767 asmparser_dstreg_vs_2,
768 asmparser_srcreg_vs_2,
770 asmparser_predicate_supported,
771 asmparser_coissue_unsupported,
773 asmparser_dcl_output,
774 asmparser_dcl_input,
775 asmparser_dcl_sampler,
777 asmparser_end,
779 asmparser_instr,
782 static const struct asmparser_backend parser_vs_3 = {
783 asmparser_constF,
784 asmparser_constI,
785 asmparser_constB,
787 asmparser_dstreg_vs_3,
788 asmparser_srcreg_vs_3,
790 asmparser_predicate_supported,
791 asmparser_coissue_unsupported,
793 asmparser_dcl_output,
794 asmparser_dcl_input,
795 asmparser_dcl_sampler,
797 asmparser_end,
799 asmparser_instr,
802 static const struct asmparser_backend parser_ps_2 = {
803 asmparser_constF,
804 asmparser_constI,
805 asmparser_constB,
807 asmparser_dstreg_ps_2,
808 asmparser_srcreg_ps_2,
810 asmparser_predicate_unsupported,
811 asmparser_coissue_unsupported,
813 asmparser_dcl_output,
814 asmparser_dcl_input,
815 asmparser_dcl_sampler,
817 asmparser_end,
819 asmparser_instr,
822 static const struct asmparser_backend parser_ps_2_x = {
823 asmparser_constF,
824 asmparser_constI,
825 asmparser_constB,
827 asmparser_dstreg_ps_2_x,
828 asmparser_srcreg_ps_2_x,
830 asmparser_predicate_supported,
831 asmparser_coissue_unsupported,
833 asmparser_dcl_output,
834 asmparser_dcl_input,
835 asmparser_dcl_sampler,
837 asmparser_end,
839 asmparser_instr,
842 static const struct asmparser_backend parser_ps_3 = {
843 asmparser_constF,
844 asmparser_constI,
845 asmparser_constB,
847 asmparser_dstreg_ps_3,
848 asmparser_srcreg_ps_3,
850 asmparser_predicate_supported,
851 asmparser_coissue_unsupported,
853 asmparser_dcl_output,
854 asmparser_dcl_input,
855 asmparser_dcl_sampler,
857 asmparser_end,
859 asmparser_instr,
862 static void gen_oldvs_output(struct bwriter_shader *shader) {
863 record_declaration(shader, BWRITERDECLUSAGE_POSITION, 0, 0, TRUE, OPOS_REG, BWRITERSP_WRITEMASK_ALL);
864 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, TRUE, OT0_REG, BWRITERSP_WRITEMASK_ALL);
865 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, TRUE, OT1_REG, BWRITERSP_WRITEMASK_ALL);
866 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, TRUE, OT2_REG, BWRITERSP_WRITEMASK_ALL);
867 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, TRUE, OT3_REG, BWRITERSP_WRITEMASK_ALL);
868 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, TRUE, OT4_REG, BWRITERSP_WRITEMASK_ALL);
869 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, TRUE, OT5_REG, BWRITERSP_WRITEMASK_ALL);
870 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, TRUE, OT6_REG, BWRITERSP_WRITEMASK_ALL);
871 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, TRUE, OT7_REG, BWRITERSP_WRITEMASK_ALL);
872 record_declaration(shader, BWRITERDECLUSAGE_FOG, 0, 0, TRUE, OFOG_REG, OFOG_WRITEMASK);
873 record_declaration(shader, BWRITERDECLUSAGE_PSIZE, 0, 0, TRUE, OPTS_REG, OPTS_WRITEMASK);
874 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, TRUE, OD0_REG, BWRITERSP_WRITEMASK_ALL);
875 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, TRUE, OD1_REG, BWRITERSP_WRITEMASK_ALL);
878 static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) {
879 switch(texcoords) {
880 case 8: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, FALSE, T7_VARYING, BWRITERSP_WRITEMASK_ALL);
881 case 7: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, FALSE, T6_VARYING, BWRITERSP_WRITEMASK_ALL);
882 case 6: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, FALSE, T5_VARYING, BWRITERSP_WRITEMASK_ALL);
883 case 5: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, FALSE, T4_VARYING, BWRITERSP_WRITEMASK_ALL);
884 case 4: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, FALSE, T3_VARYING, BWRITERSP_WRITEMASK_ALL);
885 case 3: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, FALSE, T2_VARYING, BWRITERSP_WRITEMASK_ALL);
886 case 2: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, FALSE, T1_VARYING, BWRITERSP_WRITEMASK_ALL);
887 case 1: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, FALSE, T0_VARYING, BWRITERSP_WRITEMASK_ALL);
889 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, FALSE, C0_VARYING, BWRITERSP_WRITEMASK_ALL);
890 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL);
893 void create_vs10_parser(struct asm_parser *ret) {
894 TRACE_(parsed_shader)("vs_1_0\n");
896 ret->shader = asm_alloc(sizeof(*ret->shader));
897 if(!ret->shader) {
898 ERR("Failed to allocate memory for the shader\n");
899 set_parse_status(ret, PARSE_ERR);
900 return;
903 ret->shader->type = ST_VERTEX;
904 ret->shader->version = BWRITERVS_VERSION(1, 0);
905 ret->funcs = &parser_vs_1;
906 gen_oldvs_output(ret->shader);
909 void create_vs11_parser(struct asm_parser *ret) {
910 TRACE_(parsed_shader)("vs_1_1\n");
912 ret->shader = asm_alloc(sizeof(*ret->shader));
913 if(!ret->shader) {
914 ERR("Failed to allocate memory for the shader\n");
915 set_parse_status(ret, PARSE_ERR);
916 return;
919 ret->shader->type = ST_VERTEX;
920 ret->shader->version = BWRITERVS_VERSION(1, 1);
921 ret->funcs = &parser_vs_1;
922 gen_oldvs_output(ret->shader);
925 void create_vs20_parser(struct asm_parser *ret) {
926 TRACE_(parsed_shader)("vs_2_0\n");
928 ret->shader = asm_alloc(sizeof(*ret->shader));
929 if(!ret->shader) {
930 ERR("Failed to allocate memory for the shader\n");
931 set_parse_status(ret, PARSE_ERR);
932 return;
935 ret->shader->type = ST_VERTEX;
936 ret->shader->version = BWRITERVS_VERSION(2, 0);
937 ret->funcs = &parser_vs_2;
938 gen_oldvs_output(ret->shader);
941 void create_vs2x_parser(struct asm_parser *ret) {
942 TRACE_(parsed_shader)("vs_2_x\n");
944 ret->shader = asm_alloc(sizeof(*ret->shader));
945 if(!ret->shader) {
946 ERR("Failed to allocate memory for the shader\n");
947 set_parse_status(ret, PARSE_ERR);
948 return;
951 ret->shader->type = ST_VERTEX;
952 ret->shader->version = BWRITERVS_VERSION(2, 1);
953 ret->funcs = &parser_vs_2;
954 gen_oldvs_output(ret->shader);
957 void create_vs30_parser(struct asm_parser *ret) {
958 TRACE_(parsed_shader)("vs_3_0\n");
960 ret->shader = asm_alloc(sizeof(*ret->shader));
961 if(!ret->shader) {
962 ERR("Failed to allocate memory for the shader\n");
963 set_parse_status(ret, PARSE_ERR);
964 return;
967 ret->shader->type = ST_VERTEX;
968 ret->shader->version = BWRITERVS_VERSION(3, 0);
969 ret->funcs = &parser_vs_3;
972 void create_ps20_parser(struct asm_parser *ret) {
973 TRACE_(parsed_shader)("ps_2_0\n");
975 ret->shader = asm_alloc(sizeof(*ret->shader));
976 if(!ret->shader) {
977 ERR("Failed to allocate memory for the shader\n");
978 set_parse_status(ret, PARSE_ERR);
979 return;
982 ret->shader->type = ST_PIXEL;
983 ret->shader->version = BWRITERPS_VERSION(2, 0);
984 ret->funcs = &parser_ps_2;
985 gen_oldps_input(ret->shader, 8);
988 void create_ps2x_parser(struct asm_parser *ret) {
989 TRACE_(parsed_shader)("ps_2_x\n");
991 ret->shader = asm_alloc(sizeof(*ret->shader));
992 if(!ret->shader) {
993 ERR("Failed to allocate memory for the shader\n");
994 set_parse_status(ret, PARSE_ERR);
995 return;
998 ret->shader->type = ST_PIXEL;
999 ret->shader->version = BWRITERPS_VERSION(2, 1);
1000 ret->funcs = &parser_ps_2_x;
1001 gen_oldps_input(ret->shader, 8);
1004 void create_ps30_parser(struct asm_parser *ret) {
1005 TRACE_(parsed_shader)("ps_3_0\n");
1007 ret->shader = asm_alloc(sizeof(*ret->shader));
1008 if(!ret->shader) {
1009 ERR("Failed to allocate memory for the shader\n");
1010 set_parse_status(ret, PARSE_ERR);
1011 return;
1014 ret->shader->type = ST_PIXEL;
1015 ret->shader->version = BWRITERPS_VERSION(3, 0);
1016 ret->funcs = &parser_ps_3;