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
24 #include "wine/port.h"
25 #include "wine/debug.h"
27 #include "d3dx9_36_private.h"
28 #include "asmshader.tab.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
34 %option prefix="asmshader_"
35 %option noinput nounput
37 /* Swizzles and writemasks consist of a dot and up to 4 x, y, z or w characters,
38 * or up to 4 a, r, g, b characters. There are different rules for swizzles and
39 * writemasks wrt repetition, those are handled in the grammar.
42 COMPONENT [xyzw]|[rgba]
46 /* for relative addressing in the form o[x], v[x] and c[x] */
49 REG_CONSTFLOAT c[0-9]*
53 REG_TEXCRDOUT oT[0-9]+
58 REG_VERTEXCOLOR oD[01]
59 REG_FRAGCOLOR oC[0-9]+
66 /* Not really a register, but it is considered as such */
69 DCL_POSITION _position[0-9]*
70 DCL_BLENDWEIGHT _blendweight[0-9]*
71 DCL_BLENDINDICES _blendindices[0-9]*
72 DCL_NORMAL _normal[0-9]*
73 DCL_PSIZE _psize[0-9]*
74 DCL_TEXCOORD _texcoord[0-9]*
75 DCL_TANGENT _tangent[0-9]*
76 DCL_BINORMAL _binormal[0-9]*
77 DCL_TESSFACTOR _tessfactor[0-9]*
78 DCL_POSITIONT _positiont[0-9]*
79 DCL_COLOR _color[0-9]*
81 DCL_DEPTH _depth[0-9]*
82 DCL_SAMPLE _sample[0-9]*
87 DCL_SAMPLERVOLUME _volume
89 PREPROCESSORDIRECTIVE #[^\n]*\n
92 DOUBLESLASHCOMMENT "//"[^\n]*
93 SEMICOLONCOMMENT ";"[^\n]*
95 /* Whitespaces are spaces, tabs and newlines */
101 IMMVAL \-?(([0-9]+)|([0-9]*\.[0-9]+))(f)?
107 /* Common instructions(vertex and pixel shaders) */
108 add {return INSTR_ADD; }
109 nop {return INSTR_NOP; }
110 mov {return INSTR_MOV; }
111 sub {return INSTR_SUB; }
112 mad {return INSTR_MAD; }
113 mul {return INSTR_MUL; }
114 rcp {return INSTR_RCP; }
115 rsq {return INSTR_RSQ; }
116 dp3 {return INSTR_DP3; }
117 dp4 {return INSTR_DP4; }
118 min {return INSTR_MIN; }
119 max {return INSTR_MAX; }
120 slt {return INSTR_SLT; }
121 sge {return INSTR_SGE; }
122 abs {return INSTR_ABS; }
123 exp {return INSTR_EXP; }
124 log {return INSTR_LOG; }
125 expp {return INSTR_EXPP; }
126 logp {return INSTR_LOGP; }
127 dst {return INSTR_DST; }
128 lrp {return INSTR_LRP; }
129 frc {return INSTR_FRC; }
130 pow {return INSTR_POW; }
131 crs {return INSTR_CRS; }
132 sgn {return INSTR_SGN; }
133 nrm {return INSTR_NRM; }
134 sincos {return INSTR_SINCOS; }
135 m4x4 {return INSTR_M4x4; }
136 m4x3 {return INSTR_M4x3; }
137 m3x4 {return INSTR_M3x4; }
138 m3x3 {return INSTR_M3x3; }
139 m3x2 {return INSTR_M3x2; }
140 dcl {return INSTR_DCL; }
141 def {return INSTR_DEF; }
142 defb {return INSTR_DEFB; }
143 defi {return INSTR_DEFI; }
144 rep {return INSTR_REP; }
145 endrep {return INSTR_ENDREP; }
146 if {return INSTR_IF; }
147 else {return INSTR_ELSE; }
148 endif {return INSTR_ENDIF; }
149 break {return INSTR_BREAK; }
150 breakp {return INSTR_BREAKP; }
151 call {return INSTR_CALL; }
152 callnz {return INSTR_CALLNZ; }
153 loop {return INSTR_LOOP; }
154 ret {return INSTR_RET; }
155 endloop {return INSTR_ENDLOOP; }
156 label {return INSTR_LABEL; }
157 setp {return INSTR_SETP; }
158 texldl {return INSTR_TEXLDL; }
160 /* Vertex shader only instructions */
161 lit {return INSTR_LIT; }
162 mova {return INSTR_MOVA; }
164 /* Pixel shader only instructions */
165 cmp {return INSTR_CMP; }
166 dp2add {return INSTR_DP2ADD; }
167 texkill {return INSTR_TEXKILL; }
168 texld {return INSTR_TEXLD; }
169 dsx {return INSTR_DSX; }
170 dsy {return INSTR_DSY; }
171 texldp {return INSTR_TEXLDP; }
172 texldb {return INSTR_TEXLDB; }
173 texldd {return INSTR_TEXLDD; }
176 asmshader_lval.regnum = atoi(yytext + 1);
180 asmshader_lval.regnum = atoi(yytext + 1);
184 asmshader_lval.regnum = atoi(yytext + 1);
188 asmshader_lval.regnum = atoi(yytext + 1);
189 return REG_CONSTFLOAT;
192 asmshader_lval.regnum = atoi(yytext + 1);
196 asmshader_lval.regnum = atoi(yytext + 1);
197 return REG_CONSTBOOL;
200 asmshader_lval.regnum = atoi(yytext + 1);
204 asmshader_lval.regnum = atoi(yytext + 2);
205 return REG_TEXCRDOUT;
208 asmshader_lval.regnum = atoi(yytext + 1);
211 {REG_OPOS} {return REG_OPOS; }
212 {REG_OFOG} {return REG_OFOG; }
213 {REG_OPTS} {return REG_OPTS; }
215 asmshader_lval.regnum = atoi(yytext + 2);
216 return REG_VERTEXCOLOR;
219 asmshader_lval.regnum = atoi(yytext + 2);
220 return REG_FRAGCOLOR;
222 {REG_FRAGDEPTH} {return REG_FRAGDEPTH; }
223 {REG_VPOS} {return REG_VPOS; }
224 {REG_VFACE} {return REG_VFACE; }
225 {REG_ADDRESS} {return REG_ADDRESS; }
226 {REG_LOOP} {return REG_LOOP; }
227 {REG_PREDICATE} {return REG_PREDICATE; }
230 asmshader_lval.regnum = atoi(yytext + 1);
234 /* Shader versions. These are important to select the correct
237 vs\.1\.0|vs_1_0 {return VER_VS10; }
238 vs\.1\.1|vs_1_1 {return VER_VS11; }
240 vs_2_0 {return VER_VS20; }
241 vs_2_x {return VER_VS2X; }
242 vs_3_0 {return VER_VS30; }
244 ps\.1\.0|ps_1_0 {return VER_PS10; }
245 ps\.1\.1|ps_1_1 {return VER_PS11; }
246 ps\.1\.2|ps_1_2 {return VER_PS12; }
247 ps\.1\.3|ps_1_3 {return VER_PS13; }
248 ps\.1\.4|ps_1_4 {return VER_PS14; }
250 ps_2_0 {return VER_PS20; }
251 ps_2_x {return VER_PS2X; }
252 ps_3_0 {return VER_PS30; }
254 {DOT} {return yytext[0]; }
259 asmshader_lval.component = 0;
263 asmshader_lval.component = 1;
267 asmshader_lval.component = 2;
271 asmshader_lval.component = 3;
277 /* Output modifiers */
278 \_sat {return MOD_SAT; }
279 \_pp {return MOD_PP; }
280 \_centroid {return MOD_CENTROID; }
283 \_gt {return COMP_GT; }
284 \_lt {return COMP_LT; }
285 \_ge {return COMP_GE; }
286 \_le {return COMP_LE; }
287 \_eq {return COMP_EQ; }
288 \_ne {return COMP_NE; }
291 asmshader_lval.immval.val = atof(yytext);
292 asmshader_lval.immval.integer = ((strstr(yytext, ".") == NULL) && (strstr(yytext, "f") == NULL));
296 asmshader_lval.immbool = TRUE;
300 asmshader_lval.immbool = FALSE;
304 {COMMA} {return yytext[0]; }
305 - {return yytext[0]; }
306 \( {return yytext[0]; }
307 \) {return yytext[0]; }
309 /* for relative addressing */
310 \[|\]|\+ {return yytext[0]; }
312 \_abs {return SMOD_ABS; }
314 ! {return SMOD_NOT; }
317 if(yytext[strlen("_position")] == '\0') {
318 asmshader_lval.regnum = 0;
320 asmshader_lval.regnum = atoi(yytext + strlen("_position"));
322 return USAGE_POSITION;
325 if(yytext[strlen("_blendweight")] == '\0') {
326 asmshader_lval.regnum = 0;
328 asmshader_lval.regnum = atoi(yytext + strlen("_blendweight"));
330 return USAGE_BLENDWEIGHT;
333 if(yytext[strlen("_blendindices")] == '\0') {
334 asmshader_lval.regnum = 0;
336 asmshader_lval.regnum = atoi(yytext + strlen("_blendindices"));
338 return USAGE_BLENDINDICES;
341 if(yytext[strlen("_normal")] == '\0') {
342 asmshader_lval.regnum = 0;
344 asmshader_lval.regnum = atoi(yytext + strlen("_normal"));
349 if(yytext[strlen("_psize")] == '\0') {
350 asmshader_lval.regnum = 0;
352 asmshader_lval.regnum = atoi(yytext + strlen("_psize"));
357 if(yytext[strlen("_texcoord")] == '\0') {
358 asmshader_lval.regnum = 0;
360 asmshader_lval.regnum = atoi(yytext + strlen("_texcoord"));
362 return USAGE_TEXCOORD;
365 if(yytext[strlen("_tangent")] == '\0') {
366 asmshader_lval.regnum = 0;
368 asmshader_lval.regnum = atoi(yytext + strlen("_tangent"));
370 return USAGE_TANGENT;
373 if(yytext[strlen("_binormal")] == '\0') {
374 asmshader_lval.regnum = 0;
376 asmshader_lval.regnum = atoi(yytext + strlen("_binormal"));
378 return USAGE_BINORMAL;
381 if(yytext[strlen("_tessfactor")] == '\0') {
382 asmshader_lval.regnum = 0;
384 asmshader_lval.regnum = atoi(yytext + strlen("_tessfactor"));
386 return USAGE_TESSFACTOR;
389 if(yytext[strlen("_positiont")] == '\0') {
390 asmshader_lval.regnum = 0;
392 asmshader_lval.regnum = atoi(yytext + strlen("_positiont"));
394 return USAGE_POSITIONT;
397 if(yytext[strlen("_color")] == '\0') {
398 asmshader_lval.regnum = 0;
400 asmshader_lval.regnum = atoi(yytext + strlen("_color"));
405 if(yytext[strlen("_fog")] == '\0') {
406 asmshader_lval.regnum = 0;
408 asmshader_lval.regnum = atoi(yytext + strlen("_fog"));
413 if(yytext[strlen("_depth")] == '\0') {
414 asmshader_lval.regnum = 0;
416 asmshader_lval.regnum = atoi(yytext + strlen("_depth"));
421 if(yytext[strlen("_sample")] == '\0') {
422 asmshader_lval.regnum = 0;
424 asmshader_lval.regnum = atoi(yytext + strlen("_sample"));
429 {DCL_SAMPLER1D} { return SAMPTYPE_1D; }
430 {DCL_SAMPLER2D} { return SAMPTYPE_2D; }
431 {DCL_SAMPLERCUBE} { return SAMPTYPE_CUBE; }
432 {DCL_SAMPLERVOLUME} { return SAMPTYPE_VOLUME; }
434 {PREPROCESSORDIRECTIVE} {
435 /* TODO: update current line information */
436 TRACE("line info update: %s", yytext);
440 {DOUBLESLASHCOMMENT} { }
441 {SEMICOLONCOMMENT} { }
443 {WHITESPACE} { /* Do nothing */ }
449 asmparser_message(&asm_ctx, "Line %u: Unexpected input %s\n", asm_ctx.line_no, yytext);
450 set_parse_status(&asm_ctx, PARSE_ERR);
455 struct bwriter_shader *SlAssembleShader(const char *text, char **messages) {
456 struct bwriter_shader *ret = NULL;
457 YY_BUFFER_STATE buffer;
458 TRACE("%p, %p\n", text, messages);
460 buffer = asmshader__scan_string(text);
461 asmshader__switch_to_buffer(buffer);
463 ret = parse_asm_shader(messages);
465 asmshader__delete_buffer(buffer);