2 * Direct3D shader assembler
4 * Copyright 2008 Stefan Dösinger
5 * Copyright 2009 Matteo Bruni
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/debug.h"
25 #include "d3dcompiler_private.h"
26 #include "asmshader.tab.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
32 %option prefix="asmshader_"
33 %option noinput nounput never-interactive
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.
40 COMPONENT [xyzw]|[rgba]
44 /* for relative addressing in the form o[x], v[x] and c[x] */
47 REG_CONSTFLOAT c[0-9]*
51 REG_TEXCRDOUT oT[0-9]+
56 REG_VERTEXCOLOR oD[01]
57 REG_FRAGCOLOR oC[0-9]+
64 /* Not really a register, but it is considered as such */
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]*
79 DCL_DEPTH _depth[0-9]*
80 DCL_SAMPLE _sample[0-9]*
85 DCL_SAMPLERVOLUME _volume
87 PREPROCESSORDIRECTIVE #[^\n]*\n
90 DOUBLESLASHCOMMENT "//"[^\n]*
91 SEMICOLONCOMMENT ";"[^\n]*
93 /* Whitespaces are spaces, tabs and newlines */
99 IMMVAL (([0-9]+\.?)|([0-9]*\.[0-9]+))(f)?
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; }
158 /* Vertex shader only instructions */
159 lit {return INSTR_LIT; }
160 mova {return INSTR_MOVA; }
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; }
196 asmshader_lval.regnum = atoi(yytext + 1);
200 asmshader_lval.regnum = atoi(yytext + 1);
204 asmshader_lval.regnum = atoi(yytext + 1);
208 asmshader_lval.regnum = atoi(yytext + 1);
209 return REG_CONSTFLOAT;
212 asmshader_lval.regnum = atoi(yytext + 1);
216 asmshader_lval.regnum = atoi(yytext + 1);
217 return REG_CONSTBOOL;
220 asmshader_lval.regnum = atoi(yytext + 1);
224 asmshader_lval.regnum = atoi(yytext + 2);
225 return REG_TEXCRDOUT;
228 asmshader_lval.regnum = atoi(yytext + 1);
231 {REG_OPOS} {return REG_OPOS; }
232 {REG_OFOG} {return REG_OFOG; }
233 {REG_OPTS} {return REG_OPTS; }
235 asmshader_lval.regnum = atoi(yytext + 2);
236 return REG_VERTEXCOLOR;
239 asmshader_lval.regnum = atoi(yytext + 2);
240 return REG_FRAGCOLOR;
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; }
250 asmshader_lval.regnum = atoi(yytext + 1);
254 /* Shader versions. These are important to select the correct
257 vs\.1\.0|vs_1_0 {return VER_VS10; }
258 vs\.1\.1|vs_1_1 {return VER_VS11; }
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; }
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; }
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; }
274 {DOT} {return yytext[0]; }
279 asmshader_lval.component = 0;
283 asmshader_lval.component = 1;
287 asmshader_lval.component = 2;
291 asmshader_lval.component = 3;
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; }
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; }
317 asmshader_lval.immval.val = atof(yytext);
318 asmshader_lval.immval.integer = ((strstr(yytext, ".") == NULL) && (strstr(yytext, "f") == NULL));
322 asmshader_lval.immbool = TRUE;
326 asmshader_lval.immbool = FALSE;
330 {COMMA} {return yytext[0]; }
331 - {return yytext[0]; }
332 \( {return yytext[0]; }
333 \) {return yytext[0]; }
335 /* for relative addressing */
336 \[|\]|\+ {return yytext[0]; }
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; }
345 ! {return SMOD_NOT; }
348 if(yytext[strlen("_position")] == '\0') {
349 asmshader_lval.regnum = 0;
351 asmshader_lval.regnum = atoi(yytext + strlen("_position"));
353 return USAGE_POSITION;
356 if(yytext[strlen("_blendweight")] == '\0') {
357 asmshader_lval.regnum = 0;
359 asmshader_lval.regnum = atoi(yytext + strlen("_blendweight"));
361 return USAGE_BLENDWEIGHT;
364 if(yytext[strlen("_blendindices")] == '\0') {
365 asmshader_lval.regnum = 0;
367 asmshader_lval.regnum = atoi(yytext + strlen("_blendindices"));
369 return USAGE_BLENDINDICES;
372 if(yytext[strlen("_normal")] == '\0') {
373 asmshader_lval.regnum = 0;
375 asmshader_lval.regnum = atoi(yytext + strlen("_normal"));
380 if(yytext[strlen("_psize")] == '\0') {
381 asmshader_lval.regnum = 0;
383 asmshader_lval.regnum = atoi(yytext + strlen("_psize"));
388 if(yytext[strlen("_texcoord")] == '\0') {
389 asmshader_lval.regnum = 0;
391 asmshader_lval.regnum = atoi(yytext + strlen("_texcoord"));
393 return USAGE_TEXCOORD;
396 if(yytext[strlen("_tangent")] == '\0') {
397 asmshader_lval.regnum = 0;
399 asmshader_lval.regnum = atoi(yytext + strlen("_tangent"));
401 return USAGE_TANGENT;
404 if(yytext[strlen("_binormal")] == '\0') {
405 asmshader_lval.regnum = 0;
407 asmshader_lval.regnum = atoi(yytext + strlen("_binormal"));
409 return USAGE_BINORMAL;
412 if(yytext[strlen("_tessfactor")] == '\0') {
413 asmshader_lval.regnum = 0;
415 asmshader_lval.regnum = atoi(yytext + strlen("_tessfactor"));
417 return USAGE_TESSFACTOR;
420 if(yytext[strlen("_positiont")] == '\0') {
421 asmshader_lval.regnum = 0;
423 asmshader_lval.regnum = atoi(yytext + strlen("_positiont"));
425 return USAGE_POSITIONT;
428 if(yytext[strlen("_color")] == '\0') {
429 asmshader_lval.regnum = 0;
431 asmshader_lval.regnum = atoi(yytext + strlen("_color"));
436 if(yytext[strlen("_fog")] == '\0') {
437 asmshader_lval.regnum = 0;
439 asmshader_lval.regnum = atoi(yytext + strlen("_fog"));
444 if(yytext[strlen("_depth")] == '\0') {
445 asmshader_lval.regnum = 0;
447 asmshader_lval.regnum = atoi(yytext + strlen("_depth"));
452 if(yytext[strlen("_sample")] == '\0') {
453 asmshader_lval.regnum = 0;
455 asmshader_lval.regnum = atoi(yytext + strlen("_sample"));
460 {DCL_SAMPLER1D} { return SAMPTYPE_1D; }
461 {DCL_SAMPLER2D} { return SAMPTYPE_2D; }
462 {DCL_SAMPLERCUBE} { return SAMPTYPE_CUBE; }
463 {DCL_SAMPLERVOLUME} { return SAMPTYPE_VOLUME; }
465 {PREPROCESSORDIRECTIVE} {
466 /* TODO: update current line information */
467 TRACE("line info update: %s", yytext);
471 {DOUBLESLASHCOMMENT} { }
472 {SEMICOLONCOMMENT} { }
474 {WHITESPACE} { /* Do nothing */ }
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);
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);
491 buffer = asmshader__scan_string(text);
492 asmshader__switch_to_buffer(buffer);
494 ret = parse_asm_shader(messages);
496 asmshader__delete_buffer(buffer);