wined3d: read_from_framebuffer_texture() isn't suitable for readback of onscreen...
[wine/testsucceed.git] / dlls / d3dx9_36 / asmparser.c
blob4e7f0183f271a01e9a3ce227882beef7c20aab1d
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, FALSE)) {
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 struct instruction instr;
123 if(!This->shader) return;
124 if(mod != 0 &&
125 (This->shader->version != BWRITERPS_VERSION(3, 0) ||
126 (mod != BWRITERSPDM_MSAMPCENTROID &&
127 mod != BWRITERSPDM_PARTIALPRECISION))) {
128 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
129 set_parse_status(This, PARSE_ERR);
130 return;
133 /* Check register type and modifiers */
134 instr.dstmod = mod;
135 instr.shift = 0;
136 This->funcs->dstreg(This, &instr, reg);
138 if(!record_declaration(This->shader, usage, num, mod, FALSE, reg->regnum, reg->writemask, FALSE)) {
139 ERR("Out of memory\n");
140 set_parse_status(This, PARSE_ERR);
144 static void asmparser_dcl_input_ps_2(struct asm_parser *This, DWORD usage, DWORD num,
145 DWORD mod, const struct shader_reg *reg) {
146 struct instruction instr;
148 if(!This->shader) return;
149 if(usage != 0) {
150 asmparser_message(This, "Line %u: Unsupported usage in dcl instruction\n", This->line_no);
151 set_parse_status(This, PARSE_ERR);
152 return;
154 instr.dstmod = mod;
155 instr.shift = 0;
156 This->funcs->dstreg(This, &instr, reg);
157 if(!record_declaration(This->shader, usage, num, mod, FALSE, instr.dst.regnum, instr.dst.writemask, FALSE)) {
158 ERR("Out of memory\n");
159 set_parse_status(This, PARSE_ERR);
163 static void asmparser_dcl_sampler(struct asm_parser *This, DWORD samptype,
164 DWORD mod, DWORD regnum,
165 unsigned int line_no) {
166 if(!This->shader) return;
167 if(mod != 0 &&
168 (This->shader->version != BWRITERPS_VERSION(3, 0) ||
169 (mod != BWRITERSPDM_MSAMPCENTROID &&
170 mod != BWRITERSPDM_PARTIALPRECISION))) {
171 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no);
172 set_parse_status(This, PARSE_ERR);
173 return;
175 if(!record_sampler(This->shader, samptype, mod, regnum)) {
176 ERR("Out of memory\n");
177 set_parse_status(This, PARSE_ERR);
181 static void asmparser_dcl_sampler_unsupported(struct asm_parser *This, DWORD samptype,
182 DWORD mod, DWORD regnum,
183 unsigned int line_no) {
184 asmparser_message(This, "Line %u: Sampler declaration unsupported in this shader version\n", This->line_no);
185 set_parse_status(This, PARSE_ERR);
188 static void asmparser_sincos(struct asm_parser *This, DWORD mod, DWORD shift,
189 const struct shader_reg *dst,
190 const struct src_regs *srcs) {
191 struct instruction *instr;
193 if(!srcs || srcs->count != 3) {
194 asmparser_message(This, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This->line_no);
195 set_parse_status(This, PARSE_ERR);
196 return;
199 instr = alloc_instr(3);
200 if(!instr) {
201 ERR("Error allocating memory for the instruction\n");
202 set_parse_status(This, PARSE_ERR);
203 return;
206 instr->opcode = BWRITERSIO_SINCOS;
207 instr->dstmod = mod;
208 instr->shift = shift;
209 instr->comptype = 0;
211 This->funcs->dstreg(This, instr, dst);
212 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
213 This->funcs->srcreg(This, instr, 1, &srcs->reg[1]);
214 This->funcs->srcreg(This, instr, 2, &srcs->reg[2]);
216 if(!add_instruction(This->shader, instr)) {
217 ERR("Out of memory\n");
218 set_parse_status(This, PARSE_ERR);
222 static void asmparser_instr(struct asm_parser *This, DWORD opcode,
223 DWORD mod, DWORD shift,
224 BWRITER_COMPARISON_TYPE comp,
225 const struct shader_reg *dst,
226 const struct src_regs *srcs, int expectednsrcs) {
227 struct instruction *instr;
228 unsigned int i;
229 BOOL firstreg = TRUE;
230 unsigned int src_count = srcs ? srcs->count : 0;
232 if(!This->shader) return;
234 TRACE_(parsed_shader)("%s%s%s ", debug_print_opcode(opcode),
235 debug_print_dstmod(mod),
236 debug_print_comp(comp));
237 if(dst) {
238 TRACE_(parsed_shader)("%s", debug_print_dstreg(dst, This->shader->type));
239 firstreg = FALSE;
241 for(i = 0; i < src_count; i++) {
242 if(!firstreg) TRACE_(parsed_shader)(", ");
243 else firstreg = FALSE;
244 TRACE_(parsed_shader)("%s", debug_print_srcreg(&srcs->reg[i],
245 This->shader->type));
247 TRACE_(parsed_shader)("\n");
249 /* Check for instructions with different syntaxes in different shader versio
250 ns */
251 switch(opcode) {
252 case BWRITERSIO_SINCOS:
253 /* The syntax changes between vs 2 and the other shader versions */
254 if(This->shader->version == BWRITERVS_VERSION(2, 0) ||
255 This->shader->version == BWRITERVS_VERSION(2, 1)) {
256 asmparser_sincos(This, mod, shift, dst, srcs);
257 return;
259 /* Use the default handling */
260 break;
263 if(src_count != expectednsrcs) {
264 asmparser_message(This, "Line %u: Wrong number of source registers\n", This->line_no);
265 set_parse_status(This, PARSE_ERR);
266 return;
269 instr = alloc_instr(src_count);
270 if(!instr) {
271 ERR("Error allocating memory for the instruction\n");
272 set_parse_status(This, PARSE_ERR);
273 return;
276 instr->opcode = opcode;
277 instr->dstmod = mod;
278 instr->shift = shift;
279 instr->comptype = comp;
280 if(dst) This->funcs->dstreg(This, instr, dst);
281 for(i = 0; i < src_count; i++) {
282 This->funcs->srcreg(This, instr, i, &srcs->reg[i]);
285 if(!add_instruction(This->shader, instr)) {
286 ERR("Out of memory\n");
287 set_parse_status(This, PARSE_ERR);
291 static struct shader_reg map_oldvs_register(const struct shader_reg *reg) {
292 struct shader_reg ret;
293 switch(reg->type) {
294 case BWRITERSPR_RASTOUT:
295 ret = *reg;
296 ret.type = BWRITERSPR_OUTPUT;
297 switch(reg->regnum) {
298 case BWRITERSRO_POSITION:
299 ret.regnum = OPOS_REG;
300 break;
301 case BWRITERSRO_FOG:
302 ret.regnum = OFOG_REG;
303 ret.writemask = OFOG_WRITEMASK;
304 break;
305 case BWRITERSRO_POINT_SIZE:
306 ret.regnum = OPTS_REG;
307 ret.writemask = OPTS_WRITEMASK;
308 break;
309 default:
310 FIXME("Unhandled RASTOUT register %u\n", reg->regnum);
311 return *reg;
313 return ret;
315 case BWRITERSPR_TEXCRDOUT:
316 ret = *reg;
317 ret.type = BWRITERSPR_OUTPUT;
318 switch(reg->regnum) {
319 case 0: ret.regnum = OT0_REG; break;
320 case 1: ret.regnum = OT1_REG; break;
321 case 2: ret.regnum = OT2_REG; break;
322 case 3: ret.regnum = OT3_REG; break;
323 case 4: ret.regnum = OT4_REG; break;
324 case 5: ret.regnum = OT5_REG; break;
325 case 6: ret.regnum = OT6_REG; break;
326 case 7: ret.regnum = OT7_REG; break;
327 default:
328 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg->regnum);
329 return *reg;
331 return ret;
333 case BWRITERSPR_ATTROUT:
334 ret = *reg;
335 ret.type = BWRITERSPR_OUTPUT;
336 switch(reg->regnum) {
337 case 0: ret.regnum = OD0_REG; break;
338 case 1: ret.regnum = OD1_REG; break;
339 default:
340 FIXME("Unhandled ATTROUT regnum %u\n", reg->regnum);
341 return *reg;
343 return ret;
345 default: return *reg;
349 static struct shader_reg map_oldps_register(const struct shader_reg *reg, BOOL tex_varying) {
350 struct shader_reg ret;
351 switch(reg->type) {
352 case BWRITERSPR_TEXTURE:
353 if(tex_varying) {
354 ret = *reg;
355 ret.type = BWRITERSPR_INPUT;
356 switch(reg->regnum) {
357 case 0: ret.regnum = T0_VARYING; break;
358 case 1: ret.regnum = T1_VARYING; break;
359 case 2: ret.regnum = T2_VARYING; break;
360 case 3: ret.regnum = T3_VARYING; break;
361 case 4: ret.regnum = T4_VARYING; break;
362 case 5: ret.regnum = T5_VARYING; break;
363 case 6: ret.regnum = T6_VARYING; break;
364 case 7: ret.regnum = T7_VARYING; break;
365 default:
366 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
367 return *reg;
369 return ret;
370 } else {
371 FIXME("TODO: ps_1_x texture register mapping\n");
372 return *reg;
375 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
376 to 3.0 ones */
378 default: return *reg;
382 /* Checks for unsupported source modifiers in VS (all versions) or
383 PS 2.0 and newer */
384 static void check_legacy_srcmod(struct asm_parser *This, DWORD srcmod) {
385 if(srcmod == BWRITERSPSM_BIAS || srcmod == BWRITERSPSM_BIASNEG ||
386 srcmod == BWRITERSPSM_SIGN || srcmod == BWRITERSPSM_SIGNNEG ||
387 srcmod == BWRITERSPSM_COMP || srcmod == BWRITERSPSM_X2 ||
388 srcmod == BWRITERSPSM_X2NEG || srcmod == BWRITERSPSM_DZ ||
389 srcmod == BWRITERSPSM_DW) {
390 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
391 This->line_no,
392 debug_print_srcmod(srcmod));
393 set_parse_status(This, PARSE_ERR);
397 static void check_abs_srcmod(struct asm_parser *This, DWORD srcmod) {
398 if(srcmod == BWRITERSPSM_ABS || srcmod == BWRITERSPSM_ABSNEG) {
399 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
400 This->line_no,
401 debug_print_srcmod(srcmod));
402 set_parse_status(This, PARSE_ERR);
406 static void check_loop_swizzle(struct asm_parser *This,
407 const struct shader_reg *src) {
408 if((src->type == BWRITERSPR_LOOP && src->swizzle != BWRITERVS_NOSWIZZLE) ||
409 (src->rel_reg && src->rel_reg->type == BWRITERSPR_LOOP &&
410 src->rel_reg->swizzle != BWRITERVS_NOSWIZZLE)) {
411 asmparser_message(This, "Line %u: Swizzle not allowed on aL register\n", This->line_no);
412 set_parse_status(This, PARSE_ERR);
416 static void check_shift_dstmod(struct asm_parser *This, DWORD shift) {
417 if(shift != 0) {
418 asmparser_message(This, "Line %u: Shift modifiers not supported in this shader version\n",
419 This->line_no);
420 set_parse_status(This, PARSE_ERR);
424 static void check_ps_dstmod(struct asm_parser *This, DWORD dstmod) {
425 if(dstmod == BWRITERSPDM_PARTIALPRECISION ||
426 dstmod == BWRITERSPDM_MSAMPCENTROID) {
427 asmparser_message(This, "Line %u: Instruction modifier %s not supported in this shader version\n",
428 This->line_no,
429 debug_print_dstmod(dstmod));
430 set_parse_status(This, PARSE_ERR);
434 struct allowed_reg_type {
435 DWORD type;
436 DWORD count;
437 BOOL reladdr;
440 static BOOL check_reg_type(const struct shader_reg *reg,
441 const struct allowed_reg_type *allowed) {
442 unsigned int i = 0;
444 while(allowed[i].type != ~0U) {
445 if(reg->type == allowed[i].type) {
446 if(reg->rel_reg) {
447 if(allowed[i].reladdr)
448 return TRUE; /* The relative addressing register
449 can have a negative value, we
450 can't check the register index */
451 return FALSE;
453 if(reg->regnum < allowed[i].count) return TRUE;
454 return FALSE;
456 i++;
458 return FALSE;
461 /* Native assembler doesn't do separate checks for src and dst registers */
462 static const struct allowed_reg_type vs_1_reg_allowed[] = {
463 { BWRITERSPR_TEMP, 12, FALSE },
464 { BWRITERSPR_INPUT, 16, FALSE },
465 { BWRITERSPR_CONST, ~0U, TRUE },
466 { BWRITERSPR_ADDR, 1, FALSE },
467 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
468 { BWRITERSPR_ATTROUT, 2, FALSE },
469 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
470 { ~0U, 0 } /* End tag */
473 /* struct instruction *asmparser_srcreg
475 * Records a source register in the instruction and does shader version
476 * specific checks and modifications on it
478 * Parameters:
479 * This: Shader parser instance
480 * instr: instruction to store the register in
481 * num: Number of source register
482 * src: Pointer to source the register structure. The caller can free
483 * it afterwards
485 static void asmparser_srcreg_vs_1(struct asm_parser *This,
486 struct instruction *instr, int num,
487 const struct shader_reg *src) {
488 struct shader_reg reg;
490 if(!check_reg_type(src, vs_1_reg_allowed)) {
491 asmparser_message(This, "Line %u: Source register %s not supported in VS 1\n",
492 This->line_no,
493 debug_print_srcreg(src, ST_VERTEX));
494 set_parse_status(This, PARSE_ERR);
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_2_reg_allowed[] = {
503 { BWRITERSPR_TEMP, 12, FALSE },
504 { BWRITERSPR_INPUT, 16, FALSE },
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_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
513 { BWRITERSPR_ATTROUT, 2, FALSE },
514 { BWRITERSPR_TEXCRDOUT, 8, FALSE },
515 { ~0U, 0 } /* End tag */
518 static void asmparser_srcreg_vs_2(struct asm_parser *This,
519 struct instruction *instr, int num,
520 const struct shader_reg *src) {
521 struct shader_reg reg;
523 if(!check_reg_type(src, vs_2_reg_allowed)) {
524 asmparser_message(This, "Line %u: Source register %s not supported in VS 2\n",
525 This->line_no,
526 debug_print_srcreg(src, ST_VERTEX));
527 set_parse_status(This, PARSE_ERR);
529 check_loop_swizzle(This, src);
530 check_legacy_srcmod(This, src->srcmod);
531 check_abs_srcmod(This, src->srcmod);
532 reg = map_oldvs_register(src);
533 memcpy(&instr->src[num], &reg, sizeof(reg));
536 static const struct allowed_reg_type vs_3_reg_allowed[] = {
537 { BWRITERSPR_TEMP, 32, FALSE },
538 { BWRITERSPR_INPUT, 16, TRUE },
539 { BWRITERSPR_CONST, ~0U, TRUE },
540 { BWRITERSPR_ADDR, 1, FALSE },
541 { BWRITERSPR_CONSTBOOL, 16, FALSE },
542 { BWRITERSPR_CONSTINT, 16, FALSE },
543 { BWRITERSPR_LOOP, 1, FALSE },
544 { BWRITERSPR_LABEL, 2048, FALSE },
545 { BWRITERSPR_PREDICATE, 1, FALSE },
546 { BWRITERSPR_SAMPLER, 4, FALSE },
547 { BWRITERSPR_OUTPUT, 12, TRUE },
548 { ~0U, 0 } /* End tag */
551 static void asmparser_srcreg_vs_3(struct asm_parser *This,
552 struct instruction *instr, int num,
553 const struct shader_reg *src) {
554 if(!check_reg_type(src, vs_3_reg_allowed)) {
555 asmparser_message(This, "Line %u: Source register %s not supported in VS 3.0\n",
556 This->line_no,
557 debug_print_srcreg(src, ST_VERTEX));
558 set_parse_status(This, PARSE_ERR);
560 check_loop_swizzle(This, src);
561 check_legacy_srcmod(This, src->srcmod);
562 memcpy(&instr->src[num], src, sizeof(*src));
565 static const struct allowed_reg_type ps_2_0_reg_allowed[] = {
566 { BWRITERSPR_INPUT, 2, FALSE },
567 { BWRITERSPR_TEMP, 32, FALSE },
568 { BWRITERSPR_CONST, 32, FALSE },
569 { BWRITERSPR_CONSTINT, 16, FALSE },
570 { BWRITERSPR_CONSTBOOL, 16, FALSE },
571 { BWRITERSPR_SAMPLER, 16, FALSE },
572 { BWRITERSPR_TEXTURE, 8, FALSE },
573 { BWRITERSPR_COLOROUT, 4, FALSE },
574 { BWRITERSPR_DEPTHOUT, 1, FALSE },
575 { ~0U, 0 } /* End tag */
578 static void asmparser_srcreg_ps_2(struct asm_parser *This,
579 struct instruction *instr, int num,
580 const struct shader_reg *src) {
581 struct shader_reg reg;
583 if(!check_reg_type(src, ps_2_0_reg_allowed)) {
584 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.0\n",
585 This->line_no,
586 debug_print_srcreg(src, ST_PIXEL));
587 set_parse_status(This, PARSE_ERR);
589 check_legacy_srcmod(This, src->srcmod);
590 check_abs_srcmod(This, src->srcmod);
591 reg = map_oldps_register(src, TRUE);
592 memcpy(&instr->src[num], &reg, sizeof(reg));
595 static const struct allowed_reg_type ps_2_x_reg_allowed[] = {
596 { BWRITERSPR_INPUT, 2, FALSE },
597 { BWRITERSPR_TEMP, 32, FALSE },
598 { BWRITERSPR_CONST, 32, FALSE },
599 { BWRITERSPR_CONSTINT, 16, FALSE },
600 { BWRITERSPR_CONSTBOOL, 16, FALSE },
601 { BWRITERSPR_PREDICATE, 1, FALSE },
602 { BWRITERSPR_SAMPLER, 16, FALSE },
603 { BWRITERSPR_TEXTURE, 8, FALSE },
604 { BWRITERSPR_LABEL, 2048, FALSE },
605 { BWRITERSPR_COLOROUT, 4, FALSE },
606 { BWRITERSPR_DEPTHOUT, 1, FALSE },
607 { ~0U, 0 } /* End tag */
610 static void asmparser_srcreg_ps_2_x(struct asm_parser *This,
611 struct instruction *instr, int num,
612 const struct shader_reg *src) {
613 struct shader_reg reg;
615 if(!check_reg_type(src, ps_2_x_reg_allowed)) {
616 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.x\n",
617 This->line_no,
618 debug_print_srcreg(src, ST_PIXEL));
619 set_parse_status(This, PARSE_ERR);
621 check_legacy_srcmod(This, src->srcmod);
622 check_abs_srcmod(This, src->srcmod);
623 reg = map_oldps_register(src, TRUE);
624 memcpy(&instr->src[num], &reg, sizeof(reg));
627 static const struct allowed_reg_type ps_3_reg_allowed[] = {
628 { BWRITERSPR_INPUT, 10, TRUE },
629 { BWRITERSPR_TEMP, 32, FALSE },
630 { BWRITERSPR_CONST, 224, FALSE },
631 { BWRITERSPR_CONSTINT, 16, FALSE },
632 { BWRITERSPR_CONSTBOOL, 16, FALSE },
633 { BWRITERSPR_PREDICATE, 1, FALSE },
634 { BWRITERSPR_SAMPLER, 16, FALSE },
635 { BWRITERSPR_MISCTYPE, 2, FALSE }, /* vPos and vFace */
636 { BWRITERSPR_LOOP, 1, FALSE },
637 { BWRITERSPR_LABEL, 2048, FALSE },
638 { BWRITERSPR_COLOROUT, 4, FALSE },
639 { BWRITERSPR_DEPTHOUT, 1, FALSE },
640 { ~0U, 0 } /* End tag */
643 static void asmparser_srcreg_ps_3(struct asm_parser *This,
644 struct instruction *instr, int num,
645 const struct shader_reg *src) {
646 if(!check_reg_type(src, ps_3_reg_allowed)) {
647 asmparser_message(This, "Line %u: Source register %s not supported in PS 3.0\n",
648 This->line_no,
649 debug_print_srcreg(src, ST_PIXEL));
650 set_parse_status(This, PARSE_ERR);
652 check_loop_swizzle(This, src);
653 check_legacy_srcmod(This, src->srcmod);
654 memcpy(&instr->src[num], src, sizeof(*src));
657 static void asmparser_dstreg_vs_1(struct asm_parser *This,
658 struct instruction *instr,
659 const struct shader_reg *dst) {
660 struct shader_reg reg;
662 if(!check_reg_type(dst, vs_1_reg_allowed)) {
663 asmparser_message(This, "Line %u: Destination register %s not supported in VS 1\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 reg = map_oldvs_register(dst);
671 memcpy(&instr->dst, &reg, sizeof(reg));
672 instr->has_dst = TRUE;
675 static void asmparser_dstreg_vs_2(struct asm_parser *This,
676 struct instruction *instr,
677 const struct shader_reg *dst) {
678 struct shader_reg reg;
680 if(!check_reg_type(dst, vs_2_reg_allowed)) {
681 asmparser_message(This, "Line %u: Destination register %s not supported in VS 2.0\n",
682 This->line_no,
683 debug_print_dstreg(dst, ST_VERTEX));
684 set_parse_status(This, PARSE_ERR);
686 check_ps_dstmod(This, instr->dstmod);
687 check_shift_dstmod(This, instr->shift);
688 reg = map_oldvs_register(dst);
689 memcpy(&instr->dst, &reg, sizeof(reg));
690 instr->has_dst = TRUE;
693 static void asmparser_dstreg_vs_3(struct asm_parser *This,
694 struct instruction *instr,
695 const struct shader_reg *dst) {
696 if(!check_reg_type(dst, vs_3_reg_allowed)) {
697 asmparser_message(This, "Line %u: Destination register %s not supported in VS 3.0\n",
698 This->line_no,
699 debug_print_dstreg(dst, ST_VERTEX));
700 set_parse_status(This, PARSE_ERR);
702 check_ps_dstmod(This, instr->dstmod);
703 check_shift_dstmod(This, instr->shift);
704 memcpy(&instr->dst, dst, sizeof(*dst));
705 instr->has_dst = TRUE;
708 static void asmparser_dstreg_ps_2(struct asm_parser *This,
709 struct instruction *instr,
710 const struct shader_reg *dst) {
711 struct shader_reg reg;
713 if(!check_reg_type(dst, ps_2_0_reg_allowed)) {
714 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.0\n",
715 This->line_no,
716 debug_print_dstreg(dst, ST_PIXEL));
717 set_parse_status(This, PARSE_ERR);
719 check_shift_dstmod(This, instr->shift);
720 reg = map_oldps_register(dst, TRUE);
721 memcpy(&instr->dst, &reg, sizeof(reg));
722 instr->has_dst = TRUE;
725 static void asmparser_dstreg_ps_2_x(struct asm_parser *This,
726 struct instruction *instr,
727 const struct shader_reg *dst) {
728 struct shader_reg reg;
730 if(!check_reg_type(dst, ps_2_x_reg_allowed)) {
731 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.x\n",
732 This->line_no,
733 debug_print_dstreg(dst, ST_PIXEL));
734 set_parse_status(This, PARSE_ERR);
736 check_shift_dstmod(This, instr->shift);
737 reg = map_oldps_register(dst, TRUE);
738 memcpy(&instr->dst, &reg, sizeof(reg));
739 instr->has_dst = TRUE;
742 static void asmparser_dstreg_ps_3(struct asm_parser *This,
743 struct instruction *instr,
744 const struct shader_reg *dst) {
745 if(!check_reg_type(dst, ps_3_reg_allowed)) {
746 asmparser_message(This, "Line %u: Destination register %s not supported in PS 3.0\n",
747 This->line_no,
748 debug_print_dstreg(dst, ST_PIXEL));
749 set_parse_status(This, PARSE_ERR);
751 check_shift_dstmod(This, instr->shift);
752 memcpy(&instr->dst, dst, sizeof(*dst));
753 instr->has_dst = TRUE;
756 static void asmparser_predicate_supported(struct asm_parser *This,
757 const struct shader_reg *predicate) {
758 /* this sets the predicate of the last instruction added to the shader */
759 if(!This->shader) return;
760 if(This->shader->num_instrs == 0) ERR("Predicate without an instruction\n");
761 This->shader->instr[This->shader->num_instrs - 1]->has_predicate = TRUE;
762 memcpy(&This->shader->instr[This->shader->num_instrs - 1]->predicate, predicate, sizeof(*predicate));
765 static void asmparser_predicate_unsupported(struct asm_parser *This,
766 const struct shader_reg *predicate) {
767 asmparser_message(This, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This->line_no);
768 set_parse_status(This, PARSE_ERR);
771 static void asmparser_coissue_unsupported(struct asm_parser *This) {
772 asmparser_message(This, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This->line_no);
773 set_parse_status(This, PARSE_ERR);
776 static const struct asmparser_backend parser_vs_1 = {
777 asmparser_constF,
778 asmparser_constI,
779 asmparser_constB,
781 asmparser_dstreg_vs_1,
782 asmparser_srcreg_vs_1,
784 asmparser_predicate_unsupported,
785 asmparser_coissue_unsupported,
787 asmparser_dcl_output,
788 asmparser_dcl_input,
789 asmparser_dcl_sampler_unsupported,
791 asmparser_end,
793 asmparser_instr,
796 static const struct asmparser_backend parser_vs_2 = {
797 asmparser_constF,
798 asmparser_constI,
799 asmparser_constB,
801 asmparser_dstreg_vs_2,
802 asmparser_srcreg_vs_2,
804 asmparser_predicate_supported,
805 asmparser_coissue_unsupported,
807 asmparser_dcl_output,
808 asmparser_dcl_input,
809 asmparser_dcl_sampler_unsupported,
811 asmparser_end,
813 asmparser_instr,
816 static const struct asmparser_backend parser_vs_3 = {
817 asmparser_constF,
818 asmparser_constI,
819 asmparser_constB,
821 asmparser_dstreg_vs_3,
822 asmparser_srcreg_vs_3,
824 asmparser_predicate_supported,
825 asmparser_coissue_unsupported,
827 asmparser_dcl_output,
828 asmparser_dcl_input,
829 asmparser_dcl_sampler,
831 asmparser_end,
833 asmparser_instr,
836 static const struct asmparser_backend parser_ps_2 = {
837 asmparser_constF,
838 asmparser_constI,
839 asmparser_constB,
841 asmparser_dstreg_ps_2,
842 asmparser_srcreg_ps_2,
844 asmparser_predicate_unsupported,
845 asmparser_coissue_unsupported,
847 asmparser_dcl_output,
848 asmparser_dcl_input_ps_2,
849 asmparser_dcl_sampler,
851 asmparser_end,
853 asmparser_instr,
856 static const struct asmparser_backend parser_ps_2_x = {
857 asmparser_constF,
858 asmparser_constI,
859 asmparser_constB,
861 asmparser_dstreg_ps_2_x,
862 asmparser_srcreg_ps_2_x,
864 asmparser_predicate_supported,
865 asmparser_coissue_unsupported,
867 asmparser_dcl_output,
868 asmparser_dcl_input_ps_2,
869 asmparser_dcl_sampler,
871 asmparser_end,
873 asmparser_instr,
876 static const struct asmparser_backend parser_ps_3 = {
877 asmparser_constF,
878 asmparser_constI,
879 asmparser_constB,
881 asmparser_dstreg_ps_3,
882 asmparser_srcreg_ps_3,
884 asmparser_predicate_supported,
885 asmparser_coissue_unsupported,
887 asmparser_dcl_output,
888 asmparser_dcl_input,
889 asmparser_dcl_sampler,
891 asmparser_end,
893 asmparser_instr,
896 static void gen_oldvs_output(struct bwriter_shader *shader) {
897 record_declaration(shader, BWRITERDECLUSAGE_POSITION, 0, 0, TRUE, OPOS_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
898 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, TRUE, OT0_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
899 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, TRUE, OT1_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
900 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, TRUE, OT2_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
901 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, TRUE, OT3_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
902 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, TRUE, OT4_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
903 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, TRUE, OT5_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
904 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, TRUE, OT6_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
905 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, TRUE, OT7_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
906 record_declaration(shader, BWRITERDECLUSAGE_FOG, 0, 0, TRUE, OFOG_REG, OFOG_WRITEMASK, TRUE);
907 record_declaration(shader, BWRITERDECLUSAGE_PSIZE, 0, 0, TRUE, OPTS_REG, OPTS_WRITEMASK, TRUE);
908 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, TRUE, OD0_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
909 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, TRUE, OD1_REG, BWRITERSP_WRITEMASK_ALL, TRUE);
912 static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) {
913 switch(texcoords) {
914 case 8: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, FALSE, T7_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
915 case 7: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, FALSE, T6_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
916 case 6: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, FALSE, T5_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
917 case 5: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, FALSE, T4_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
918 case 4: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, FALSE, T3_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
919 case 3: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, FALSE, T2_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
920 case 2: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, FALSE, T1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
921 case 1: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, FALSE, T0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
923 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, FALSE, C0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
924 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE);
927 void create_vs10_parser(struct asm_parser *ret) {
928 TRACE_(parsed_shader)("vs_1_0\n");
930 ret->shader = asm_alloc(sizeof(*ret->shader));
931 if(!ret->shader) {
932 ERR("Failed to allocate memory for the shader\n");
933 set_parse_status(ret, PARSE_ERR);
934 return;
937 ret->shader->type = ST_VERTEX;
938 ret->shader->version = BWRITERVS_VERSION(1, 0);
939 ret->funcs = &parser_vs_1;
940 gen_oldvs_output(ret->shader);
943 void create_vs11_parser(struct asm_parser *ret) {
944 TRACE_(parsed_shader)("vs_1_1\n");
946 ret->shader = asm_alloc(sizeof(*ret->shader));
947 if(!ret->shader) {
948 ERR("Failed to allocate memory for the shader\n");
949 set_parse_status(ret, PARSE_ERR);
950 return;
953 ret->shader->type = ST_VERTEX;
954 ret->shader->version = BWRITERVS_VERSION(1, 1);
955 ret->funcs = &parser_vs_1;
956 gen_oldvs_output(ret->shader);
959 void create_vs20_parser(struct asm_parser *ret) {
960 TRACE_(parsed_shader)("vs_2_0\n");
962 ret->shader = asm_alloc(sizeof(*ret->shader));
963 if(!ret->shader) {
964 ERR("Failed to allocate memory for the shader\n");
965 set_parse_status(ret, PARSE_ERR);
966 return;
969 ret->shader->type = ST_VERTEX;
970 ret->shader->version = BWRITERVS_VERSION(2, 0);
971 ret->funcs = &parser_vs_2;
972 gen_oldvs_output(ret->shader);
975 void create_vs2x_parser(struct asm_parser *ret) {
976 TRACE_(parsed_shader)("vs_2_x\n");
978 ret->shader = asm_alloc(sizeof(*ret->shader));
979 if(!ret->shader) {
980 ERR("Failed to allocate memory for the shader\n");
981 set_parse_status(ret, PARSE_ERR);
982 return;
985 ret->shader->type = ST_VERTEX;
986 ret->shader->version = BWRITERVS_VERSION(2, 1);
987 ret->funcs = &parser_vs_2;
988 gen_oldvs_output(ret->shader);
991 void create_vs30_parser(struct asm_parser *ret) {
992 TRACE_(parsed_shader)("vs_3_0\n");
994 ret->shader = asm_alloc(sizeof(*ret->shader));
995 if(!ret->shader) {
996 ERR("Failed to allocate memory for the shader\n");
997 set_parse_status(ret, PARSE_ERR);
998 return;
1001 ret->shader->type = ST_VERTEX;
1002 ret->shader->version = BWRITERVS_VERSION(3, 0);
1003 ret->funcs = &parser_vs_3;
1006 void create_ps20_parser(struct asm_parser *ret) {
1007 TRACE_(parsed_shader)("ps_2_0\n");
1009 ret->shader = asm_alloc(sizeof(*ret->shader));
1010 if(!ret->shader) {
1011 ERR("Failed to allocate memory for the shader\n");
1012 set_parse_status(ret, PARSE_ERR);
1013 return;
1016 ret->shader->type = ST_PIXEL;
1017 ret->shader->version = BWRITERPS_VERSION(2, 0);
1018 ret->funcs = &parser_ps_2;
1019 gen_oldps_input(ret->shader, 8);
1022 void create_ps2x_parser(struct asm_parser *ret) {
1023 TRACE_(parsed_shader)("ps_2_x\n");
1025 ret->shader = asm_alloc(sizeof(*ret->shader));
1026 if(!ret->shader) {
1027 ERR("Failed to allocate memory for the shader\n");
1028 set_parse_status(ret, PARSE_ERR);
1029 return;
1032 ret->shader->type = ST_PIXEL;
1033 ret->shader->version = BWRITERPS_VERSION(2, 1);
1034 ret->funcs = &parser_ps_2_x;
1035 gen_oldps_input(ret->shader, 8);
1038 void create_ps30_parser(struct asm_parser *ret) {
1039 TRACE_(parsed_shader)("ps_3_0\n");
1041 ret->shader = asm_alloc(sizeof(*ret->shader));
1042 if(!ret->shader) {
1043 ERR("Failed to allocate memory for the shader\n");
1044 set_parse_status(ret, PARSE_ERR);
1045 return;
1048 ret->shader->type = ST_PIXEL;
1049 ret->shader->version = BWRITERPS_VERSION(3, 0);
1050 ret->funcs = &parser_ps_3;