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