1 /* 2 * Direct3D shader assembler 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 #include "asmshader.tab.h" 27 28 WINE_DEFAULT_DEBUG_CHANNEL(asmshader); 29 %} 30 31 %option noyywrap 32 %option prefix="asmshader_" 33 %option noinput nounput never-interactive 34 35 /* Swizzles and writemasks consist of a dot and up to 4 x, y, z or w characters, 36 * or up to 4 a, r, g, b characters. There are different rules for swizzles and 37 * writemasks wrt repetition, those are handled in the grammar. 38 */ 39 DOT \. 40 COMPONENT [xyzw]|[rgba] 41 42 /* Registers */ 43 REG_TEMP r[0-9]+ 44 /* for relative addressing in the form o[x], v[x] and c[x] */ 45 REG_OUTPUT o[0-9]* 46 REG_INPUT v[0-9]* 47 REG_CONSTFLOAT c[0-9]* 48 REG_CONSTINT i[0-9]+ 49 REG_CONSTBOOL b[0-9]+ 50 REG_TEXTURE t[0-9]+ 51 REG_TEXCRDOUT oT[0-9]+ 52 REG_SAMPLER s[0-9]+ 53 REG_OPOS oPos 54 REG_OFOG oFog 55 REG_OPTS oPts 56 REG_VERTEXCOLOR oD[01] 57 REG_FRAGCOLOR oC[0-9]+ 58 REG_FRAGDEPTH oDepth 59 REG_VPOS vPos 60 REG_VFACE vFace 61 REG_ADDRESS a0 62 REG_LOOP aL 63 REG_PREDICATE p0 64 /* Not really a register, but it is considered as such */ 65 REG_LABEL l[0-9]+ 66 67 DCL_POSITION _position[0-9]* 68 DCL_BLENDWEIGHT _blendweight[0-9]* 69 DCL_BLENDINDICES _blendindices[0-9]* 70 DCL_NORMAL _normal[0-9]* 71 DCL_PSIZE _psize[0-9]* 72 DCL_TEXCOORD _texcoord[0-9]* 73 DCL_TANGENT _tangent[0-9]* 74 DCL_BINORMAL _binormal[0-9]* 75 DCL_TESSFACTOR _tessfactor[0-9]* 76 DCL_POSITIONT _positiont[0-9]* 77 DCL_COLOR _color[0-9]* 78 DCL_FOG _fog[0-9]* 79 DCL_DEPTH _depth[0-9]* 80 DCL_SAMPLE _sample[0-9]* 81 82 DCL_SAMPLER1D _1d 83 DCL_SAMPLER2D _2d 84 DCL_SAMPLERCUBE _cube 85 DCL_SAMPLERVOLUME _volume 86 87 PREPROCESSORDIRECTIVE #[^\n]*\n 88 89 /* Comments */ 90 DOUBLESLASHCOMMENT "//"[^\n]* 91 SEMICOLONCOMMENT ";"[^\n]* 92 93 /* Whitespaces are spaces, tabs and newlines */ 94 WHITESPACE [ \t]+ 95 NEWLINE (\n)|(\r\n) 96 97 COMMA "," 98 99 IMMVAL \-?(([0-9]+\.?)|([0-9]*\.[0-9]+))(f)? 100 101 ANY (.) 102 103 %% 104 105 /* Common instructions(vertex and pixel shaders) */ 106 add {return INSTR_ADD; } 107 nop {return INSTR_NOP; } 108 mov {return INSTR_MOV; } 109 sub {return INSTR_SUB; } 110 mad {return INSTR_MAD; } 111 mul {return INSTR_MUL; } 112 rcp {return INSTR_RCP; } 113 rsq {return INSTR_RSQ; } 114 dp3 {return INSTR_DP3; } 115 dp4 {return INSTR_DP4; } 116 min {return INSTR_MIN; } 117 max {return INSTR_MAX; } 118 slt {return INSTR_SLT; } 119 sge {return INSTR_SGE; } 120 abs {return INSTR_ABS; } 121 exp {return INSTR_EXP; } 122 log {return INSTR_LOG; } 123 expp {return INSTR_EXPP; } 124 logp {return INSTR_LOGP; } 125 dst {return INSTR_DST; } 126 lrp {return INSTR_LRP; } 127 frc {return INSTR_FRC; } 128 pow {return INSTR_POW; } 129 crs {return INSTR_CRS; } 130 sgn {return INSTR_SGN; } 131 nrm {return INSTR_NRM; } 132 sincos {return INSTR_SINCOS; } 133 m4x4 {return INSTR_M4x4; } 134 m4x3 {return INSTR_M4x3; } 135 m3x4 {return INSTR_M3x4; } 136 m3x3 {return INSTR_M3x3; } 137 m3x2 {return INSTR_M3x2; } 138 dcl {return INSTR_DCL; } 139 def {return INSTR_DEF; } 140 defb {return INSTR_DEFB; } 141 defi {return INSTR_DEFI; } 142 rep {return INSTR_REP; } 143 endrep {return INSTR_ENDREP; } 144 if {return INSTR_IF; } 145 else {return INSTR_ELSE; } 146 endif {return INSTR_ENDIF; } 147 break {return INSTR_BREAK; } 148 breakp {return INSTR_BREAKP; } 149 call {return INSTR_CALL; } 150 callnz {return INSTR_CALLNZ; } 151 loop {return INSTR_LOOP; } 152 ret {return INSTR_RET; } 153 endloop {return INSTR_ENDLOOP; } 154 label {return INSTR_LABEL; } 155 setp {return INSTR_SETP; } 156 texldl {return INSTR_TEXLDL; } 157 158 /* Vertex shader only instructions */ 159 lit {return INSTR_LIT; } 160 mova {return INSTR_MOVA; } 161 162 /* Pixel shader only instructions */ 163 cnd {return INSTR_CND; } 164 cmp {return INSTR_CMP; } 165 dp2add {return INSTR_DP2ADD; } 166 texcoord {return INSTR_TEXCOORD; } 167 texcrd {return INSTR_TEXCRD; } 168 texkill {return INSTR_TEXKILL; } 169 tex {return INSTR_TEX; } 170 texld {return INSTR_TEXLD; } 171 texbem {return INSTR_TEXBEM; } 172 texbeml {return INSTR_TEXBEML; } 173 texreg2ar {return INSTR_TEXREG2AR; } 174 texreg2gb {return INSTR_TEXREG2GB; } 175 texreg2rgb {return INSTR_TEXREG2RGB; } 176 texm3x2pad {return INSTR_TEXM3x2PAD; } 177 texm3x2tex {return INSTR_TEXM3x2TEX; } 178 texm3x3pad {return INSTR_TEXM3x3PAD; } 179 texm3x3spec {return INSTR_TEXM3x3SPEC; } 180 texm3x3vspec {return INSTR_TEXM3x3VSPEC; } 181 texm3x3tex {return INSTR_TEXM3x3TEX; } 182 texdp3tex {return INSTR_TEXDP3TEX; } 183 texm3x2depth {return INSTR_TEXM3x2DEPTH; } 184 texdp3 {return INSTR_TEXDP3; } 185 texm3x3 {return INSTR_TEXM3x3; } 186 texdepth {return INSTR_TEXDEPTH; } 187 bem {return INSTR_BEM; } 188 dsx {return INSTR_DSX; } 189 dsy {return INSTR_DSY; } 190 texldp {return INSTR_TEXLDP; } 191 texldb {return INSTR_TEXLDB; } 192 texldd {return INSTR_TEXLDD; } 193 phase {return INSTR_PHASE; } 194 195 {REG_TEMP} { 196 asmshader_lval.regnum = atoi(yytext + 1); 197 return REG_TEMP; 198 } 199 {REG_OUTPUT} { 200 asmshader_lval.regnum = atoi(yytext + 1); 201 return REG_OUTPUT; 202 } 203 {REG_INPUT} { 204 asmshader_lval.regnum = atoi(yytext + 1); 205 return REG_INPUT; 206 } 207 {REG_CONSTFLOAT} { 208 asmshader_lval.regnum = atoi(yytext + 1); 209 return REG_CONSTFLOAT; 210 } 211 {REG_CONSTINT} { 212 asmshader_lval.regnum = atoi(yytext + 1); 213 return REG_CONSTINT; 214 } 215 {REG_CONSTBOOL} { 216 asmshader_lval.regnum = atoi(yytext + 1); 217 return REG_CONSTBOOL; 218 } 219 {REG_TEXTURE} { 220 asmshader_lval.regnum = atoi(yytext + 1); 221 return REG_TEXTURE; 222 } 223 {REG_TEXCRDOUT} { 224 asmshader_lval.regnum = atoi(yytext + 2); 225 return REG_TEXCRDOUT; 226 } 227 {REG_SAMPLER} { 228 asmshader_lval.regnum = atoi(yytext + 1); 229 return REG_SAMPLER; 230 } 231 {REG_OPOS} {return REG_OPOS; } 232 {REG_OFOG} {return REG_OFOG; } 233 {REG_OPTS} {return REG_OPTS; } 234 {REG_VERTEXCOLOR} { 235 asmshader_lval.regnum = atoi(yytext + 2); 236 return REG_VERTEXCOLOR; 237 } 238 {REG_FRAGCOLOR} { 239 asmshader_lval.regnum = atoi(yytext + 2); 240 return REG_FRAGCOLOR; 241 } 242 {REG_FRAGDEPTH} {return REG_FRAGDEPTH; } 243 {REG_VPOS} {return REG_VPOS; } 244 {REG_VFACE} {return REG_VFACE; } 245 {REG_ADDRESS} {return REG_ADDRESS; } 246 {REG_LOOP} {return REG_LOOP; } 247 {REG_PREDICATE} {return REG_PREDICATE; } 248 249 {REG_LABEL} { 250 asmshader_lval.regnum = atoi(yytext + 1); 251 return REG_LABEL; 252 } 253 254 /* Shader versions. These are important to select the correct 255 * parser profile. 256 */ 257 vs\.1\.0|vs_1_0 {return VER_VS10; } 258 vs\.1\.1|vs_1_1 {return VER_VS11; } 259 260 vs\.2\.0|vs_2_0 {return VER_VS20; } 261 vs\.2\.x|vs_2_x {return VER_VS2X; } 262 vs\.3\.0|vs_3_0 {return VER_VS30; } 263 264 ps\.1\.0|ps_1_0 {return VER_PS10; } 265 ps\.1\.1|ps_1_1 {return VER_PS11; } 266 ps\.1\.2|ps_1_2 {return VER_PS12; } 267 ps\.1\.3|ps_1_3 {return VER_PS13; } 268 ps\.1\.4|ps_1_4 {return VER_PS14; } 269 270 ps\.2\.0|ps_2_0 {return VER_PS20; } 271 ps\.2\.x|ps_2_x {return VER_PS2X; } 272 ps\.3\.0|ps_3_0 {return VER_PS30; } 273 274 {DOT} {return yytext[0]; } 275 {COMPONENT} { 276 switch(yytext[0]) { 277 case 'x': 278 case 'r': 279 asmshader_lval.component = 0; 280 break; 281 case 'y': 282 case 'g': 283 asmshader_lval.component = 1; 284 break; 285 case 'z': 286 case 'b': 287 asmshader_lval.component = 2; 288 break; 289 case 'w': 290 case 'a': 291 asmshader_lval.component = 3; 292 break; 293 } 294 return COMPONENT; 295 } 296 297 /* Output modifiers */ 298 \_x2 {return SHIFT_X2; } 299 \_x4 {return SHIFT_X4; } 300 \_x8 {return SHIFT_X8; } 301 \_d2 {return SHIFT_D2; } 302 \_d4 {return SHIFT_D4; } 303 \_d8 {return SHIFT_D8; } 304 \_sat {return MOD_SAT; } 305 \_pp {return MOD_PP; } 306 \_centroid {return MOD_CENTROID; } 307 308 /* compare params */ 309 \_gt {return COMP_GT; } 310 \_lt {return COMP_LT; } 311 \_ge {return COMP_GE; } 312 \_le {return COMP_LE; } 313 \_eq {return COMP_EQ; } 314 \_ne {return COMP_NE; } 315 316 {IMMVAL} { 317 asmshader_lval.immval.val = atof(yytext); 318 asmshader_lval.immval.integer = ((strstr(yytext, ".") == NULL) && (strstr(yytext, "f") == NULL)); 319 return IMMVAL; 320 } 321 true { 322 asmshader_lval.immbool = TRUE; 323 return IMMBOOL; 324 } 325 false { 326 asmshader_lval.immbool = FALSE; 327 return IMMBOOL; 328 } 329 330 {COMMA} {return yytext[0]; } 331 - {return yytext[0]; } 332 \( {return yytext[0]; } 333 \) {return yytext[0]; } 334 335 /* for relative addressing */ 336 \[|\]|\+ {return yytext[0]; } 337 338 \_bias {return SMOD_BIAS; } 339 /* No _x2 here; it is identical to MOD_X2 */ 340 \_bx2 {return SMOD_SCALEBIAS; } 341 \_dz {return SMOD_DZ; } 342 \_dw {return SMOD_DW; } 343 \_abs {return SMOD_ABS; } 344 345 ! {return SMOD_NOT; } 346 347 {DCL_POSITION} { 348 if(yytext[strlen("_position")] == '\0') { 349 asmshader_lval.regnum = 0; 350 } else { 351 asmshader_lval.regnum = atoi(yytext + strlen("_position")); 352 } 353 return USAGE_POSITION; 354 } 355 {DCL_BLENDWEIGHT} { 356 if(yytext[strlen("_blendweight")] == '\0') { 357 asmshader_lval.regnum = 0; 358 } else { 359 asmshader_lval.regnum = atoi(yytext + strlen("_blendweight")); 360 } 361 return USAGE_BLENDWEIGHT; 362 } 363 {DCL_BLENDINDICES} { 364 if(yytext[strlen("_blendindices")] == '\0') { 365 asmshader_lval.regnum = 0; 366 } else { 367 asmshader_lval.regnum = atoi(yytext + strlen("_blendindices")); 368 } 369 return USAGE_BLENDINDICES; 370 } 371 {DCL_NORMAL} { 372 if(yytext[strlen("_normal")] == '\0') { 373 asmshader_lval.regnum = 0; 374 } else { 375 asmshader_lval.regnum = atoi(yytext + strlen("_normal")); 376 } 377 return USAGE_NORMAL; 378 } 379 {DCL_PSIZE} { 380 if(yytext[strlen("_psize")] == '\0') { 381 asmshader_lval.regnum = 0; 382 } else { 383 asmshader_lval.regnum = atoi(yytext + strlen("_psize")); 384 } 385 return USAGE_PSIZE; 386 } 387 {DCL_TEXCOORD} { 388 if(yytext[strlen("_texcoord")] == '\0') { 389 asmshader_lval.regnum = 0; 390 } else { 391 asmshader_lval.regnum = atoi(yytext + strlen("_texcoord")); 392 } 393 return USAGE_TEXCOORD; 394 } 395 {DCL_TANGENT} { 396 if(yytext[strlen("_tangent")] == '\0') { 397 asmshader_lval.regnum = 0; 398 } else { 399 asmshader_lval.regnum = atoi(yytext + strlen("_tangent")); 400 } 401 return USAGE_TANGENT; 402 } 403 {DCL_BINORMAL} { 404 if(yytext[strlen("_binormal")] == '\0') { 405 asmshader_lval.regnum = 0; 406 } else { 407 asmshader_lval.regnum = atoi(yytext + strlen("_binormal")); 408 } 409 return USAGE_BINORMAL; 410 } 411 {DCL_TESSFACTOR} { 412 if(yytext[strlen("_tessfactor")] == '\0') { 413 asmshader_lval.regnum = 0; 414 } else { 415 asmshader_lval.regnum = atoi(yytext + strlen("_tessfactor")); 416 } 417 return USAGE_TESSFACTOR; 418 } 419 {DCL_POSITIONT} { 420 if(yytext[strlen("_positiont")] == '\0') { 421 asmshader_lval.regnum = 0; 422 } else { 423 asmshader_lval.regnum = atoi(yytext + strlen("_positiont")); 424 } 425 return USAGE_POSITIONT; 426 } 427 {DCL_COLOR} { 428 if(yytext[strlen("_color")] == '\0') { 429 asmshader_lval.regnum = 0; 430 } else { 431 asmshader_lval.regnum = atoi(yytext + strlen("_color")); 432 } 433 return USAGE_COLOR; 434 } 435 {DCL_FOG} { 436 if(yytext[strlen("_fog")] == '\0') { 437 asmshader_lval.regnum = 0; 438 } else { 439 asmshader_lval.regnum = atoi(yytext + strlen("_fog")); 440 } 441 return USAGE_FOG; 442 } 443 {DCL_DEPTH} { 444 if(yytext[strlen("_depth")] == '\0') { 445 asmshader_lval.regnum = 0; 446 } else { 447 asmshader_lval.regnum = atoi(yytext + strlen("_depth")); 448 } 449 return USAGE_DEPTH; 450 } 451 {DCL_SAMPLE} { 452 if(yytext[strlen("_sample")] == '\0') { 453 asmshader_lval.regnum = 0; 454 } else { 455 asmshader_lval.regnum = atoi(yytext + strlen("_sample")); 456 } 457 return USAGE_SAMPLE; 458 } 459 460 {DCL_SAMPLER1D} { return SAMPTYPE_1D; } 461 {DCL_SAMPLER2D} { return SAMPTYPE_2D; } 462 {DCL_SAMPLERCUBE} { return SAMPTYPE_CUBE; } 463 {DCL_SAMPLERVOLUME} { return SAMPTYPE_VOLUME; } 464 465 {PREPROCESSORDIRECTIVE} { 466 /* TODO: update current line information */ 467 TRACE("line info update: %s", yytext); 468 } 469 470 /* Skip comments */ 471 {DOUBLESLASHCOMMENT} { } 472 {SEMICOLONCOMMENT} { } 473 474 {WHITESPACE} { /* Do nothing */ } 475 {NEWLINE} { 476 asm_ctx.line_no++; 477 } 478 479 {ANY} { 480 asmparser_message(&asm_ctx, "Line %u: Unexpected input %s\n", asm_ctx.line_no, yytext); 481 set_parse_status(&asm_ctx.status, PARSE_ERR); 482 } 483 484 %% 485 486 struct bwriter_shader *SlAssembleShader(const char *text, char **messages) { 487 struct bwriter_shader *ret = NULL; 488 YY_BUFFER_STATE buffer; 489 TRACE("%p, %p\n", text, messages); 490 491 buffer = asmshader__scan_string(text); 492 asmshader__switch_to_buffer(buffer); 493 494 ret = parse_asm_shader(messages); 495 496 asmshader__delete_buffer(buffer); 497 498 return ret; 499 } 500