1 /* 2 * Direct3D asm shader parser 3 * 4 * Copyright 2008 Stefan Dösinger 5 * Copyright 2009 Matteo Bruni 6 * 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. 11 * 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. 16 * 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 20 * 21 */ 22 23 #include "wine/debug.h" 24 25 #include "d3dcompiler_private.h" 26 27 WINE_DEFAULT_DEBUG_CHANNEL(asmshader); 28 WINE_DECLARE_DEBUG_CHANNEL(parsed_shader); 29 30 31 /* How to map vs 1.0 and 2.0 varyings to 3.0 ones 32 * oTx is mapped to ox, which happens to be an 33 * identical mapping since BWRITERSPR_TEXCRDOUT == BWRITERSPR_OUTPUT 34 * oPos, oFog and point size are mapped to general output regs as well. 35 * the vs 1.x and 2.x parser functions add varying declarations 36 * to the shader, and the 1.x and 2.x output functions check those varyings 37 */ 38 #define OT0_REG 0 39 #define OT1_REG 1 40 #define OT2_REG 2 41 #define OT3_REG 3 42 #define OT4_REG 4 43 #define OT5_REG 5 44 #define OT6_REG 6 45 #define OT7_REG 7 46 #define OPOS_REG 8 47 #define OFOG_REG 9 48 #define OFOG_WRITEMASK BWRITERSP_WRITEMASK_0 49 #define OPTS_REG 9 50 #define OPTS_WRITEMASK BWRITERSP_WRITEMASK_1 51 #define OD0_REG 10 52 #define OD1_REG 11 53 54 /* Input color registers 0-1 are identically mapped */ 55 #define C0_VARYING 0 56 #define C1_VARYING 1 57 #define T0_VARYING 2 58 #define T1_VARYING 3 59 #define T2_VARYING 4 60 #define T3_VARYING 5 61 #define T4_VARYING 6 62 #define T5_VARYING 7 63 #define T6_VARYING 8 64 #define T7_VARYING 9 65 66 /**************************************************************** 67 * Common(non-version specific) shader parser control code * 68 ****************************************************************/ 69 70 static void asmparser_end(struct asm_parser *This) { 71 TRACE("Finalizing shader\n"); 72 } 73 74 static void asmparser_constF(struct asm_parser *This, DWORD reg, float x, float y, float z, float w) { 75 if(!This->shader) return; 76 TRACE("Adding float constant %u at pos %u\n", reg, This->shader->num_cf); 77 TRACE_(parsed_shader)("def c%u, %f, %f, %f, %f\n", reg, x, y, z, w); 78 if(!add_constF(This->shader, reg, x, y, z, w)) { 79 ERR("Out of memory\n"); 80 set_parse_status(&This->status, PARSE_ERR); 81 } 82 } 83 84 static void asmparser_constB(struct asm_parser *This, DWORD reg, BOOL x) { 85 if(!This->shader) return; 86 TRACE("Adding boolean constant %u at pos %u\n", reg, This->shader->num_cb); 87 TRACE_(parsed_shader)("def b%u, %s\n", reg, x ? "true" : "false"); 88 if(!add_constB(This->shader, reg, x)) { 89 ERR("Out of memory\n"); 90 set_parse_status(&This->status, PARSE_ERR); 91 } 92 } 93 94 static void asmparser_constI(struct asm_parser *This, DWORD reg, INT x, INT y, INT z, INT w) { 95 if(!This->shader) return; 96 TRACE("Adding integer constant %u at pos %u\n", reg, This->shader->num_ci); 97 TRACE_(parsed_shader)("def i%u, %d, %d, %d, %d\n", reg, x, y, z, w); 98 if(!add_constI(This->shader, reg, x, y, z, w)) { 99 ERR("Out of memory\n"); 100 set_parse_status(&This->status, PARSE_ERR); 101 } 102 } 103 104 static void asmparser_dcl_output(struct asm_parser *This, DWORD usage, DWORD num, 105 const struct shader_reg *reg) { 106 if(!This->shader) return; 107 if(This->shader->type == ST_PIXEL) { 108 asmparser_message(This, "Line %u: Output register declared in a pixel shader\n", This->line_no); 109 set_parse_status(&This->status, PARSE_ERR); 110 } 111 if(!record_declaration(This->shader, usage, num, 0, TRUE, reg->regnum, reg->u.writemask, FALSE)) { 112 ERR("Out of memory\n"); 113 set_parse_status(&This->status, PARSE_ERR); 114 } 115 } 116 117 static void asmparser_dcl_output_unsupported(struct asm_parser *This, DWORD usage, DWORD num, 118 const struct shader_reg *reg) { 119 asmparser_message(This, "Line %u: Output declaration unsupported in this shader version\n", This->line_no); 120 set_parse_status(&This->status, PARSE_ERR); 121 } 122 123 static void asmparser_dcl_input(struct asm_parser *This, DWORD usage, DWORD num, 124 DWORD mod, const struct shader_reg *reg) { 125 struct instruction instr; 126 127 if(!This->shader) return; 128 if(mod != 0 && 129 (This->shader->version != BWRITERPS_VERSION(3, 0) || 130 (mod != BWRITERSPDM_MSAMPCENTROID && 131 mod != BWRITERSPDM_PARTIALPRECISION))) { 132 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no); 133 set_parse_status(&This->status, PARSE_ERR); 134 return; 135 } 136 137 /* Check register type and modifiers */ 138 instr.dstmod = mod; 139 instr.shift = 0; 140 This->funcs->dstreg(This, &instr, reg); 141 142 if(!record_declaration(This->shader, usage, num, mod, FALSE, reg->regnum, reg->u.writemask, FALSE)) { 143 ERR("Out of memory\n"); 144 set_parse_status(&This->status, PARSE_ERR); 145 } 146 } 147 148 static void asmparser_dcl_input_ps_2(struct asm_parser *This, DWORD usage, DWORD num, 149 DWORD mod, const struct shader_reg *reg) { 150 struct instruction instr; 151 152 if(!This->shader) return; 153 instr.dstmod = mod; 154 instr.shift = 0; 155 This->funcs->dstreg(This, &instr, reg); 156 if(!record_declaration(This->shader, usage, num, mod, FALSE, instr.dst.regnum, instr.dst.u.writemask, FALSE)) { 157 ERR("Out of memory\n"); 158 set_parse_status(&This->status, PARSE_ERR); 159 } 160 } 161 162 static void asmparser_dcl_input_unsupported(struct asm_parser *This, 163 DWORD usage, DWORD num, DWORD mod, const struct shader_reg *reg) 164 { 165 asmparser_message(This, "Line %u: Input declaration unsupported in this shader version\n", This->line_no); 166 set_parse_status(&This->status, PARSE_ERR); 167 } 168 169 static void asmparser_dcl_sampler(struct asm_parser *This, DWORD samptype, 170 DWORD mod, DWORD regnum, 171 unsigned int line_no) { 172 if(!This->shader) return; 173 if(mod != 0 && 174 (This->shader->version != BWRITERPS_VERSION(3, 0) || 175 (mod != BWRITERSPDM_MSAMPCENTROID && 176 mod != BWRITERSPDM_PARTIALPRECISION))) { 177 asmparser_message(This, "Line %u: Unsupported modifier in dcl instruction\n", This->line_no); 178 set_parse_status(&This->status, PARSE_ERR); 179 return; 180 } 181 if(!record_sampler(This->shader, samptype, mod, regnum)) { 182 ERR("Out of memory\n"); 183 set_parse_status(&This->status, PARSE_ERR); 184 } 185 } 186 187 static void asmparser_dcl_sampler_unsupported(struct asm_parser *This, 188 DWORD samptype, DWORD mod, DWORD regnum, unsigned int line_no) 189 { 190 asmparser_message(This, "Line %u: Sampler declaration unsupported in this shader version\n", This->line_no); 191 set_parse_status(&This->status, PARSE_ERR); 192 } 193 194 static void asmparser_sincos(struct asm_parser *This, DWORD mod, DWORD shift, 195 const struct shader_reg *dst, 196 const struct src_regs *srcs) { 197 struct instruction *instr; 198 199 if(!srcs || srcs->count != 3) { 200 asmparser_message(This, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This->line_no); 201 set_parse_status(&This->status, PARSE_ERR); 202 return; 203 } 204 205 instr = alloc_instr(3); 206 if(!instr) { 207 ERR("Error allocating memory for the instruction\n"); 208 set_parse_status(&This->status, PARSE_ERR); 209 return; 210 } 211 212 instr->opcode = BWRITERSIO_SINCOS; 213 instr->dstmod = mod; 214 instr->shift = shift; 215 instr->comptype = 0; 216 217 This->funcs->dstreg(This, instr, dst); 218 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]); 219 This->funcs->srcreg(This, instr, 1, &srcs->reg[1]); 220 This->funcs->srcreg(This, instr, 2, &srcs->reg[2]); 221 222 if(!add_instruction(This->shader, instr)) { 223 ERR("Out of memory\n"); 224 set_parse_status(&This->status, PARSE_ERR); 225 } 226 } 227 228 static struct shader_reg map_oldps_register(const struct shader_reg *reg, BOOL tex_varying) { 229 struct shader_reg ret; 230 switch(reg->type) { 231 case BWRITERSPR_TEXTURE: 232 if(tex_varying) { 233 ret = *reg; 234 ret.type = BWRITERSPR_INPUT; 235 switch(reg->regnum) { 236 case 0: ret.regnum = T0_VARYING; break; 237 case 1: ret.regnum = T1_VARYING; break; 238 case 2: ret.regnum = T2_VARYING; break; 239 case 3: ret.regnum = T3_VARYING; break; 240 case 4: ret.regnum = T4_VARYING; break; 241 case 5: ret.regnum = T5_VARYING; break; 242 case 6: ret.regnum = T6_VARYING; break; 243 case 7: ret.regnum = T7_VARYING; break; 244 default: 245 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum); 246 return *reg; 247 } 248 return ret; 249 } else { 250 ret = *reg; 251 ret.type = BWRITERSPR_TEMP; 252 switch(reg->regnum) { 253 case 0: ret.regnum = T0_REG; break; 254 case 1: ret.regnum = T1_REG; break; 255 case 2: ret.regnum = T2_REG; break; 256 case 3: ret.regnum = T3_REG; break; 257 default: 258 FIXME("Unexpected TEXTURE register t%u\n", reg->regnum); 259 return *reg; 260 } 261 return ret; 262 } 263 264 /* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings 265 to 3.0 ones */ 266 267 default: return *reg; 268 } 269 } 270 271 static void asmparser_texcoord(struct asm_parser *This, DWORD mod, DWORD shift, 272 const struct shader_reg *dst, 273 const struct src_regs *srcs) { 274 struct instruction *instr; 275 276 if(srcs) { 277 asmparser_message(This, "Line %u: Source registers in texcoord instruction\n", This->line_no); 278 set_parse_status(&This->status, PARSE_ERR); 279 return; 280 } 281 282 instr = alloc_instr(1); 283 if(!instr) { 284 ERR("Error allocating memory for the instruction\n"); 285 set_parse_status(&This->status, PARSE_ERR); 286 return; 287 } 288 289 /* texcoord copies the texture coord data into a temporary register-like 290 * readable form. In newer shader models this equals a MOV from v0 to r0, 291 * record it as this. 292 */ 293 instr->opcode = BWRITERSIO_MOV; 294 instr->dstmod = mod | BWRITERSPDM_SATURATE; /* texcoord clamps to [0;1] */ 295 instr->shift = shift; 296 instr->comptype = 0; 297 298 This->funcs->dstreg(This, instr, dst); 299 /* The src reg needs special care */ 300 instr->src[0] = map_oldps_register(dst, TRUE); 301 302 if(!add_instruction(This->shader, instr)) { 303 ERR("Out of memory\n"); 304 set_parse_status(&This->status, PARSE_ERR); 305 } 306 } 307 308 static void asmparser_texcrd(struct asm_parser *This, DWORD mod, DWORD shift, 309 const struct shader_reg *dst, 310 const struct src_regs *srcs) { 311 struct instruction *instr; 312 313 if(!srcs || srcs->count != 1) { 314 asmparser_message(This, "Line %u: Wrong number of source registers in texcrd instruction\n", This->line_no); 315 set_parse_status(&This->status, PARSE_ERR); 316 return; 317 } 318 319 instr = alloc_instr(1); 320 if(!instr) { 321 ERR("Error allocating memory for the instruction\n"); 322 set_parse_status(&This->status, PARSE_ERR); 323 return; 324 } 325 326 /* The job of texcrd is done by mov in later shader versions */ 327 instr->opcode = BWRITERSIO_MOV; 328 instr->dstmod = mod; 329 instr->shift = shift; 330 instr->comptype = 0; 331 332 This->funcs->dstreg(This, instr, dst); 333 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]); 334 335 if(!add_instruction(This->shader, instr)) { 336 ERR("Out of memory\n"); 337 set_parse_status(&This->status, PARSE_ERR); 338 } 339 } 340 341 static void asmparser_texkill(struct asm_parser *This, 342 const struct shader_reg *dst) { 343 struct instruction *instr = alloc_instr(0); 344 345 if(!instr) { 346 ERR("Error allocating memory for the instruction\n"); 347 set_parse_status(&This->status, PARSE_ERR); 348 return; 349 } 350 351 instr->opcode = BWRITERSIO_TEXKILL; 352 instr->dstmod = 0; 353 instr->shift = 0; 354 instr->comptype = 0; 355 356 /* Do not run the dst register through the normal 357 * register conversion. If used with ps_1_0 to ps_1_3 358 * the texture coordinate from that register is used, 359 * not the temporary register value. In ps_1_4 and 360 * ps_2_0 t0 is always a varying and temporaries can 361 * be used with texkill. 362 */ 363 instr->dst = map_oldps_register(dst, TRUE); 364 instr->has_dst = TRUE; 365 366 if(!add_instruction(This->shader, instr)) { 367 ERR("Out of memory\n"); 368 set_parse_status(&This->status, PARSE_ERR); 369 } 370 } 371 372 static void asmparser_texhelper(struct asm_parser *This, DWORD mod, DWORD shift, 373 const struct shader_reg *dst, 374 const struct shader_reg *src0) { 375 struct instruction *instr = alloc_instr(2); 376 377 if(!instr) { 378 ERR("Error allocating memory for the instruction\n"); 379 set_parse_status(&This->status, PARSE_ERR); 380 return; 381 } 382 383 instr->opcode = BWRITERSIO_TEX; 384 instr->dstmod = mod; 385 instr->shift = shift; 386 instr->comptype = 0; 387 /* The dest register can be mapped normally to a temporary register */ 388 This->funcs->dstreg(This, instr, dst); 389 /* Use the src passed as parameter by the specific instruction handler */ 390 instr->src[0] = *src0; 391 392 /* The 2nd source register is the sampler register with the 393 * destination's regnum 394 */ 395 ZeroMemory(&instr->src[1], sizeof(instr->src[1])); 396 instr->src[1].type = BWRITERSPR_SAMPLER; 397 instr->src[1].regnum = dst->regnum; 398 instr->src[1].u.swizzle = BWRITERVS_NOSWIZZLE; 399 instr->src[1].srcmod = BWRITERSPSM_NONE; 400 instr->src[1].rel_reg = NULL; 401 402 if(!add_instruction(This->shader, instr)) { 403 ERR("Out of memory\n"); 404 set_parse_status(&This->status, PARSE_ERR); 405 } 406 } 407 408 static void asmparser_tex(struct asm_parser *This, DWORD mod, DWORD shift, 409 const struct shader_reg *dst) { 410 struct shader_reg src; 411 412 /* The first source register is the varying containing the coordinate */ 413 src = map_oldps_register(dst, TRUE); 414 asmparser_texhelper(This, mod, shift, dst, &src); 415 } 416 417 static void asmparser_texld14(struct asm_parser *This, DWORD mod, DWORD shift, 418 const struct shader_reg *dst, 419 const struct src_regs *srcs) { 420 struct instruction *instr; 421 422 if(!srcs || srcs->count != 1) { 423 asmparser_message(This, "Line %u: texld (PS 1.4) has a wrong number of source registers\n", This->line_no); 424 set_parse_status(&This->status, PARSE_ERR); 425 return; 426 } 427 428 instr = alloc_instr(2); 429 if(!instr) { 430 ERR("Error allocating memory for the instruction\n"); 431 set_parse_status(&This->status, PARSE_ERR); 432 return; 433 } 434 435 /* This code is recording a texld instruction, not tex. However, 436 * texld borrows the opcode of tex 437 */ 438 instr->opcode = BWRITERSIO_TEX; 439 instr->dstmod = mod; 440 instr->shift = shift; 441 instr->comptype = 0; 442 443 This->funcs->dstreg(This, instr, dst); 444 This->funcs->srcreg(This, instr, 0, &srcs->reg[0]); 445 446 /* The 2nd source register is the sampler register with the 447 * destination's regnum 448 */ 449 ZeroMemory(&instr->src[1], sizeof(instr->src[1])); 450 instr->src[1].type = BWRITERSPR_SAMPLER; 451 instr->src[1].regnum = dst->regnum; 452 instr->src[1].u.swizzle = BWRITERVS_NOSWIZZLE; 453 instr->src[1].srcmod = BWRITERSPSM_NONE; 454 instr->src[1].rel_reg = NULL; 455 456 if(!add_instruction(This->shader, instr)) { 457 ERR("Out of memory\n"); 458 set_parse_status(&This->status, PARSE_ERR); 459 } 460 } 461 462 static void asmparser_texreg2ar(struct asm_parser *This, DWORD mod, DWORD shift, 463 const struct shader_reg *dst, 464 const struct shader_reg *src0) { 465 struct shader_reg src; 466 467 src = map_oldps_register(src0, FALSE); 468 /* Supply the correct swizzle */ 469 src.u.swizzle = BWRITERVS_X_W | BWRITERVS_Y_X | BWRITERVS_Z_X | BWRITERVS_W_X; 470 asmparser_texhelper(This, mod, shift, dst, &src); 471 } 472 473 static void asmparser_texreg2gb(struct asm_parser *This, DWORD mod, DWORD shift, 474 const struct shader_reg *dst, 475 const struct shader_reg *src0) { 476 struct shader_reg src; 477 478 src = map_oldps_register(src0, FALSE); 479 /* Supply the correct swizzle */ 480 src.u.swizzle = BWRITERVS_X_Y | BWRITERVS_Y_Z | BWRITERVS_Z_Z | BWRITERVS_W_Z; 481 asmparser_texhelper(This, mod, shift, dst, &src); 482 } 483 484 static void asmparser_texreg2rgb(struct asm_parser *This, DWORD mod, DWORD shift, 485 const struct shader_reg *dst, 486 const struct shader_reg *src0) { 487 struct shader_reg src; 488 489 src = map_oldps_register(src0, FALSE); 490 /* Supply the correct swizzle */ 491 src.u.swizzle = BWRITERVS_X_X | BWRITERVS_Y_Y | BWRITERVS_Z_Z | BWRITERVS_W_Z; 492 asmparser_texhelper(This, mod, shift, dst, &src); 493 } 494 495 /* Complex pixel shader 1.3 instructions like texm3x3tex are tricky - the 496 * bytecode writer works instruction by instruction, so we can't properly 497 * convert these from/to equivalent ps_3_0 instructions. Then simply keep using 498 * the ps_1_3 opcodes and just adapt the registers in the common fashion (i.e. 499 * go through asmparser_instr). 500 */ 501 502 static void asmparser_instr(struct asm_parser *This, DWORD opcode, DWORD mod, DWORD shift, 503 enum bwriter_comparison_type comp, const struct shader_reg *dst, 504 const struct src_regs *srcs, int expectednsrcs) 505 { 506 struct instruction *instr; 507 unsigned int i; 508 BOOL firstreg = TRUE; 509 unsigned int src_count = srcs ? srcs->count : 0; 510 511 if(!This->shader) return; 512 513 TRACE_(parsed_shader)("%s%s%s%s ", debug_print_opcode(opcode), 514 debug_print_dstmod(mod), 515 debug_print_shift(shift), 516 debug_print_comp(comp)); 517 if(dst) { 518 TRACE_(parsed_shader)("%s", debug_print_dstreg(dst)); 519 firstreg = FALSE; 520 } 521 for(i = 0; i < src_count; i++) { 522 if(!firstreg) TRACE_(parsed_shader)(", "); 523 else firstreg = FALSE; 524 TRACE_(parsed_shader)("%s", debug_print_srcreg(&srcs->reg[i])); 525 } 526 TRACE_(parsed_shader)("\n"); 527 528 /* Check for instructions with different syntaxes in different shader versions */ 529 switch(opcode) { 530 case BWRITERSIO_SINCOS: 531 /* The syntax changes between vs 2 and the other shader versions */ 532 if(This->shader->version == BWRITERVS_VERSION(2, 0) || 533 This->shader->version == BWRITERVS_VERSION(2, 1)) { 534 asmparser_sincos(This, mod, shift, dst, srcs); 535 return; 536 } 537 /* Use the default handling */ 538 break; 539 case BWRITERSIO_TEXCOORD: 540 /* texcoord/texcrd are two instructions present only in PS <= 1.3 and PS 1.4 respectively */ 541 if(This->shader->version == BWRITERPS_VERSION(1, 4)) 542 asmparser_texcrd(This, mod, shift, dst, srcs); 543 else asmparser_texcoord(This, mod, shift, dst, srcs); 544 return; 545 case BWRITERSIO_TEX: 546 /* this encodes both the tex PS 1.x instruction and the 547 texld 1.4/2.0+ instruction */ 548 if(This->shader->version == BWRITERPS_VERSION(1, 0) || 549 This->shader->version == BWRITERPS_VERSION(1, 1) || 550 This->shader->version == BWRITERPS_VERSION(1, 2) || 551 This->shader->version == BWRITERPS_VERSION(1, 3)) { 552 asmparser_tex(This, mod, shift, dst); 553 return; 554 } 555 else if(This->shader->version == BWRITERPS_VERSION(1, 4)) { 556 asmparser_texld14(This, mod, shift, dst, srcs); 557 return; 558 } 559 /* else fallback to the standard behavior */ 560 break; 561 } 562 563 if(src_count != expectednsrcs) { 564 asmparser_message(This, "Line %u: Wrong number of source registers\n", This->line_no); 565 set_parse_status(&This->status, PARSE_ERR); 566 return; 567 } 568 569 /* Handle PS 1.x instructions, "regularizing" them */ 570 switch(opcode) { 571 case BWRITERSIO_TEXKILL: 572 asmparser_texkill(This, dst); 573 return; 574 case BWRITERSIO_TEXREG2AR: 575 asmparser_texreg2ar(This, mod, shift, dst, &srcs->reg[0]); 576 return; 577 case BWRITERSIO_TEXREG2GB: 578 asmparser_texreg2gb(This, mod, shift, dst, &srcs->reg[0]); 579 return; 580 case BWRITERSIO_TEXREG2RGB: 581 asmparser_texreg2rgb(This, mod, shift, dst, &srcs->reg[0]); 582 return; 583 } 584 585 instr = alloc_instr(src_count); 586 if(!instr) { 587 ERR("Error allocating memory for the instruction\n"); 588 set_parse_status(&This->status, PARSE_ERR); 589 return; 590 } 591 592 instr->opcode = opcode; 593 instr->dstmod = mod; 594 instr->shift = shift; 595 instr->comptype = comp; 596 if(dst) This->funcs->dstreg(This, instr, dst); 597 for(i = 0; i < src_count; i++) { 598 This->funcs->srcreg(This, instr, i, &srcs->reg[i]); 599 } 600 601 if(!add_instruction(This->shader, instr)) { 602 ERR("Out of memory\n"); 603 set_parse_status(&This->status, PARSE_ERR); 604 } 605 } 606 607 static struct shader_reg map_oldvs_register(const struct shader_reg *reg) { 608 struct shader_reg ret; 609 switch(reg->type) { 610 case BWRITERSPR_RASTOUT: 611 ret = *reg; 612 ret.type = BWRITERSPR_OUTPUT; 613 switch(reg->regnum) { 614 case BWRITERSRO_POSITION: 615 ret.regnum = OPOS_REG; 616 break; 617 case BWRITERSRO_FOG: 618 ret.regnum = OFOG_REG; 619 ret.u.writemask = OFOG_WRITEMASK; 620 break; 621 case BWRITERSRO_POINT_SIZE: 622 ret.regnum = OPTS_REG; 623 ret.u.writemask = OPTS_WRITEMASK; 624 break; 625 default: 626 FIXME("Unhandled RASTOUT register %u\n", reg->regnum); 627 return *reg; 628 } 629 return ret; 630 631 case BWRITERSPR_TEXCRDOUT: 632 ret = *reg; 633 ret.type = BWRITERSPR_OUTPUT; 634 switch(reg->regnum) { 635 case 0: ret.regnum = OT0_REG; break; 636 case 1: ret.regnum = OT1_REG; break; 637 case 2: ret.regnum = OT2_REG; break; 638 case 3: ret.regnum = OT3_REG; break; 639 case 4: ret.regnum = OT4_REG; break; 640 case 5: ret.regnum = OT5_REG; break; 641 case 6: ret.regnum = OT6_REG; break; 642 case 7: ret.regnum = OT7_REG; break; 643 default: 644 FIXME("Unhandled TEXCRDOUT regnum %u\n", reg->regnum); 645 return *reg; 646 } 647 return ret; 648 649 case BWRITERSPR_ATTROUT: 650 ret = *reg; 651 ret.type = BWRITERSPR_OUTPUT; 652 switch(reg->regnum) { 653 case 0: ret.regnum = OD0_REG; break; 654 case 1: ret.regnum = OD1_REG; break; 655 default: 656 FIXME("Unhandled ATTROUT regnum %u\n", reg->regnum); 657 return *reg; 658 } 659 return ret; 660 661 default: return *reg; 662 } 663 } 664 665 /* Checks for unsupported source modifiers in VS (all versions) or 666 PS 2.0 and newer */ 667 static void check_legacy_srcmod(struct asm_parser *This, DWORD srcmod) { 668 if(srcmod == BWRITERSPSM_BIAS || srcmod == BWRITERSPSM_BIASNEG || 669 srcmod == BWRITERSPSM_SIGN || srcmod == BWRITERSPSM_SIGNNEG || 670 srcmod == BWRITERSPSM_COMP || srcmod == BWRITERSPSM_X2 || 671 srcmod == BWRITERSPSM_X2NEG || srcmod == BWRITERSPSM_DZ || 672 srcmod == BWRITERSPSM_DW) { 673 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n", 674 This->line_no, 675 debug_print_srcmod(srcmod)); 676 set_parse_status(&This->status, PARSE_ERR); 677 } 678 } 679 680 static void check_abs_srcmod(struct asm_parser *This, DWORD srcmod) { 681 if(srcmod == BWRITERSPSM_ABS || srcmod == BWRITERSPSM_ABSNEG) { 682 asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n", 683 This->line_no, 684 debug_print_srcmod(srcmod)); 685 set_parse_status(&This->status, PARSE_ERR); 686 } 687 } 688 689 static void check_loop_swizzle(struct asm_parser *This, 690 const struct shader_reg *src) { 691 if((src->type == BWRITERSPR_LOOP && src->u.swizzle != BWRITERVS_NOSWIZZLE) || 692 (src->rel_reg && src->rel_reg->type == BWRITERSPR_LOOP && 693 src->rel_reg->u.swizzle != BWRITERVS_NOSWIZZLE)) { 694 asmparser_message(This, "Line %u: Swizzle not allowed on aL register\n", This->line_no); 695 set_parse_status(&This->status, PARSE_ERR); 696 } 697 } 698 699 static void check_shift_dstmod(struct asm_parser *This, DWORD shift) { 700 if(shift != 0) { 701 asmparser_message(This, "Line %u: Shift modifiers not supported in this shader version\n", 702 This->line_no); 703 set_parse_status(&This->status, PARSE_ERR); 704 } 705 } 706 707 static void check_ps_dstmod(struct asm_parser *This, DWORD dstmod) { 708 if(dstmod == BWRITERSPDM_PARTIALPRECISION || 709 dstmod == BWRITERSPDM_MSAMPCENTROID) { 710 asmparser_message(This, "Line %u: Instruction modifier %s not supported in this shader version\n", 711 This->line_no, 712 debug_print_dstmod(dstmod)); 713 set_parse_status(&This->status, PARSE_ERR); 714 } 715 } 716 717 struct allowed_reg_type { 718 DWORD type; 719 DWORD count; 720 BOOL reladdr; 721 }; 722 723 static BOOL check_reg_type(const struct shader_reg *reg, 724 const struct allowed_reg_type *allowed) { 725 unsigned int i = 0; 726 727 while(allowed[i].type != ~0U) { 728 if(reg->type == allowed[i].type) { 729 if(reg->rel_reg) { 730 if(allowed[i].reladdr) 731 return TRUE; /* The relative addressing register 732 can have a negative value, we 733 can't check the register index */ 734 return FALSE; 735 } 736 if(reg->regnum < allowed[i].count) return TRUE; 737 return FALSE; 738 } 739 i++; 740 } 741 return FALSE; 742 } 743 744 /* Native assembler doesn't do separate checks for src and dst registers */ 745 static const struct allowed_reg_type vs_1_reg_allowed[] = { 746 { BWRITERSPR_TEMP, 12, FALSE }, 747 { BWRITERSPR_INPUT, 16, FALSE }, 748 { BWRITERSPR_CONST, ~0U, TRUE }, 749 { BWRITERSPR_ADDR, 1, FALSE }, 750 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */ 751 { BWRITERSPR_ATTROUT, 2, FALSE }, 752 { BWRITERSPR_TEXCRDOUT, 8, FALSE }, 753 { ~0U, 0 } /* End tag */ 754 }; 755 756 /* struct instruction *asmparser_srcreg 757 * 758 * Records a source register in the instruction and does shader version 759 * specific checks and modifications on it 760 * 761 * Parameters: 762 * This: Shader parser instance 763 * instr: instruction to store the register in 764 * num: Number of source register 765 * src: Pointer to source the register structure. The caller can free 766 * it afterwards 767 */ 768 static void asmparser_srcreg_vs_1(struct asm_parser *This, 769 struct instruction *instr, int num, 770 const struct shader_reg *src) { 771 struct shader_reg reg; 772 773 if(!check_reg_type(src, vs_1_reg_allowed)) { 774 asmparser_message(This, "Line %u: Source register %s not supported in VS 1\n", 775 This->line_no, 776 debug_print_srcreg(src)); 777 set_parse_status(&This->status, PARSE_ERR); 778 } 779 check_legacy_srcmod(This, src->srcmod); 780 check_abs_srcmod(This, src->srcmod); 781 reg = map_oldvs_register(src); 782 instr->src[num] = reg; 783 } 784 785 static const struct allowed_reg_type vs_2_reg_allowed[] = { 786 { BWRITERSPR_TEMP, 12, FALSE }, 787 { BWRITERSPR_INPUT, 16, FALSE }, 788 { BWRITERSPR_CONST, ~0U, TRUE }, 789 { BWRITERSPR_ADDR, 1, FALSE }, 790 { BWRITERSPR_CONSTBOOL, 16, FALSE }, 791 { BWRITERSPR_CONSTINT, 16, FALSE }, 792 { BWRITERSPR_LOOP, 1, FALSE }, 793 { BWRITERSPR_LABEL, 2048, FALSE }, 794 { BWRITERSPR_PREDICATE, 1, FALSE }, 795 { BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */ 796 { BWRITERSPR_ATTROUT, 2, FALSE }, 797 { BWRITERSPR_TEXCRDOUT, 8, FALSE }, 798 { ~0U, 0 } /* End tag */ 799 }; 800 801 static void asmparser_srcreg_vs_2(struct asm_parser *This, 802 struct instruction *instr, int num, 803 const struct shader_reg *src) { 804 struct shader_reg reg; 805 806 if(!check_reg_type(src, vs_2_reg_allowed)) { 807 asmparser_message(This, "Line %u: Source register %s not supported in VS 2\n", 808 This->line_no, 809 debug_print_srcreg(src)); 810 set_parse_status(&This->status, PARSE_ERR); 811 } 812 check_loop_swizzle(This, src); 813 check_legacy_srcmod(This, src->srcmod); 814 check_abs_srcmod(This, src->srcmod); 815 reg = map_oldvs_register(src); 816 instr->src[num] = reg; 817 } 818 819 static const struct allowed_reg_type vs_3_reg_allowed[] = { 820 { BWRITERSPR_TEMP, 32, FALSE }, 821 { BWRITERSPR_INPUT, 16, TRUE }, 822 { BWRITERSPR_CONST, ~0U, TRUE }, 823 { BWRITERSPR_ADDR, 1, FALSE }, 824 { BWRITERSPR_CONSTBOOL, 16, FALSE }, 825 { BWRITERSPR_CONSTINT, 16, FALSE }, 826 { BWRITERSPR_LOOP, 1, FALSE }, 827 { BWRITERSPR_LABEL, 2048, FALSE }, 828 { BWRITERSPR_PREDICATE, 1, FALSE }, 829 { BWRITERSPR_SAMPLER, 4, FALSE }, 830 { BWRITERSPR_OUTPUT, 12, TRUE }, 831 { ~0U, 0 } /* End tag */ 832 }; 833 834 static void asmparser_srcreg_vs_3(struct asm_parser *This, 835 struct instruction *instr, int num, 836 const struct shader_reg *src) { 837 if(!check_reg_type(src, vs_3_reg_allowed)) { 838 asmparser_message(This, "Line %u: Source register %s not supported in VS 3.0\n", 839 This->line_no, 840 debug_print_srcreg(src)); 841 set_parse_status(&This->status, PARSE_ERR); 842 } 843 check_loop_swizzle(This, src); 844 check_legacy_srcmod(This, src->srcmod); 845 instr->src[num] = *src; 846 } 847 848 static const struct allowed_reg_type ps_1_0123_reg_allowed[] = { 849 { BWRITERSPR_CONST, 8, FALSE }, 850 { BWRITERSPR_TEMP, 2, FALSE }, 851 { BWRITERSPR_TEXTURE, 4, FALSE }, 852 { BWRITERSPR_INPUT, 2, FALSE }, 853 { ~0U, 0 } /* End tag */ 854 }; 855 856 static void asmparser_srcreg_ps_1_0123(struct asm_parser *This, 857 struct instruction *instr, int num, 858 const struct shader_reg *src) { 859 struct shader_reg reg; 860 861 if(!check_reg_type(src, ps_1_0123_reg_allowed)) { 862 asmparser_message(This, "Line %u: Source register %s not supported in <== PS 1.3\n", 863 This->line_no, 864 debug_print_srcreg(src)); 865 set_parse_status(&This->status, PARSE_ERR); 866 } 867 check_abs_srcmod(This, src->srcmod); 868 reg = map_oldps_register(src, FALSE); 869 instr->src[num] = reg; 870 } 871 872 static const struct allowed_reg_type ps_1_4_reg_allowed[] = { 873 { BWRITERSPR_CONST, 8, FALSE }, 874 { BWRITERSPR_TEMP, 6, FALSE }, 875 { BWRITERSPR_TEXTURE, 6, FALSE }, 876 { BWRITERSPR_INPUT, 2, FALSE }, 877 { ~0U, 0 } /* End tag */ 878 }; 879 880 static void asmparser_srcreg_ps_1_4(struct asm_parser *This, 881 struct instruction *instr, int num, 882 const struct shader_reg *src) { 883 struct shader_reg reg; 884 885 if(!check_reg_type(src, ps_1_4_reg_allowed)) { 886 asmparser_message(This, "Line %u: Source register %s not supported in PS 1.4\n", 887 This->line_no, 888 debug_print_srcreg(src)); 889 set_parse_status(&This->status, PARSE_ERR); 890 } 891 check_abs_srcmod(This, src->srcmod); 892 reg = map_oldps_register(src, TRUE); 893 instr->src[num] = reg; 894 } 895 896 static const struct allowed_reg_type ps_2_0_reg_allowed[] = { 897 { BWRITERSPR_INPUT, 2, FALSE }, 898 { BWRITERSPR_TEMP, 32, FALSE }, 899 { BWRITERSPR_CONST, 32, FALSE }, 900 { BWRITERSPR_CONSTINT, 16, FALSE }, 901 { BWRITERSPR_CONSTBOOL, 16, FALSE }, 902 { BWRITERSPR_SAMPLER, 16, FALSE }, 903 { BWRITERSPR_TEXTURE, 8, FALSE }, 904 { BWRITERSPR_COLOROUT, 4, FALSE }, 905 { BWRITERSPR_DEPTHOUT, 1, FALSE }, 906 { ~0U, 0 } /* End tag */ 907 }; 908 909 static void asmparser_srcreg_ps_2(struct asm_parser *This, 910 struct instruction *instr, int num, 911 const struct shader_reg *src) { 912 struct shader_reg reg; 913 914 if(!check_reg_type(src, ps_2_0_reg_allowed)) { 915 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.0\n", 916 This->line_no, 917 debug_print_srcreg(src)); 918 set_parse_status(&This->status, PARSE_ERR); 919 } 920 check_legacy_srcmod(This, src->srcmod); 921 check_abs_srcmod(This, src->srcmod); 922 reg = map_oldps_register(src, TRUE); 923 instr->src[num] = reg; 924 } 925 926 static const struct allowed_reg_type ps_2_x_reg_allowed[] = { 927 { BWRITERSPR_INPUT, 2, FALSE }, 928 { BWRITERSPR_TEMP, 32, FALSE }, 929 { BWRITERSPR_CONST, 32, FALSE }, 930 { BWRITERSPR_CONSTINT, 16, FALSE }, 931 { BWRITERSPR_CONSTBOOL, 16, FALSE }, 932 { BWRITERSPR_PREDICATE, 1, FALSE }, 933 { BWRITERSPR_SAMPLER, 16, FALSE }, 934 { BWRITERSPR_TEXTURE, 8, FALSE }, 935 { BWRITERSPR_LABEL, 2048, FALSE }, 936 { BWRITERSPR_COLOROUT, 4, FALSE }, 937 { BWRITERSPR_DEPTHOUT, 1, FALSE }, 938 { ~0U, 0 } /* End tag */ 939 }; 940 941 static void asmparser_srcreg_ps_2_x(struct asm_parser *This, 942 struct instruction *instr, int num, 943 const struct shader_reg *src) { 944 struct shader_reg reg; 945 946 if(!check_reg_type(src, ps_2_x_reg_allowed)) { 947 asmparser_message(This, "Line %u: Source register %s not supported in PS 2.x\n", 948 This->line_no, 949 debug_print_srcreg(src)); 950 set_parse_status(&This->status, PARSE_ERR); 951 } 952 check_legacy_srcmod(This, src->srcmod); 953 check_abs_srcmod(This, src->srcmod); 954 reg = map_oldps_register(src, TRUE); 955 instr->src[num] = reg; 956 } 957 958 static const struct allowed_reg_type ps_3_reg_allowed[] = { 959 { BWRITERSPR_INPUT, 10, TRUE }, 960 { BWRITERSPR_TEMP, 32, FALSE }, 961 { BWRITERSPR_CONST, 224, FALSE }, 962 { BWRITERSPR_CONSTINT, 16, FALSE }, 963 { BWRITERSPR_CONSTBOOL, 16, FALSE }, 964 { BWRITERSPR_PREDICATE, 1, FALSE }, 965 { BWRITERSPR_SAMPLER, 16, FALSE }, 966 { BWRITERSPR_MISCTYPE, 2, FALSE }, /* vPos and vFace */ 967 { BWRITERSPR_LOOP, 1, FALSE }, 968 { BWRITERSPR_LABEL, 2048, FALSE }, 969 { BWRITERSPR_COLOROUT, 4, FALSE }, 970 { BWRITERSPR_DEPTHOUT, 1, FALSE }, 971 { ~0U, 0 } /* End tag */ 972 }; 973 974 static void asmparser_srcreg_ps_3(struct asm_parser *This, 975 struct instruction *instr, int num, 976 const struct shader_reg *src) { 977 if(!check_reg_type(src, ps_3_reg_allowed)) { 978 asmparser_message(This, "Line %u: Source register %s not supported in PS 3.0\n", 979 This->line_no, 980 debug_print_srcreg(src)); 981 set_parse_status(&This->status, PARSE_ERR); 982 } 983 check_loop_swizzle(This, src); 984 check_legacy_srcmod(This, src->srcmod); 985 instr->src[num] = *src; 986 } 987 988 static void asmparser_dstreg_vs_1(struct asm_parser *This, 989 struct instruction *instr, 990 const struct shader_reg *dst) { 991 struct shader_reg reg; 992 993 if(!check_reg_type(dst, vs_1_reg_allowed)) { 994 asmparser_message(This, "Line %u: Destination register %s not supported in VS 1\n", 995 This->line_no, 996 debug_print_dstreg(dst)); 997 set_parse_status(&This->status, PARSE_ERR); 998 } 999 check_ps_dstmod(This, instr->dstmod); 1000 check_shift_dstmod(This, instr->shift); 1001 reg = map_oldvs_register(dst); 1002 instr->dst = reg; 1003 instr->has_dst = TRUE; 1004 } 1005 1006 static void asmparser_dstreg_vs_2(struct asm_parser *This, 1007 struct instruction *instr, 1008 const struct shader_reg *dst) { 1009 struct shader_reg reg; 1010 1011 if(!check_reg_type(dst, vs_2_reg_allowed)) { 1012 asmparser_message(This, "Line %u: Destination register %s not supported in VS 2.0\n", 1013 This->line_no, 1014 debug_print_dstreg(dst)); 1015 set_parse_status(&This->status, PARSE_ERR); 1016 } 1017 check_ps_dstmod(This, instr->dstmod); 1018 check_shift_dstmod(This, instr->shift); 1019 reg = map_oldvs_register(dst); 1020 instr->dst = reg; 1021 instr->has_dst = TRUE; 1022 } 1023 1024 static void asmparser_dstreg_vs_3(struct asm_parser *This, 1025 struct instruction *instr, 1026 const struct shader_reg *dst) { 1027 if(!check_reg_type(dst, vs_3_reg_allowed)) { 1028 asmparser_message(This, "Line %u: Destination register %s not supported in VS 3.0\n", 1029 This->line_no, 1030 debug_print_dstreg(dst)); 1031 set_parse_status(&This->status, PARSE_ERR); 1032 } 1033 check_ps_dstmod(This, instr->dstmod); 1034 check_shift_dstmod(This, instr->shift); 1035 instr->dst = *dst; 1036 instr->has_dst = TRUE; 1037 } 1038 1039 static void asmparser_dstreg_ps_1_0123(struct asm_parser *This, 1040 struct instruction *instr, 1041 const struct shader_reg *dst) { 1042 struct shader_reg reg; 1043 1044 if(!check_reg_type(dst, ps_1_0123_reg_allowed)) { 1045 asmparser_message(This, "Line %u: Destination register %s not supported in PS 1\n", 1046 This->line_no, 1047 debug_print_dstreg(dst)); 1048 set_parse_status(&This->status, PARSE_ERR); 1049 } 1050 reg = map_oldps_register(dst, FALSE); 1051 instr->dst = reg; 1052 instr->has_dst = TRUE; 1053 } 1054 1055 static void asmparser_dstreg_ps_1_4(struct asm_parser *This, 1056 struct instruction *instr, 1057 const struct shader_reg *dst) { 1058 struct shader_reg reg; 1059 1060 if(!check_reg_type(dst, ps_1_4_reg_allowed)) { 1061 asmparser_message(This, "Line %u: Destination register %s not supported in PS 1\n", 1062 This->line_no, 1063 debug_print_dstreg(dst)); 1064 set_parse_status(&This->status, PARSE_ERR); 1065 } 1066 reg = map_oldps_register(dst, TRUE); 1067 instr->dst = reg; 1068 instr->has_dst = TRUE; 1069 } 1070 1071 static void asmparser_dstreg_ps_2(struct asm_parser *This, 1072 struct instruction *instr, 1073 const struct shader_reg *dst) { 1074 struct shader_reg reg; 1075 1076 if(!check_reg_type(dst, ps_2_0_reg_allowed)) { 1077 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.0\n", 1078 This->line_no, 1079 debug_print_dstreg(dst)); 1080 set_parse_status(&This->status, PARSE_ERR); 1081 } 1082 check_shift_dstmod(This, instr->shift); 1083 reg = map_oldps_register(dst, TRUE); 1084 instr->dst = reg; 1085 instr->has_dst = TRUE; 1086 } 1087 1088 static void asmparser_dstreg_ps_2_x(struct asm_parser *This, 1089 struct instruction *instr, 1090 const struct shader_reg *dst) { 1091 struct shader_reg reg; 1092 1093 if(!check_reg_type(dst, ps_2_x_reg_allowed)) { 1094 asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.x\n", 1095 This->line_no, 1096 debug_print_dstreg(dst)); 1097 set_parse_status(&This->status, PARSE_ERR); 1098 } 1099 check_shift_dstmod(This, instr->shift); 1100 reg = map_oldps_register(dst, TRUE); 1101 instr->dst = reg; 1102 instr->has_dst = TRUE; 1103 } 1104 1105 static void asmparser_dstreg_ps_3(struct asm_parser *This, 1106 struct instruction *instr, 1107 const struct shader_reg *dst) { 1108 if(!check_reg_type(dst, ps_3_reg_allowed)) { 1109 asmparser_message(This, "Line %u: Destination register %s not supported in PS 3.0\n", 1110 This->line_no, 1111 debug_print_dstreg(dst)); 1112 set_parse_status(&This->status, PARSE_ERR); 1113 } 1114 check_shift_dstmod(This, instr->shift); 1115 instr->dst = *dst; 1116 instr->has_dst = TRUE; 1117 } 1118 1119 static void asmparser_predicate_supported(struct asm_parser *This, 1120 const struct shader_reg *predicate) { 1121 /* this sets the predicate of the last instruction added to the shader */ 1122 if(!This->shader) return; 1123 if(This->shader->num_instrs == 0) ERR("Predicate without an instruction\n"); 1124 This->shader->instr[This->shader->num_instrs - 1]->has_predicate = TRUE; 1125 This->shader->instr[This->shader->num_instrs - 1]->predicate = *predicate; 1126 } 1127 1128 static void asmparser_predicate_unsupported(struct asm_parser *This, 1129 const struct shader_reg *predicate) { 1130 asmparser_message(This, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This->line_no); 1131 set_parse_status(&This->status, PARSE_ERR); 1132 } 1133 1134 static void asmparser_coissue_supported(struct asm_parser *This) { 1135 /* this sets the coissue flag of the last instruction added to the shader */ 1136 if(!This->shader) return; 1137 if(This->shader->num_instrs == 0){ 1138 asmparser_message(This, "Line %u: Coissue flag on the first shader instruction\n", This->line_no); 1139 set_parse_status(&This->status, PARSE_ERR); 1140 } 1141 This->shader->instr[This->shader->num_instrs-1]->coissue = TRUE; 1142 } 1143 1144 static void asmparser_coissue_unsupported(struct asm_parser *This) { 1145 asmparser_message(This, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This->line_no); 1146 set_parse_status(&This->status, PARSE_ERR); 1147 } 1148 1149 static const struct asmparser_backend parser_vs_1 = { 1150 asmparser_constF, 1151 asmparser_constI, 1152 asmparser_constB, 1153 1154 asmparser_dstreg_vs_1, 1155 asmparser_srcreg_vs_1, 1156 1157 asmparser_predicate_unsupported, 1158 asmparser_coissue_unsupported, 1159 1160 asmparser_dcl_output_unsupported, 1161 asmparser_dcl_input, 1162 asmparser_dcl_sampler_unsupported, 1163 1164 asmparser_end, 1165 1166 asmparser_instr, 1167 }; 1168 1169 static const struct asmparser_backend parser_vs_2 = { 1170 asmparser_constF, 1171 asmparser_constI, 1172 asmparser_constB, 1173 1174 asmparser_dstreg_vs_2, 1175 asmparser_srcreg_vs_2, 1176 1177 asmparser_predicate_supported, 1178 asmparser_coissue_unsupported, 1179 1180 asmparser_dcl_output_unsupported, 1181 asmparser_dcl_input, 1182 asmparser_dcl_sampler_unsupported, 1183 1184 asmparser_end, 1185 1186 asmparser_instr, 1187 }; 1188 1189 static const struct asmparser_backend parser_vs_3 = { 1190 asmparser_constF, 1191 asmparser_constI, 1192 asmparser_constB, 1193 1194 asmparser_dstreg_vs_3, 1195 asmparser_srcreg_vs_3, 1196 1197 asmparser_predicate_supported, 1198 asmparser_coissue_unsupported, 1199 1200 asmparser_dcl_output, 1201 asmparser_dcl_input, 1202 asmparser_dcl_sampler, 1203 1204 asmparser_end, 1205 1206 asmparser_instr, 1207 }; 1208 1209 static const struct asmparser_backend parser_ps_1_0123 = { 1210 asmparser_constF, 1211 asmparser_constI, 1212 asmparser_constB, 1213 1214 asmparser_dstreg_ps_1_0123, 1215 asmparser_srcreg_ps_1_0123, 1216 1217 asmparser_predicate_unsupported, 1218 asmparser_coissue_supported, 1219 1220 asmparser_dcl_output_unsupported, 1221 asmparser_dcl_input_unsupported, 1222 asmparser_dcl_sampler_unsupported, 1223 1224 asmparser_end, 1225 1226 asmparser_instr, 1227 }; 1228 1229 static const struct asmparser_backend parser_ps_1_4 = { 1230 asmparser_constF, 1231 asmparser_constI, 1232 asmparser_constB, 1233 1234 asmparser_dstreg_ps_1_4, 1235 asmparser_srcreg_ps_1_4, 1236 1237 asmparser_predicate_unsupported, 1238 asmparser_coissue_supported, 1239 1240 asmparser_dcl_output_unsupported, 1241 asmparser_dcl_input_unsupported, 1242 asmparser_dcl_sampler_unsupported, 1243 1244 asmparser_end, 1245 1246 asmparser_instr, 1247 }; 1248 1249 static const struct asmparser_backend parser_ps_2 = { 1250 asmparser_constF, 1251 asmparser_constI, 1252 asmparser_constB, 1253 1254 asmparser_dstreg_ps_2, 1255 asmparser_srcreg_ps_2, 1256 1257 asmparser_predicate_unsupported, 1258 asmparser_coissue_unsupported, 1259 1260 asmparser_dcl_output_unsupported, 1261 asmparser_dcl_input_ps_2, 1262 asmparser_dcl_sampler, 1263 1264 asmparser_end, 1265 1266 asmparser_instr, 1267 }; 1268 1269 static const struct asmparser_backend parser_ps_2_x = { 1270 asmparser_constF, 1271 asmparser_constI, 1272 asmparser_constB, 1273 1274 asmparser_dstreg_ps_2_x, 1275 asmparser_srcreg_ps_2_x, 1276 1277 asmparser_predicate_supported, 1278 asmparser_coissue_unsupported, 1279 1280 asmparser_dcl_output_unsupported, 1281 asmparser_dcl_input_ps_2, 1282 asmparser_dcl_sampler, 1283 1284 asmparser_end, 1285 1286 asmparser_instr, 1287 }; 1288 1289 static const struct asmparser_backend parser_ps_3 = { 1290 asmparser_constF, 1291 asmparser_constI, 1292 asmparser_constB, 1293 1294 asmparser_dstreg_ps_3, 1295 asmparser_srcreg_ps_3, 1296 1297 asmparser_predicate_supported, 1298 asmparser_coissue_unsupported, 1299 1300 asmparser_dcl_output_unsupported, 1301 asmparser_dcl_input, 1302 asmparser_dcl_sampler, 1303 1304 asmparser_end, 1305 1306 asmparser_instr, 1307 }; 1308 1309 static void gen_oldvs_output(struct bwriter_shader *shader) { 1310 record_declaration(shader, BWRITERDECLUSAGE_POSITION, 0, 0, TRUE, OPOS_REG, BWRITERSP_WRITEMASK_ALL, TRUE); 1311 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, TRUE, OT0_REG, BWRITERSP_WRITEMASK_ALL, TRUE); 1312 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, TRUE, OT1_REG, BWRITERSP_WRITEMASK_ALL, TRUE); 1313 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, TRUE, OT2_REG, BWRITERSP_WRITEMASK_ALL, TRUE); 1314 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, TRUE, OT3_REG, BWRITERSP_WRITEMASK_ALL, TRUE); 1315 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, TRUE, OT4_REG, BWRITERSP_WRITEMASK_ALL, TRUE); 1316 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, TRUE, OT5_REG, BWRITERSP_WRITEMASK_ALL, TRUE); 1317 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, TRUE, OT6_REG, BWRITERSP_WRITEMASK_ALL, TRUE); 1318 record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, TRUE, OT7_REG, BWRITERSP_WRITEMASK_ALL, TRUE); 1319 record_declaration(shader, BWRITERDECLUSAGE_FOG, 0, 0, TRUE, OFOG_REG, OFOG_WRITEMASK, TRUE); 1320 record_declaration(shader, BWRITERDECLUSAGE_PSIZE, 0, 0, TRUE, OPTS_REG, OPTS_WRITEMASK, TRUE); 1321 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, TRUE, OD0_REG, BWRITERSP_WRITEMASK_ALL, TRUE); 1322 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, TRUE, OD1_REG, BWRITERSP_WRITEMASK_ALL, TRUE); 1323 } 1324 1325 static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) { 1326 switch(texcoords) { 1327 case 8: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, 0, FALSE, T7_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE); 1328 /* fall through */ 1329 case 7: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, 0, FALSE, T6_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE); 1330 /* fall through */ 1331 case 6: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, 0, FALSE, T5_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE); 1332 /* fall through */ 1333 case 5: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, 0, FALSE, T4_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE); 1334 /* fall through */ 1335 case 4: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, 0, FALSE, T3_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE); 1336 /* fall through */ 1337 case 3: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, 0, FALSE, T2_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE); 1338 /* fall through */ 1339 case 2: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, 0, FALSE, T1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE); 1340 /* fall through */ 1341 case 1: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, 0, FALSE, T0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE); 1342 }; 1343 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, 0, FALSE, C0_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE); 1344 record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, 0, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL, TRUE); 1345 } 1346 1347 void create_vs10_parser(struct asm_parser *ret) { 1348 TRACE_(parsed_shader)("vs_1_0\n"); 1349 1350 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1351 if(!ret->shader) { 1352 ERR("Failed to allocate memory for the shader\n"); 1353 set_parse_status(&ret->status, PARSE_ERR); 1354 return; 1355 } 1356 1357 ret->shader->type = ST_VERTEX; 1358 ret->shader->version = BWRITERVS_VERSION(1, 0); 1359 ret->funcs = &parser_vs_1; 1360 gen_oldvs_output(ret->shader); 1361 } 1362 1363 void create_vs11_parser(struct asm_parser *ret) { 1364 TRACE_(parsed_shader)("vs_1_1\n"); 1365 1366 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1367 if(!ret->shader) { 1368 ERR("Failed to allocate memory for the shader\n"); 1369 set_parse_status(&ret->status, PARSE_ERR); 1370 return; 1371 } 1372 1373 ret->shader->type = ST_VERTEX; 1374 ret->shader->version = BWRITERVS_VERSION(1, 1); 1375 ret->funcs = &parser_vs_1; 1376 gen_oldvs_output(ret->shader); 1377 } 1378 1379 void create_vs20_parser(struct asm_parser *ret) { 1380 TRACE_(parsed_shader)("vs_2_0\n"); 1381 1382 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1383 if(!ret->shader) { 1384 ERR("Failed to allocate memory for the shader\n"); 1385 set_parse_status(&ret->status, PARSE_ERR); 1386 return; 1387 } 1388 1389 ret->shader->type = ST_VERTEX; 1390 ret->shader->version = BWRITERVS_VERSION(2, 0); 1391 ret->funcs = &parser_vs_2; 1392 gen_oldvs_output(ret->shader); 1393 } 1394 1395 void create_vs2x_parser(struct asm_parser *ret) { 1396 TRACE_(parsed_shader)("vs_2_x\n"); 1397 1398 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1399 if(!ret->shader) { 1400 ERR("Failed to allocate memory for the shader\n"); 1401 set_parse_status(&ret->status, PARSE_ERR); 1402 return; 1403 } 1404 1405 ret->shader->type = ST_VERTEX; 1406 ret->shader->version = BWRITERVS_VERSION(2, 1); 1407 ret->funcs = &parser_vs_2; 1408 gen_oldvs_output(ret->shader); 1409 } 1410 1411 void create_vs30_parser(struct asm_parser *ret) { 1412 TRACE_(parsed_shader)("vs_3_0\n"); 1413 1414 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1415 if(!ret->shader) { 1416 ERR("Failed to allocate memory for the shader\n"); 1417 set_parse_status(&ret->status, PARSE_ERR); 1418 return; 1419 } 1420 1421 ret->shader->type = ST_VERTEX; 1422 ret->shader->version = BWRITERVS_VERSION(3, 0); 1423 ret->funcs = &parser_vs_3; 1424 } 1425 1426 void create_ps10_parser(struct asm_parser *ret) { 1427 TRACE_(parsed_shader)("ps_1_0\n"); 1428 1429 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1430 if(!ret->shader) { 1431 ERR("Failed to allocate memory for the shader\n"); 1432 set_parse_status(&ret->status, PARSE_ERR); 1433 return; 1434 } 1435 1436 ret->shader->type = ST_PIXEL; 1437 ret->shader->version = BWRITERPS_VERSION(1, 0); 1438 ret->funcs = &parser_ps_1_0123; 1439 gen_oldps_input(ret->shader, 4); 1440 } 1441 1442 void create_ps11_parser(struct asm_parser *ret) { 1443 TRACE_(parsed_shader)("ps_1_1\n"); 1444 1445 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1446 if(!ret->shader) { 1447 ERR("Failed to allocate memory for the shader\n"); 1448 set_parse_status(&ret->status, PARSE_ERR); 1449 return; 1450 } 1451 1452 ret->shader->type = ST_PIXEL; 1453 ret->shader->version = BWRITERPS_VERSION(1, 1); 1454 ret->funcs = &parser_ps_1_0123; 1455 gen_oldps_input(ret->shader, 4); 1456 } 1457 1458 void create_ps12_parser(struct asm_parser *ret) { 1459 TRACE_(parsed_shader)("ps_1_2\n"); 1460 1461 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1462 if(!ret->shader) { 1463 ERR("Failed to allocate memory for the shader\n"); 1464 set_parse_status(&ret->status, PARSE_ERR); 1465 return; 1466 } 1467 1468 ret->shader->type = ST_PIXEL; 1469 ret->shader->version = BWRITERPS_VERSION(1, 2); 1470 ret->funcs = &parser_ps_1_0123; 1471 gen_oldps_input(ret->shader, 4); 1472 } 1473 1474 void create_ps13_parser(struct asm_parser *ret) { 1475 TRACE_(parsed_shader)("ps_1_3\n"); 1476 1477 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1478 if(!ret->shader) { 1479 ERR("Failed to allocate memory for the shader\n"); 1480 set_parse_status(&ret->status, PARSE_ERR); 1481 return; 1482 } 1483 1484 ret->shader->type = ST_PIXEL; 1485 ret->shader->version = BWRITERPS_VERSION(1, 3); 1486 ret->funcs = &parser_ps_1_0123; 1487 gen_oldps_input(ret->shader, 4); 1488 } 1489 1490 void create_ps14_parser(struct asm_parser *ret) { 1491 TRACE_(parsed_shader)("ps_1_4\n"); 1492 1493 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1494 if(!ret->shader) { 1495 ERR("Failed to allocate memory for the shader\n"); 1496 set_parse_status(&ret->status, PARSE_ERR); 1497 return; 1498 } 1499 1500 ret->shader->type = ST_PIXEL; 1501 ret->shader->version = BWRITERPS_VERSION(1, 4); 1502 ret->funcs = &parser_ps_1_4; 1503 gen_oldps_input(ret->shader, 6); 1504 } 1505 1506 void create_ps20_parser(struct asm_parser *ret) { 1507 TRACE_(parsed_shader)("ps_2_0\n"); 1508 1509 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1510 if(!ret->shader) { 1511 ERR("Failed to allocate memory for the shader\n"); 1512 set_parse_status(&ret->status, PARSE_ERR); 1513 return; 1514 } 1515 1516 ret->shader->type = ST_PIXEL; 1517 ret->shader->version = BWRITERPS_VERSION(2, 0); 1518 ret->funcs = &parser_ps_2; 1519 gen_oldps_input(ret->shader, 8); 1520 } 1521 1522 void create_ps2x_parser(struct asm_parser *ret) { 1523 TRACE_(parsed_shader)("ps_2_x\n"); 1524 1525 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1526 if(!ret->shader) { 1527 ERR("Failed to allocate memory for the shader\n"); 1528 set_parse_status(&ret->status, PARSE_ERR); 1529 return; 1530 } 1531 1532 ret->shader->type = ST_PIXEL; 1533 ret->shader->version = BWRITERPS_VERSION(2, 1); 1534 ret->funcs = &parser_ps_2_x; 1535 gen_oldps_input(ret->shader, 8); 1536 } 1537 1538 void create_ps30_parser(struct asm_parser *ret) { 1539 TRACE_(parsed_shader)("ps_3_0\n"); 1540 1541 ret->shader = d3dcompiler_alloc(sizeof(*ret->shader)); 1542 if(!ret->shader) { 1543 ERR("Failed to allocate memory for the shader\n"); 1544 set_parse_status(&ret->status, PARSE_ERR); 1545 return; 1546 } 1547 1548 ret->shader->type = ST_PIXEL; 1549 ret->shader->version = BWRITERPS_VERSION(3, 0); 1550 ret->funcs = &parser_ps_3; 1551 } 1552