* Sync up to trunk head (r64377).
[reactos.git] / dll / directx / wine / d3dcompiler_43 / bytecodewriter.c
1 /*
2 * Direct3D bytecode output functions
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 "d3dcompiler_private.h"
24 #include "d3d9types.h"
25
26 WINE_DEFAULT_DEBUG_CHANNEL(bytecodewriter);
27
28 /****************************************************************
29 * General assembler shader construction helper routines follow *
30 ****************************************************************/
31 /* struct instruction *alloc_instr
32 *
33 * Allocates a new instruction structure with srcs registers
34 *
35 * Parameters:
36 * srcs: Number of source registers to allocate
37 *
38 * Returns:
39 * A pointer to the allocated instruction structure
40 * NULL in case of an allocation failure
41 */
42 struct instruction *alloc_instr(unsigned int srcs) {
43 struct instruction *ret = d3dcompiler_alloc(sizeof(*ret));
44 if(!ret) {
45 ERR("Failed to allocate memory for an instruction structure\n");
46 return NULL;
47 }
48
49 if(srcs) {
50 ret->src = d3dcompiler_alloc(srcs * sizeof(*ret->src));
51 if(!ret->src) {
52 ERR("Failed to allocate memory for instruction registers\n");
53 d3dcompiler_free(ret);
54 return NULL;
55 }
56 ret->num_srcs = srcs;
57 }
58 return ret;
59 }
60
61 /* void add_instruction
62 *
63 * Adds a new instruction to the shader's instructions array and grows the instruction array
64 * if needed.
65 *
66 * The function does NOT copy the instruction structure. Make sure not to release the
67 * instruction or any of its substructures like registers.
68 *
69 * Parameters:
70 * shader: Shader to add the instruction to
71 * instr: Instruction to add to the shader
72 */
73 BOOL add_instruction(struct bwriter_shader *shader, struct instruction *instr) {
74 struct instruction **new_instructions;
75
76 if(!shader) return FALSE;
77
78 if(shader->instr_alloc_size == 0) {
79 shader->instr = d3dcompiler_alloc(sizeof(*shader->instr) * INSTRARRAY_INITIAL_SIZE);
80 if(!shader->instr) {
81 ERR("Failed to allocate the shader instruction array\n");
82 return FALSE;
83 }
84 shader->instr_alloc_size = INSTRARRAY_INITIAL_SIZE;
85 } else if(shader->instr_alloc_size == shader->num_instrs) {
86 new_instructions = d3dcompiler_realloc(shader->instr,
87 sizeof(*shader->instr) * (shader->instr_alloc_size) * 2);
88 if(!new_instructions) {
89 ERR("Failed to grow the shader instruction array\n");
90 return FALSE;
91 }
92 shader->instr = new_instructions;
93 shader->instr_alloc_size = shader->instr_alloc_size * 2;
94 } else if(shader->num_instrs > shader->instr_alloc_size) {
95 ERR("More instructions than allocated. This should not happen\n");
96 return FALSE;
97 }
98
99 shader->instr[shader->num_instrs] = instr;
100 shader->num_instrs++;
101 return TRUE;
102 }
103
104 BOOL add_constF(struct bwriter_shader *shader, DWORD reg, float x, float y, float z, float w) {
105 struct constant *newconst;
106
107 if(shader->num_cf) {
108 struct constant **newarray;
109 newarray = d3dcompiler_realloc(shader->constF,
110 sizeof(*shader->constF) * (shader->num_cf + 1));
111 if(!newarray) {
112 ERR("Failed to grow the constants array\n");
113 return FALSE;
114 }
115 shader->constF = newarray;
116 } else {
117 shader->constF = d3dcompiler_alloc(sizeof(*shader->constF));
118 if(!shader->constF) {
119 ERR("Failed to allocate the constants array\n");
120 return FALSE;
121 }
122 }
123
124 newconst = d3dcompiler_alloc(sizeof(*newconst));
125 if(!newconst) {
126 ERR("Failed to allocate a new constant\n");
127 return FALSE;
128 }
129 newconst->regnum = reg;
130 newconst->value[0].f = x;
131 newconst->value[1].f = y;
132 newconst->value[2].f = z;
133 newconst->value[3].f = w;
134 shader->constF[shader->num_cf] = newconst;
135
136 shader->num_cf++;
137 return TRUE;
138 }
139
140 BOOL add_constI(struct bwriter_shader *shader, DWORD reg, INT x, INT y, INT z, INT w) {
141 struct constant *newconst;
142
143 if(shader->num_ci) {
144 struct constant **newarray;
145 newarray = d3dcompiler_realloc(shader->constI,
146 sizeof(*shader->constI) * (shader->num_ci + 1));
147 if(!newarray) {
148 ERR("Failed to grow the constants array\n");
149 return FALSE;
150 }
151 shader->constI = newarray;
152 } else {
153 shader->constI = d3dcompiler_alloc(sizeof(*shader->constI));
154 if(!shader->constI) {
155 ERR("Failed to allocate the constants array\n");
156 return FALSE;
157 }
158 }
159
160 newconst = d3dcompiler_alloc(sizeof(*newconst));
161 if(!newconst) {
162 ERR("Failed to allocate a new constant\n");
163 return FALSE;
164 }
165 newconst->regnum = reg;
166 newconst->value[0].i = x;
167 newconst->value[1].i = y;
168 newconst->value[2].i = z;
169 newconst->value[3].i = w;
170 shader->constI[shader->num_ci] = newconst;
171
172 shader->num_ci++;
173 return TRUE;
174 }
175
176 BOOL add_constB(struct bwriter_shader *shader, DWORD reg, BOOL x) {
177 struct constant *newconst;
178
179 if(shader->num_cb) {
180 struct constant **newarray;
181 newarray = d3dcompiler_realloc(shader->constB,
182 sizeof(*shader->constB) * (shader->num_cb + 1));
183 if(!newarray) {
184 ERR("Failed to grow the constants array\n");
185 return FALSE;
186 }
187 shader->constB = newarray;
188 } else {
189 shader->constB = d3dcompiler_alloc(sizeof(*shader->constB));
190 if(!shader->constB) {
191 ERR("Failed to allocate the constants array\n");
192 return FALSE;
193 }
194 }
195
196 newconst = d3dcompiler_alloc(sizeof(*newconst));
197 if(!newconst) {
198 ERR("Failed to allocate a new constant\n");
199 return FALSE;
200 }
201 newconst->regnum = reg;
202 newconst->value[0].b = x;
203 shader->constB[shader->num_cb] = newconst;
204
205 shader->num_cb++;
206 return TRUE;
207 }
208
209 BOOL record_declaration(struct bwriter_shader *shader, DWORD usage,
210 DWORD usage_idx, DWORD mod, BOOL output,
211 DWORD regnum, DWORD writemask, BOOL builtin) {
212 unsigned int *num;
213 struct declaration **decl;
214 unsigned int i;
215
216 if(!shader) return FALSE;
217
218 if(output) {
219 num = &shader->num_outputs;
220 decl = &shader->outputs;
221 } else {
222 num = &shader->num_inputs;
223 decl = &shader->inputs;
224 }
225
226 if(*num == 0) {
227 *decl = d3dcompiler_alloc(sizeof(**decl));
228 if(!*decl) {
229 ERR("Error allocating declarations array\n");
230 return FALSE;
231 }
232 } else {
233 struct declaration *newdecl;
234 for(i = 0; i < *num; i++) {
235 if((*decl)[i].regnum == regnum && ((*decl)[i].writemask & writemask)) {
236 WARN("Declaration of register %u already exists, writemask match 0x%x\n",
237 regnum, (*decl)[i].writemask & writemask);
238 }
239 }
240
241 newdecl = d3dcompiler_realloc(*decl,
242 sizeof(**decl) * ((*num) + 1));
243 if(!newdecl) {
244 ERR("Error reallocating declarations array\n");
245 return FALSE;
246 }
247 *decl = newdecl;
248 }
249 (*decl)[*num].usage = usage;
250 (*decl)[*num].usage_idx = usage_idx;
251 (*decl)[*num].regnum = regnum;
252 (*decl)[*num].mod = mod;
253 (*decl)[*num].writemask = writemask;
254 (*decl)[*num].builtin = builtin;
255 (*num)++;
256
257 return TRUE;
258 }
259
260 BOOL record_sampler(struct bwriter_shader *shader, DWORD samptype, DWORD mod, DWORD regnum) {
261 unsigned int i;
262
263 if(!shader) return FALSE;
264
265 if(shader->num_samplers == 0) {
266 shader->samplers = d3dcompiler_alloc(sizeof(*shader->samplers));
267 if(!shader->samplers) {
268 ERR("Error allocating samplers array\n");
269 return FALSE;
270 }
271 } else {
272 struct samplerdecl *newarray;
273
274 for(i = 0; i < shader->num_samplers; i++) {
275 if(shader->samplers[i].regnum == regnum) {
276 WARN("Sampler %u already declared\n", regnum);
277 /* This is not an error as far as the assembler is concerned.
278 * Direct3D might refuse to load the compiled shader though
279 */
280 }
281 }
282
283 newarray = d3dcompiler_realloc(shader->samplers,
284 sizeof(*shader->samplers) * (shader->num_samplers + 1));
285 if(!newarray) {
286 ERR("Error reallocating samplers array\n");
287 return FALSE;
288 }
289 shader->samplers = newarray;
290 }
291
292 shader->samplers[shader->num_samplers].type = samptype;
293 shader->samplers[shader->num_samplers].mod = mod;
294 shader->samplers[shader->num_samplers].regnum = regnum;
295 shader->num_samplers++;
296 return TRUE;
297 }
298
299
300 /* shader bytecode buffer manipulation functions.
301 * allocate_buffer creates a new buffer structure, put_dword adds a new
302 * DWORD to the buffer. In the rare case of a memory allocation failure
303 * when trying to grow the buffer a flag is set in the buffer to mark it
304 * invalid. This avoids return value checking and passing in many places
305 */
306 static struct bytecode_buffer *allocate_buffer(void) {
307 struct bytecode_buffer *ret;
308
309 ret = d3dcompiler_alloc(sizeof(*ret));
310 if(!ret) return NULL;
311
312 ret->alloc_size = BYTECODEBUFFER_INITIAL_SIZE;
313 ret->data = d3dcompiler_alloc(sizeof(DWORD) * ret->alloc_size);
314 if(!ret->data) {
315 d3dcompiler_free(ret);
316 return NULL;
317 }
318 ret->state = S_OK;
319 return ret;
320 }
321
322 static void put_dword(struct bytecode_buffer *buffer, DWORD value) {
323 if(FAILED(buffer->state)) return;
324
325 if(buffer->alloc_size == buffer->size) {
326 DWORD *newarray;
327 buffer->alloc_size *= 2;
328 newarray = d3dcompiler_realloc(buffer->data,
329 sizeof(DWORD) * buffer->alloc_size);
330 if(!newarray) {
331 ERR("Failed to grow the buffer data memory\n");
332 buffer->state = E_OUTOFMEMORY;
333 return;
334 }
335 buffer->data = newarray;
336 }
337 buffer->data[buffer->size++] = value;
338 }
339
340 /* bwriter -> d3d9 conversion functions. */
341 static DWORD d3d9_swizzle(DWORD bwriter_swizzle)
342 {
343 /* Currently a NOP, but this allows changing the internal definitions
344 * without side effects. */
345 DWORD ret = 0;
346
347 if ((bwriter_swizzle & BWRITERVS_X_X) == BWRITERVS_X_X) ret |= D3DVS_X_X;
348 if ((bwriter_swizzle & BWRITERVS_X_Y) == BWRITERVS_X_Y) ret |= D3DVS_X_Y;
349 if ((bwriter_swizzle & BWRITERVS_X_Z) == BWRITERVS_X_Z) ret |= D3DVS_X_Z;
350 if ((bwriter_swizzle & BWRITERVS_X_W) == BWRITERVS_X_W) ret |= D3DVS_X_W;
351
352 if ((bwriter_swizzle & BWRITERVS_Y_X) == BWRITERVS_Y_X) ret |= D3DVS_Y_X;
353 if ((bwriter_swizzle & BWRITERVS_Y_Y) == BWRITERVS_Y_Y) ret |= D3DVS_Y_Y;
354 if ((bwriter_swizzle & BWRITERVS_Y_Z) == BWRITERVS_Y_Z) ret |= D3DVS_Y_Z;
355 if ((bwriter_swizzle & BWRITERVS_Y_W) == BWRITERVS_Y_W) ret |= D3DVS_Y_W;
356
357 if ((bwriter_swizzle & BWRITERVS_Z_X) == BWRITERVS_Z_X) ret |= D3DVS_Z_X;
358 if ((bwriter_swizzle & BWRITERVS_Z_Y) == BWRITERVS_Z_Y) ret |= D3DVS_Z_Y;
359 if ((bwriter_swizzle & BWRITERVS_Z_Z) == BWRITERVS_Z_Z) ret |= D3DVS_Z_Z;
360 if ((bwriter_swizzle & BWRITERVS_Z_W) == BWRITERVS_Z_W) ret |= D3DVS_Z_W;
361
362 if ((bwriter_swizzle & BWRITERVS_W_X) == BWRITERVS_W_X) ret |= D3DVS_W_X;
363 if ((bwriter_swizzle & BWRITERVS_W_Y) == BWRITERVS_W_Y) ret |= D3DVS_W_Y;
364 if ((bwriter_swizzle & BWRITERVS_W_Z) == BWRITERVS_W_Z) ret |= D3DVS_W_Z;
365 if ((bwriter_swizzle & BWRITERVS_W_W) == BWRITERVS_W_W) ret |= D3DVS_W_W;
366
367 return ret;
368 }
369
370 static DWORD d3d9_writemask(DWORD bwriter_writemask)
371 {
372 DWORD ret = 0;
373
374 if (bwriter_writemask & BWRITERSP_WRITEMASK_0) ret |= D3DSP_WRITEMASK_0;
375 if (bwriter_writemask & BWRITERSP_WRITEMASK_1) ret |= D3DSP_WRITEMASK_1;
376 if (bwriter_writemask & BWRITERSP_WRITEMASK_2) ret |= D3DSP_WRITEMASK_2;
377 if (bwriter_writemask & BWRITERSP_WRITEMASK_3) ret |= D3DSP_WRITEMASK_3;
378
379 return ret;
380 }
381
382 static DWORD d3d9_srcmod(DWORD bwriter_srcmod)
383 {
384 switch (bwriter_srcmod)
385 {
386 case BWRITERSPSM_NONE: return D3DSPSM_NONE;
387 case BWRITERSPSM_NEG: return D3DSPSM_NEG;
388 case BWRITERSPSM_BIAS: return D3DSPSM_BIAS;
389 case BWRITERSPSM_BIASNEG: return D3DSPSM_BIASNEG;
390 case BWRITERSPSM_SIGN: return D3DSPSM_SIGN;
391 case BWRITERSPSM_SIGNNEG: return D3DSPSM_SIGNNEG;
392 case BWRITERSPSM_COMP: return D3DSPSM_COMP;
393 case BWRITERSPSM_X2: return D3DSPSM_X2;
394 case BWRITERSPSM_X2NEG: return D3DSPSM_X2NEG;
395 case BWRITERSPSM_DZ: return D3DSPSM_DZ;
396 case BWRITERSPSM_DW: return D3DSPSM_DW;
397 case BWRITERSPSM_ABS: return D3DSPSM_ABS;
398 case BWRITERSPSM_ABSNEG: return D3DSPSM_ABSNEG;
399 case BWRITERSPSM_NOT: return D3DSPSM_NOT;
400 default:
401 FIXME("Unhandled BWRITERSPSM token %#x.\n", bwriter_srcmod);
402 return 0;
403 }
404 }
405
406 static DWORD d3d9_dstmod(DWORD bwriter_mod)
407 {
408 DWORD ret = 0;
409
410 if (bwriter_mod & BWRITERSPDM_SATURATE) ret |= D3DSPDM_SATURATE;
411 if (bwriter_mod & BWRITERSPDM_PARTIALPRECISION) ret |= D3DSPDM_PARTIALPRECISION;
412 if (bwriter_mod & BWRITERSPDM_MSAMPCENTROID) ret |= D3DSPDM_MSAMPCENTROID;
413
414 return ret;
415 }
416
417 static DWORD d3d9_comparetype(DWORD asmshader_comparetype)
418 {
419 switch (asmshader_comparetype)
420 {
421 case BWRITER_COMPARISON_GT: return D3DSPC_GT;
422 case BWRITER_COMPARISON_EQ: return D3DSPC_EQ;
423 case BWRITER_COMPARISON_GE: return D3DSPC_GE;
424 case BWRITER_COMPARISON_LT: return D3DSPC_LT;
425 case BWRITER_COMPARISON_NE: return D3DSPC_NE;
426 case BWRITER_COMPARISON_LE: return D3DSPC_LE;
427 default:
428 FIXME("Unexpected BWRITER_COMPARISON type %#x.\n", asmshader_comparetype);
429 return 0;
430 }
431 }
432
433 static DWORD d3d9_sampler(DWORD bwriter_sampler)
434 {
435 if (bwriter_sampler == BWRITERSTT_UNKNOWN) return D3DSTT_UNKNOWN;
436 if (bwriter_sampler == BWRITERSTT_1D) return D3DSTT_1D;
437 if (bwriter_sampler == BWRITERSTT_2D) return D3DSTT_2D;
438 if (bwriter_sampler == BWRITERSTT_CUBE) return D3DSTT_CUBE;
439 if (bwriter_sampler == BWRITERSTT_VOLUME) return D3DSTT_VOLUME;
440 FIXME("Unexpected BWRITERSAMPLER_TEXTURE_TYPE type %#x.\n", bwriter_sampler);
441
442 return 0;
443 }
444
445 static DWORD d3d9_register(DWORD bwriter_register)
446 {
447 if (bwriter_register == BWRITERSPR_TEMP) return D3DSPR_TEMP;
448 if (bwriter_register == BWRITERSPR_INPUT) return D3DSPR_INPUT;
449 if (bwriter_register == BWRITERSPR_CONST) return D3DSPR_CONST;
450 if (bwriter_register == BWRITERSPR_ADDR) return D3DSPR_ADDR;
451 if (bwriter_register == BWRITERSPR_TEXTURE) return D3DSPR_TEXTURE;
452 if (bwriter_register == BWRITERSPR_RASTOUT) return D3DSPR_RASTOUT;
453 if (bwriter_register == BWRITERSPR_ATTROUT) return D3DSPR_ATTROUT;
454 if (bwriter_register == BWRITERSPR_TEXCRDOUT) return D3DSPR_TEXCRDOUT;
455 if (bwriter_register == BWRITERSPR_OUTPUT) return D3DSPR_OUTPUT;
456 if (bwriter_register == BWRITERSPR_CONSTINT) return D3DSPR_CONSTINT;
457 if (bwriter_register == BWRITERSPR_COLOROUT) return D3DSPR_COLOROUT;
458 if (bwriter_register == BWRITERSPR_DEPTHOUT) return D3DSPR_DEPTHOUT;
459 if (bwriter_register == BWRITERSPR_SAMPLER) return D3DSPR_SAMPLER;
460 if (bwriter_register == BWRITERSPR_CONSTBOOL) return D3DSPR_CONSTBOOL;
461 if (bwriter_register == BWRITERSPR_LOOP) return D3DSPR_LOOP;
462 if (bwriter_register == BWRITERSPR_MISCTYPE) return D3DSPR_MISCTYPE;
463 if (bwriter_register == BWRITERSPR_LABEL) return D3DSPR_LABEL;
464 if (bwriter_register == BWRITERSPR_PREDICATE) return D3DSPR_PREDICATE;
465
466 FIXME("Unexpected BWRITERSPR %#x.\n", bwriter_register);
467 return ~0U;
468 }
469
470 static DWORD d3d9_opcode(DWORD bwriter_opcode)
471 {
472 switch (bwriter_opcode)
473 {
474 case BWRITERSIO_NOP: return D3DSIO_NOP;
475 case BWRITERSIO_MOV: return D3DSIO_MOV;
476 case BWRITERSIO_ADD: return D3DSIO_ADD;
477 case BWRITERSIO_SUB: return D3DSIO_SUB;
478 case BWRITERSIO_MAD: return D3DSIO_MAD;
479 case BWRITERSIO_MUL: return D3DSIO_MUL;
480 case BWRITERSIO_RCP: return D3DSIO_RCP;
481 case BWRITERSIO_RSQ: return D3DSIO_RSQ;
482 case BWRITERSIO_DP3: return D3DSIO_DP3;
483 case BWRITERSIO_DP4: return D3DSIO_DP4;
484 case BWRITERSIO_MIN: return D3DSIO_MIN;
485 case BWRITERSIO_MAX: return D3DSIO_MAX;
486 case BWRITERSIO_SLT: return D3DSIO_SLT;
487 case BWRITERSIO_SGE: return D3DSIO_SGE;
488 case BWRITERSIO_EXP: return D3DSIO_EXP;
489 case BWRITERSIO_LOG: return D3DSIO_LOG;
490 case BWRITERSIO_LIT: return D3DSIO_LIT;
491 case BWRITERSIO_DST: return D3DSIO_DST;
492 case BWRITERSIO_LRP: return D3DSIO_LRP;
493 case BWRITERSIO_FRC: return D3DSIO_FRC;
494 case BWRITERSIO_M4x4: return D3DSIO_M4x4;
495 case BWRITERSIO_M4x3: return D3DSIO_M4x3;
496 case BWRITERSIO_M3x4: return D3DSIO_M3x4;
497 case BWRITERSIO_M3x3: return D3DSIO_M3x3;
498 case BWRITERSIO_M3x2: return D3DSIO_M3x2;
499 case BWRITERSIO_CALL: return D3DSIO_CALL;
500 case BWRITERSIO_CALLNZ: return D3DSIO_CALLNZ;
501 case BWRITERSIO_LOOP: return D3DSIO_LOOP;
502 case BWRITERSIO_RET: return D3DSIO_RET;
503 case BWRITERSIO_ENDLOOP: return D3DSIO_ENDLOOP;
504 case BWRITERSIO_LABEL: return D3DSIO_LABEL;
505 case BWRITERSIO_DCL: return D3DSIO_DCL;
506 case BWRITERSIO_POW: return D3DSIO_POW;
507 case BWRITERSIO_CRS: return D3DSIO_CRS;
508 case BWRITERSIO_SGN: return D3DSIO_SGN;
509 case BWRITERSIO_ABS: return D3DSIO_ABS;
510 case BWRITERSIO_NRM: return D3DSIO_NRM;
511 case BWRITERSIO_SINCOS: return D3DSIO_SINCOS;
512 case BWRITERSIO_REP: return D3DSIO_REP;
513 case BWRITERSIO_ENDREP: return D3DSIO_ENDREP;
514 case BWRITERSIO_IF: return D3DSIO_IF;
515 case BWRITERSIO_IFC: return D3DSIO_IFC;
516 case BWRITERSIO_ELSE: return D3DSIO_ELSE;
517 case BWRITERSIO_ENDIF: return D3DSIO_ENDIF;
518 case BWRITERSIO_BREAK: return D3DSIO_BREAK;
519 case BWRITERSIO_BREAKC: return D3DSIO_BREAKC;
520 case BWRITERSIO_MOVA: return D3DSIO_MOVA;
521 case BWRITERSIO_DEFB: return D3DSIO_DEFB;
522 case BWRITERSIO_DEFI: return D3DSIO_DEFI;
523
524 case BWRITERSIO_TEXCOORD: return D3DSIO_TEXCOORD;
525 case BWRITERSIO_TEXKILL: return D3DSIO_TEXKILL;
526 case BWRITERSIO_TEX: return D3DSIO_TEX;
527 case BWRITERSIO_TEXBEM: return D3DSIO_TEXBEM;
528 case BWRITERSIO_TEXBEML: return D3DSIO_TEXBEML;
529 case BWRITERSIO_TEXREG2AR: return D3DSIO_TEXREG2AR;
530 case BWRITERSIO_TEXREG2GB: return D3DSIO_TEXREG2GB;
531 case BWRITERSIO_TEXM3x2PAD: return D3DSIO_TEXM3x2PAD;
532 case BWRITERSIO_TEXM3x2TEX: return D3DSIO_TEXM3x2TEX;
533 case BWRITERSIO_TEXM3x3PAD: return D3DSIO_TEXM3x3PAD;
534 case BWRITERSIO_TEXM3x3TEX: return D3DSIO_TEXM3x3TEX;
535 case BWRITERSIO_TEXM3x3SPEC: return D3DSIO_TEXM3x3SPEC;
536 case BWRITERSIO_TEXM3x3VSPEC:return D3DSIO_TEXM3x3VSPEC;
537 case BWRITERSIO_EXPP: return D3DSIO_EXPP;
538 case BWRITERSIO_LOGP: return D3DSIO_LOGP;
539 case BWRITERSIO_CND: return D3DSIO_CND;
540 case BWRITERSIO_DEF: return D3DSIO_DEF;
541 case BWRITERSIO_TEXREG2RGB: return D3DSIO_TEXREG2RGB;
542 case BWRITERSIO_TEXDP3TEX: return D3DSIO_TEXDP3TEX;
543 case BWRITERSIO_TEXM3x2DEPTH:return D3DSIO_TEXM3x2DEPTH;
544 case BWRITERSIO_TEXDP3: return D3DSIO_TEXDP3;
545 case BWRITERSIO_TEXM3x3: return D3DSIO_TEXM3x3;
546 case BWRITERSIO_TEXDEPTH: return D3DSIO_TEXDEPTH;
547 case BWRITERSIO_CMP: return D3DSIO_CMP;
548 case BWRITERSIO_BEM: return D3DSIO_BEM;
549 case BWRITERSIO_DP2ADD: return D3DSIO_DP2ADD;
550 case BWRITERSIO_DSX: return D3DSIO_DSX;
551 case BWRITERSIO_DSY: return D3DSIO_DSY;
552 case BWRITERSIO_TEXLDD: return D3DSIO_TEXLDD;
553 case BWRITERSIO_SETP: return D3DSIO_SETP;
554 case BWRITERSIO_TEXLDL: return D3DSIO_TEXLDL;
555 case BWRITERSIO_BREAKP: return D3DSIO_BREAKP;
556
557 case BWRITERSIO_PHASE: return D3DSIO_PHASE;
558 case BWRITERSIO_COMMENT: return D3DSIO_COMMENT;
559 case BWRITERSIO_END: return D3DSIO_END;
560
561 case BWRITERSIO_TEXLDP: return D3DSIO_TEX | D3DSI_TEXLD_PROJECT;
562 case BWRITERSIO_TEXLDB: return D3DSIO_TEX | D3DSI_TEXLD_BIAS;
563
564 default:
565 FIXME("Unhandled BWRITERSIO token %#x.\n", bwriter_opcode);
566 return ~0U;
567 }
568 }
569
570 /******************************************************
571 * Implementation of the writer functions starts here *
572 ******************************************************/
573 static void write_declarations(struct bc_writer *This,
574 struct bytecode_buffer *buffer, BOOL len,
575 const struct declaration *decls, unsigned int num, DWORD type) {
576 DWORD i;
577 DWORD instr_dcl = D3DSIO_DCL;
578 DWORD token;
579 struct shader_reg reg;
580
581 ZeroMemory(&reg, sizeof(reg));
582
583 if(len) {
584 instr_dcl |= 2 << D3DSI_INSTLENGTH_SHIFT;
585 }
586
587 for(i = 0; i < num; i++) {
588 if(decls[i].builtin) continue;
589
590 /* Write the DCL instruction */
591 put_dword(buffer, instr_dcl);
592
593 /* Write the usage and index */
594 token = (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
595 token |= (decls[i].usage << D3DSP_DCL_USAGE_SHIFT) & D3DSP_DCL_USAGE_MASK;
596 token |= (decls[i].usage_idx << D3DSP_DCL_USAGEINDEX_SHIFT) & D3DSP_DCL_USAGEINDEX_MASK;
597 put_dword(buffer, token);
598
599 /* Write the dest register */
600 reg.type = type;
601 reg.regnum = decls[i].regnum;
602 reg.u.writemask = decls[i].writemask;
603 This->funcs->dstreg(This, &reg, buffer, 0, decls[i].mod);
604 }
605 }
606
607 static void write_const(struct constant **consts, int num, DWORD opcode, DWORD reg_type, struct bytecode_buffer *buffer, BOOL len) {
608 int i;
609 DWORD instr_def = opcode;
610 const DWORD reg = (1<<31) |
611 ((reg_type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) |
612 ((reg_type << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) |
613 D3DSP_WRITEMASK_ALL;
614
615 if(len) {
616 if(opcode == D3DSIO_DEFB)
617 instr_def |= 2 << D3DSI_INSTLENGTH_SHIFT;
618 else
619 instr_def |= 5 << D3DSI_INSTLENGTH_SHIFT;
620 }
621
622 for(i = 0; i < num; i++) {
623 /* Write the DEF instruction */
624 put_dword(buffer, instr_def);
625
626 put_dword(buffer, reg | (consts[i]->regnum & D3DSP_REGNUM_MASK));
627 put_dword(buffer, consts[i]->value[0].d);
628 if(opcode != D3DSIO_DEFB) {
629 put_dword(buffer, consts[i]->value[1].d);
630 put_dword(buffer, consts[i]->value[2].d);
631 put_dword(buffer, consts[i]->value[3].d);
632 }
633 }
634 }
635
636 static void write_constF(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
637 write_const(shader->constF, shader->num_cf, D3DSIO_DEF, D3DSPR_CONST, buffer, len);
638 }
639
640 /* This function looks for VS 1/2 registers mapping to VS 3 output registers */
641 static HRESULT vs_find_builtin_varyings(struct bc_writer *This, const struct bwriter_shader *shader) {
642 DWORD i;
643 DWORD usage, usage_idx, writemask, regnum;
644
645 for(i = 0; i < shader->num_outputs; i++) {
646 if(!shader->outputs[i].builtin) continue;
647
648 usage = shader->outputs[i].usage;
649 usage_idx = shader->outputs[i].usage_idx;
650 writemask = shader->outputs[i].writemask;
651 regnum = shader->outputs[i].regnum;
652
653 switch(usage) {
654 case BWRITERDECLUSAGE_POSITION:
655 case BWRITERDECLUSAGE_POSITIONT:
656 if(usage_idx > 0) {
657 WARN("dcl_position%u not supported in sm 1/2 shaders\n", usage_idx);
658 return E_INVALIDARG;
659 }
660 TRACE("o%u is oPos\n", regnum);
661 This->oPos_regnum = regnum;
662 break;
663
664 case BWRITERDECLUSAGE_COLOR:
665 if(usage_idx > 1) {
666 WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx);
667 return E_INVALIDARG;
668 }
669 if(writemask != BWRITERSP_WRITEMASK_ALL) {
670 WARN("Only WRITEMASK_ALL is supported on color in sm 1/2\n");
671 return E_INVALIDARG;
672 }
673 TRACE("o%u is oD%u\n", regnum, usage_idx);
674 This->oD_regnum[usage_idx] = regnum;
675 break;
676
677 case BWRITERDECLUSAGE_TEXCOORD:
678 if(usage_idx >= 8) {
679 WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx);
680 return E_INVALIDARG;
681 }
682 if(writemask != (BWRITERSP_WRITEMASK_0) &&
683 writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1) &&
684 writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1 | BWRITERSP_WRITEMASK_2) &&
685 writemask != (BWRITERSP_WRITEMASK_ALL)) {
686 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
687 return E_INVALIDARG;
688 }
689 TRACE("o%u is oT%u\n", regnum, usage_idx);
690 This->oT_regnum[usage_idx] = regnum;
691 break;
692
693 case BWRITERDECLUSAGE_PSIZE:
694 if(usage_idx > 0) {
695 WARN("dcl_psize%u not supported in sm 1/2 shaders\n", usage_idx);
696 return E_INVALIDARG;
697 }
698 TRACE("o%u writemask 0x%08x is oPts\n", regnum, writemask);
699 This->oPts_regnum = regnum;
700 This->oPts_mask = writemask;
701 break;
702
703 case BWRITERDECLUSAGE_FOG:
704 if(usage_idx > 0) {
705 WARN("dcl_fog%u not supported in sm 1 shaders\n", usage_idx);
706 return E_INVALIDARG;
707 }
708 if(writemask != BWRITERSP_WRITEMASK_0 && writemask != BWRITERSP_WRITEMASK_1 &&
709 writemask != BWRITERSP_WRITEMASK_2 && writemask != BWRITERSP_WRITEMASK_3) {
710 WARN("Unsupported fog writemask\n");
711 return E_INVALIDARG;
712 }
713 TRACE("o%u writemask 0x%08x is oFog\n", regnum, writemask);
714 This->oFog_regnum = regnum;
715 This->oFog_mask = writemask;
716 break;
717
718 default:
719 WARN("Varying type %u is not supported in shader model 1.x\n", usage);
720 return E_INVALIDARG;
721 }
722 }
723
724 return S_OK;
725 }
726
727 static void vs_1_x_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
728 HRESULT hr;
729
730 if(shader->num_ci || shader->num_cb) {
731 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
732 WARN("Got %u int and %u boolean constants\n", shader->num_ci, shader->num_cb);
733 This->state = E_INVALIDARG;
734 return;
735 }
736
737 hr = vs_find_builtin_varyings(This, shader);
738 if(FAILED(hr)) {
739 This->state = hr;
740 return;
741 }
742
743 write_declarations(This, buffer, FALSE, shader->inputs, shader->num_inputs, BWRITERSPR_INPUT);
744 write_constF(shader, buffer, FALSE);
745 }
746
747 static HRESULT find_ps_builtin_semantics(struct bc_writer *This,
748 const struct bwriter_shader *shader,
749 DWORD texcoords) {
750 DWORD i;
751 DWORD usage, usage_idx, writemask, regnum;
752
753 This->v_regnum[0] = -1; This->v_regnum[1] = -1;
754 for(i = 0; i < 8; i++) This->t_regnum[i] = -1;
755
756 for(i = 0; i < shader->num_inputs; i++) {
757 if(!shader->inputs[i].builtin) continue;
758
759 usage = shader->inputs[i].usage;
760 usage_idx = shader->inputs[i].usage_idx;
761 writemask = shader->inputs[i].writemask;
762 regnum = shader->inputs[i].regnum;
763
764 switch(usage) {
765 case BWRITERDECLUSAGE_COLOR:
766 if(usage_idx > 1) {
767 WARN("dcl_color%u not supported in sm 1 shaders\n", usage_idx);
768 return E_INVALIDARG;
769 }
770 if(writemask != BWRITERSP_WRITEMASK_ALL) {
771 WARN("Only WRITEMASK_ALL is supported on color in sm 1\n");
772 return E_INVALIDARG;
773 }
774 TRACE("v%u is v%u\n", regnum, usage_idx);
775 This->v_regnum[usage_idx] = regnum;
776 break;
777
778 case BWRITERDECLUSAGE_TEXCOORD:
779 if(usage_idx > texcoords) {
780 WARN("dcl_texcoord%u not supported in this shader version\n", usage_idx);
781 return E_INVALIDARG;
782 }
783 if(writemask != (BWRITERSP_WRITEMASK_0) &&
784 writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1) &&
785 writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1 | BWRITERSP_WRITEMASK_2) &&
786 writemask != (BWRITERSP_WRITEMASK_ALL)) {
787 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
788 } else {
789 writemask = BWRITERSP_WRITEMASK_ALL;
790 }
791 TRACE("v%u is t%u\n", regnum, usage_idx);
792 This->t_regnum[usage_idx] = regnum;
793 break;
794
795 default:
796 WARN("Varying type %u is not supported in shader model 1.x\n", usage);
797 return E_INVALIDARG;
798 }
799 }
800
801 return S_OK;
802 }
803
804 static void ps_1_x_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
805 HRESULT hr;
806
807 /* First check the constants and varyings, and complain if unsupported things are used */
808 if(shader->num_ci || shader->num_cb) {
809 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
810 WARN("Got %u int and %u boolean constants\n", shader->num_ci, shader->num_cb);
811 This->state = E_INVALIDARG;
812 return;
813 }
814
815 hr = find_ps_builtin_semantics(This, shader, 4);
816 if(FAILED(hr)) {
817 This->state = hr;
818 return;
819 }
820
821 write_constF(shader, buffer, FALSE);
822 }
823
824 static void ps_1_4_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
825 HRESULT hr;
826
827 /* First check the constants and varyings, and complain if unsupported things are used */
828 if(shader->num_ci || shader->num_cb) {
829 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
830 WARN("Got %u int and %u boolean constants\n", shader->num_ci, shader->num_cb);
831 This->state = E_INVALIDARG;
832 return;
833 }
834 hr = find_ps_builtin_semantics(This, shader, 6);
835 if(FAILED(hr)) {
836 This->state = hr;
837 return;
838 }
839
840 write_constF(shader, buffer, FALSE);
841 }
842
843 static void end(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
844 put_dword(buffer, D3DSIO_END);
845 }
846
847 static DWORD map_vs_output(struct bc_writer *This, DWORD regnum, DWORD mask, DWORD *has_components) {
848 DWORD token = 0;
849 DWORD i;
850
851 *has_components = TRUE;
852 if(regnum == This->oPos_regnum) {
853 token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
854 token |= D3DSRO_POSITION & D3DSP_REGNUM_MASK; /* No shift */
855 return token;
856 }
857 if(regnum == This->oFog_regnum && mask == This->oFog_mask) {
858 token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
859 token |= D3DSRO_FOG & D3DSP_REGNUM_MASK; /* No shift */
860 token |= D3DSP_WRITEMASK_ALL;
861 *has_components = FALSE;
862 return token;
863 }
864 if(regnum == This->oPts_regnum && mask == This->oPts_mask) {
865 token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
866 token |= D3DSRO_POINT_SIZE & D3DSP_REGNUM_MASK; /* No shift */
867 token |= D3DSP_WRITEMASK_ALL;
868 *has_components = FALSE;
869 return token;
870 }
871 for(i = 0; i < 2; i++) {
872 if(regnum == This->oD_regnum[i]) {
873 token |= (D3DSPR_ATTROUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
874 token |= i & D3DSP_REGNUM_MASK; /* No shift */
875 return token;
876 }
877 }
878 for(i = 0; i < 8; i++) {
879 if(regnum == This->oT_regnum[i]) {
880 token |= (D3DSPR_TEXCRDOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
881 token |= i & D3DSP_REGNUM_MASK; /* No shift */
882 return token;
883 }
884 }
885
886 /* The varying must be undeclared - if an unsupported varying was declared,
887 * the vs_find_builtin_varyings function would have caught it and this code
888 * would not run */
889 WARN("Undeclared varying %u\n", regnum);
890 This->state = E_INVALIDARG;
891 return -1;
892 }
893
894 static void vs_12_dstreg(struct bc_writer *This, const struct shader_reg *reg,
895 struct bytecode_buffer *buffer,
896 DWORD shift, DWORD mod) {
897 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
898 DWORD has_wmask;
899
900 if(reg->rel_reg) {
901 WARN("Relative addressing not supported for destination registers\n");
902 This->state = E_INVALIDARG;
903 return;
904 }
905
906 switch(reg->type) {
907 case BWRITERSPR_OUTPUT:
908 token |= map_vs_output(This, reg->regnum, reg->u.writemask, &has_wmask);
909 break;
910
911 case BWRITERSPR_RASTOUT:
912 case BWRITERSPR_ATTROUT:
913 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
914 * but are unexpected. If we hit this path it might be due to an error.
915 */
916 FIXME("Unexpected register type %u\n", reg->type);
917 /* drop through */
918 case BWRITERSPR_INPUT:
919 case BWRITERSPR_TEMP:
920 case BWRITERSPR_CONST:
921 token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
922 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
923 has_wmask = TRUE;
924 break;
925
926 case BWRITERSPR_ADDR:
927 if(reg->regnum != 0) {
928 WARN("Only a0 exists\n");
929 This->state = E_INVALIDARG;
930 return;
931 }
932 token |= (D3DSPR_ADDR << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
933 token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
934 has_wmask = TRUE;
935 break;
936
937 case BWRITERSPR_PREDICATE:
938 if(This->version != BWRITERVS_VERSION(2, 1)){
939 WARN("Predicate register is allowed only in vs_2_x\n");
940 This->state = E_INVALIDARG;
941 return;
942 }
943 if(reg->regnum != 0) {
944 WARN("Only predicate register p0 exists\n");
945 This->state = E_INVALIDARG;
946 return;
947 }
948 token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
949 token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
950 token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
951 has_wmask = TRUE;
952 break;
953
954 default:
955 WARN("Invalid register type for 1.x-2.x vertex shader\n");
956 This->state = E_INVALIDARG;
957 return;
958 }
959
960 /* strictly speaking there are no modifiers in vs_2_0 and vs_1_x, but they can be written
961 * into the bytecode and since the compiler doesn't do such checks write them
962 * (the checks are done by the undocumented shader validator)
963 */
964 token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
965 token |= d3d9_dstmod(mod);
966
967 if(has_wmask) {
968 token |= d3d9_writemask(reg->u.writemask);
969 }
970 put_dword(buffer, token);
971 }
972
973 static void vs_1_x_srcreg(struct bc_writer *This, const struct shader_reg *reg,
974 struct bytecode_buffer *buffer) {
975 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
976 DWORD has_swizzle;
977 DWORD component;
978
979 switch(reg->type) {
980 case BWRITERSPR_OUTPUT:
981 /* Map the swizzle to a writemask, the format expected
982 by map_vs_output
983 */
984 switch(reg->u.swizzle) {
985 case BWRITERVS_SWIZZLE_X:
986 component = BWRITERSP_WRITEMASK_0;
987 break;
988 case BWRITERVS_SWIZZLE_Y:
989 component = BWRITERSP_WRITEMASK_1;
990 break;
991 case BWRITERVS_SWIZZLE_Z:
992 component = BWRITERSP_WRITEMASK_2;
993 break;
994 case BWRITERVS_SWIZZLE_W:
995 component = BWRITERSP_WRITEMASK_3;
996 break;
997 default:
998 component = 0;
999 }
1000 token |= map_vs_output(This, reg->regnum, component, &has_swizzle);
1001 break;
1002
1003 case BWRITERSPR_RASTOUT:
1004 case BWRITERSPR_ATTROUT:
1005 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1006 * but are unexpected. If we hit this path it might be due to an error.
1007 */
1008 FIXME("Unexpected register type %u\n", reg->type);
1009 /* drop through */
1010 case BWRITERSPR_INPUT:
1011 case BWRITERSPR_TEMP:
1012 case BWRITERSPR_CONST:
1013 case BWRITERSPR_ADDR:
1014 token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1015 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1016 if(reg->rel_reg) {
1017 if(reg->rel_reg->type != BWRITERSPR_ADDR ||
1018 reg->rel_reg->regnum != 0 ||
1019 reg->rel_reg->u.swizzle != BWRITERVS_SWIZZLE_X) {
1020 WARN("Relative addressing in vs_1_x is only allowed with a0.x\n");
1021 This->state = E_INVALIDARG;
1022 return;
1023 }
1024 token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
1025 }
1026 break;
1027
1028 default:
1029 WARN("Invalid register type for 1.x vshader\n");
1030 This->state = E_INVALIDARG;
1031 return;
1032 }
1033
1034 token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
1035
1036 token |= d3d9_srcmod(reg->srcmod);
1037 put_dword(buffer, token);
1038 }
1039
1040 static void write_srcregs(struct bc_writer *This, const struct instruction *instr,
1041 struct bytecode_buffer *buffer){
1042 unsigned int i;
1043 if(instr->has_predicate){
1044 This->funcs->srcreg(This, &instr->predicate, buffer);
1045 }
1046 for(i = 0; i < instr->num_srcs; i++){
1047 This->funcs->srcreg(This, &instr->src[i], buffer);
1048 }
1049 }
1050
1051 static DWORD map_ps13_temp(struct bc_writer *This, const struct shader_reg *reg) {
1052 DWORD token = 0;
1053 if(reg->regnum == T0_REG) {
1054 token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1055 token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
1056 } else if(reg->regnum == T1_REG) {
1057 token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1058 token |= 1 & D3DSP_REGNUM_MASK; /* No shift */
1059 } else if(reg->regnum == T2_REG) {
1060 token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1061 token |= 2 & D3DSP_REGNUM_MASK; /* No shift */
1062 } else if(reg->regnum == T3_REG) {
1063 token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1064 token |= 3 & D3DSP_REGNUM_MASK; /* No shift */
1065 } else {
1066 token |= (D3DSPR_TEMP << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1067 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1068 }
1069 return token;
1070 }
1071
1072 static DWORD map_ps_input(struct bc_writer *This,
1073 const struct shader_reg *reg) {
1074 DWORD i, token = 0;
1075 /* Map color interpolators */
1076 for(i = 0; i < 2; i++) {
1077 if(reg->regnum == This->v_regnum[i]) {
1078 token |= (D3DSPR_INPUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1079 token |= i & D3DSP_REGNUM_MASK; /* No shift */
1080 return token;
1081 }
1082 }
1083 for(i = 0; i < 8; i++) {
1084 if(reg->regnum == This->t_regnum[i]) {
1085 token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1086 token |= i & D3DSP_REGNUM_MASK; /* No shift */
1087 return token;
1088 }
1089 }
1090
1091 WARN("Invalid ps 1/2 varying\n");
1092 This->state = E_INVALIDARG;
1093 return token;
1094 }
1095
1096 static void ps_1_0123_srcreg(struct bc_writer *This, const struct shader_reg *reg,
1097 struct bytecode_buffer *buffer) {
1098 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1099 if(reg->rel_reg) {
1100 WARN("Relative addressing not supported in <= ps_3_0\n");
1101 This->state = E_INVALIDARG;
1102 return;
1103 }
1104
1105 switch(reg->type) {
1106 case BWRITERSPR_INPUT:
1107 token |= map_ps_input(This, reg);
1108 break;
1109
1110 /* Take care about the texture temporaries. There's a problem: They aren't
1111 * declared anywhere, so we can only hardcode the values that are used
1112 * to map ps_1_3 shaders to the common shader structure
1113 */
1114 case BWRITERSPR_TEMP:
1115 token |= map_ps13_temp(This, reg);
1116 break;
1117
1118 case BWRITERSPR_CONST: /* Can be mapped 1:1 */
1119 token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1120 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1121 break;
1122
1123 default:
1124 WARN("Invalid register type for <= ps_1_3 shader\n");
1125 This->state = E_INVALIDARG;
1126 return;
1127 }
1128
1129 token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
1130
1131 if(reg->srcmod == BWRITERSPSM_DZ || reg->srcmod == BWRITERSPSM_DW ||
1132 reg->srcmod == BWRITERSPSM_ABS || reg->srcmod == BWRITERSPSM_ABSNEG ||
1133 reg->srcmod == BWRITERSPSM_NOT) {
1134 WARN("Invalid source modifier %u for <= ps_1_3\n", reg->srcmod);
1135 This->state = E_INVALIDARG;
1136 return;
1137 }
1138 token |= d3d9_srcmod(reg->srcmod);
1139 put_dword(buffer, token);
1140 }
1141
1142 static void ps_1_0123_dstreg(struct bc_writer *This, const struct shader_reg *reg,
1143 struct bytecode_buffer *buffer,
1144 DWORD shift, DWORD mod) {
1145 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1146
1147 if(reg->rel_reg) {
1148 WARN("Relative addressing not supported for destination registers\n");
1149 This->state = E_INVALIDARG;
1150 return;
1151 }
1152
1153 switch(reg->type) {
1154 case BWRITERSPR_TEMP:
1155 token |= map_ps13_temp(This, reg);
1156 break;
1157
1158 /* texkill uses the input register as a destination parameter */
1159 case BWRITERSPR_INPUT:
1160 token |= map_ps_input(This, reg);
1161 break;
1162
1163 default:
1164 WARN("Invalid dest register type for 1.x pshader\n");
1165 This->state = E_INVALIDARG;
1166 return;
1167 }
1168
1169 token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
1170 token |= d3d9_dstmod(mod);
1171
1172 token |= d3d9_writemask(reg->u.writemask);
1173 put_dword(buffer, token);
1174 }
1175
1176 /* The length of an instruction consists of the destination register (if any),
1177 * the number of source registers, the number of address registers used for
1178 * indirect addressing, and optionally the predicate register
1179 */
1180 static DWORD instrlen(const struct instruction *instr, unsigned int srcs, unsigned int dsts) {
1181 unsigned int i;
1182 DWORD ret = srcs + dsts + (instr->has_predicate ? 1 : 0);
1183
1184 if(dsts){
1185 if(instr->dst.rel_reg) ret++;
1186 }
1187 for(i = 0; i < srcs; i++) {
1188 if(instr->src[i].rel_reg) ret++;
1189 }
1190 return ret;
1191 }
1192
1193 static void sm_1_x_opcode(struct bc_writer *This,
1194 const struct instruction *instr,
1195 DWORD token, struct bytecode_buffer *buffer) {
1196 /* In sm_1_x instruction length isn't encoded */
1197 if(instr->coissue){
1198 token |= D3DSI_COISSUE;
1199 }
1200 put_dword(buffer, token);
1201 }
1202
1203 static void instr_handler(struct bc_writer *This,
1204 const struct instruction *instr,
1205 struct bytecode_buffer *buffer) {
1206 DWORD token = d3d9_opcode(instr->opcode);
1207
1208 This->funcs->opcode(This, instr, token, buffer);
1209 if(instr->has_dst) This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1210 write_srcregs(This, instr, buffer);
1211 }
1212
1213 static const struct instr_handler_table vs_1_x_handlers[] = {
1214 {BWRITERSIO_ADD, instr_handler},
1215 {BWRITERSIO_NOP, instr_handler},
1216 {BWRITERSIO_MOV, instr_handler},
1217 {BWRITERSIO_SUB, instr_handler},
1218 {BWRITERSIO_MAD, instr_handler},
1219 {BWRITERSIO_MUL, instr_handler},
1220 {BWRITERSIO_RCP, instr_handler},
1221 {BWRITERSIO_RSQ, instr_handler},
1222 {BWRITERSIO_DP3, instr_handler},
1223 {BWRITERSIO_DP4, instr_handler},
1224 {BWRITERSIO_MIN, instr_handler},
1225 {BWRITERSIO_MAX, instr_handler},
1226 {BWRITERSIO_SLT, instr_handler},
1227 {BWRITERSIO_SGE, instr_handler},
1228 {BWRITERSIO_EXP, instr_handler},
1229 {BWRITERSIO_LOG, instr_handler},
1230 {BWRITERSIO_EXPP, instr_handler},
1231 {BWRITERSIO_LOGP, instr_handler},
1232 {BWRITERSIO_DST, instr_handler},
1233 {BWRITERSIO_FRC, instr_handler},
1234 {BWRITERSIO_M4x4, instr_handler},
1235 {BWRITERSIO_M4x3, instr_handler},
1236 {BWRITERSIO_M3x4, instr_handler},
1237 {BWRITERSIO_M3x3, instr_handler},
1238 {BWRITERSIO_M3x2, instr_handler},
1239 {BWRITERSIO_LIT, instr_handler},
1240
1241 {BWRITERSIO_END, NULL}, /* Sentinel value, it signals
1242 the end of the list */
1243 };
1244
1245 static const struct bytecode_backend vs_1_x_backend = {
1246 vs_1_x_header,
1247 end,
1248 vs_1_x_srcreg,
1249 vs_12_dstreg,
1250 sm_1_x_opcode,
1251 vs_1_x_handlers
1252 };
1253
1254 static void instr_ps_1_0123_texld(struct bc_writer *This,
1255 const struct instruction *instr,
1256 struct bytecode_buffer *buffer) {
1257 DWORD idx;
1258 struct shader_reg reg;
1259 DWORD swizzlemask;
1260
1261 if(instr->src[1].type != BWRITERSPR_SAMPLER ||
1262 instr->src[1].regnum > 3) {
1263 WARN("Unsupported sampler type %u regnum %u\n",
1264 instr->src[1].type, instr->src[1].regnum);
1265 This->state = E_INVALIDARG;
1266 return;
1267 } else if(instr->dst.type != BWRITERSPR_TEMP) {
1268 WARN("Can only sample into a temp register\n");
1269 This->state = E_INVALIDARG;
1270 return;
1271 }
1272
1273 idx = instr->src[1].regnum;
1274 if((idx == 0 && instr->dst.regnum != T0_REG) ||
1275 (idx == 1 && instr->dst.regnum != T1_REG) ||
1276 (idx == 2 && instr->dst.regnum != T2_REG) ||
1277 (idx == 3 && instr->dst.regnum != T3_REG)) {
1278 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_x\n",
1279 idx, instr->dst.regnum);
1280 This->state = E_INVALIDARG;
1281 return;
1282 }
1283 if(instr->src[0].type == BWRITERSPR_INPUT) {
1284 /* A simple non-dependent read tex instruction */
1285 if(instr->src[0].regnum != This->t_regnum[idx]) {
1286 WARN("Cannot sample from s%u with texture address data from interpolator %u\n",
1287 idx, instr->src[0].regnum);
1288 This->state = E_INVALIDARG;
1289 return;
1290 }
1291 This->funcs->opcode(This, instr, D3DSIO_TEX & D3DSI_OPCODE_MASK, buffer);
1292
1293 /* map the temp dstreg to the ps_1_3 texture temporary register */
1294 This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1295 } else if(instr->src[0].type == BWRITERSPR_TEMP) {
1296
1297 swizzlemask = (3 << BWRITERVS_SWIZZLE_SHIFT) |
1298 (3 << (BWRITERVS_SWIZZLE_SHIFT + 2)) |
1299 (3 << (BWRITERVS_SWIZZLE_SHIFT + 4));
1300 if((instr->src[0].u.swizzle & swizzlemask) == (BWRITERVS_X_X | BWRITERVS_Y_Y | BWRITERVS_Z_Z)) {
1301 TRACE("writing texreg2rgb\n");
1302 This->funcs->opcode(This, instr, D3DSIO_TEXREG2RGB & D3DSI_OPCODE_MASK, buffer);
1303 } else if(instr->src[0].u.swizzle == (BWRITERVS_X_W | BWRITERVS_Y_X | BWRITERVS_Z_X | BWRITERVS_W_X)) {
1304 TRACE("writing texreg2ar\n");
1305 This->funcs->opcode(This, instr, D3DSIO_TEXREG2AR & D3DSI_OPCODE_MASK, buffer);
1306 } else if(instr->src[0].u.swizzle == (BWRITERVS_X_Y | BWRITERVS_Y_Z | BWRITERVS_Z_Z | BWRITERVS_W_Z)) {
1307 TRACE("writing texreg2gb\n");
1308 This->funcs->opcode(This, instr, D3DSIO_TEXREG2GB & D3DSI_OPCODE_MASK, buffer);
1309 } else {
1310 WARN("Unsupported src addr swizzle in dependent texld: 0x%08x\n", instr->src[0].u.swizzle);
1311 This->state = E_INVALIDARG;
1312 return;
1313 }
1314
1315 /* Dst and src reg can be mapped normally. Both registers are temporary registers in the
1316 * source shader and have to be mapped to the temporary form of the texture registers. However,
1317 * the src reg doesn't have a swizzle
1318 */
1319 This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1320 reg = instr->src[0];
1321 reg.u.swizzle = BWRITERVS_NOSWIZZLE;
1322 This->funcs->srcreg(This, &reg, buffer);
1323 } else {
1324 WARN("Invalid address data source register\n");
1325 This->state = E_INVALIDARG;
1326 return;
1327 }
1328 }
1329
1330 static void instr_ps_1_0123_mov(struct bc_writer *This,
1331 const struct instruction *instr,
1332 struct bytecode_buffer *buffer) {
1333 DWORD token = D3DSIO_MOV & D3DSI_OPCODE_MASK;
1334
1335 if(instr->dst.type == BWRITERSPR_TEMP && instr->src[0].type == BWRITERSPR_INPUT) {
1336 if((instr->dst.regnum == T0_REG && instr->src[0].regnum == This->t_regnum[0]) ||
1337 (instr->dst.regnum == T1_REG && instr->src[0].regnum == This->t_regnum[1]) ||
1338 (instr->dst.regnum == T2_REG && instr->src[0].regnum == This->t_regnum[2]) ||
1339 (instr->dst.regnum == T3_REG && instr->src[0].regnum == This->t_regnum[3])) {
1340 if(instr->dstmod & BWRITERSPDM_SATURATE) {
1341 This->funcs->opcode(This, instr, D3DSIO_TEXCOORD & D3DSI_OPCODE_MASK, buffer);
1342 /* Remove the SATURATE flag, it's implicit to the instruction */
1343 This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod & (~BWRITERSPDM_SATURATE));
1344 return;
1345 } else {
1346 WARN("A varying -> temp copy is only supported with the SATURATE modifier in <=ps_1_3\n");
1347 This->state = E_INVALIDARG;
1348 return;
1349 }
1350 } else if(instr->src[0].regnum == This->v_regnum[0] ||
1351 instr->src[0].regnum == This->v_regnum[1]) {
1352 /* Handled by the normal mov below. Just drop out of the if condition */
1353 } else {
1354 WARN("Unsupported varying -> temp mov in <= ps_1_3\n");
1355 This->state = E_INVALIDARG;
1356 return;
1357 }
1358 }
1359
1360 This->funcs->opcode(This, instr, token, buffer);
1361 This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1362 This->funcs->srcreg(This, &instr->src[0], buffer);
1363 }
1364
1365 static const struct instr_handler_table ps_1_0123_handlers[] = {
1366 {BWRITERSIO_ADD, instr_handler},
1367 {BWRITERSIO_NOP, instr_handler},
1368 {BWRITERSIO_MOV, instr_ps_1_0123_mov},
1369 {BWRITERSIO_SUB, instr_handler},
1370 {BWRITERSIO_MAD, instr_handler},
1371 {BWRITERSIO_MUL, instr_handler},
1372 {BWRITERSIO_DP3, instr_handler},
1373 {BWRITERSIO_DP4, instr_handler},
1374 {BWRITERSIO_LRP, instr_handler},
1375
1376 /* pshader instructions */
1377 {BWRITERSIO_CND, instr_handler},
1378 {BWRITERSIO_CMP, instr_handler},
1379 {BWRITERSIO_TEXKILL, instr_handler},
1380 {BWRITERSIO_TEX, instr_ps_1_0123_texld},
1381 {BWRITERSIO_TEXBEM, instr_handler},
1382 {BWRITERSIO_TEXBEML, instr_handler},
1383 {BWRITERSIO_TEXM3x2PAD, instr_handler},
1384 {BWRITERSIO_TEXM3x3PAD, instr_handler},
1385 {BWRITERSIO_TEXM3x3SPEC, instr_handler},
1386 {BWRITERSIO_TEXM3x3VSPEC, instr_handler},
1387 {BWRITERSIO_TEXM3x3TEX, instr_handler},
1388 {BWRITERSIO_TEXM3x3, instr_handler},
1389 {BWRITERSIO_TEXM3x2DEPTH, instr_handler},
1390 {BWRITERSIO_TEXM3x2TEX, instr_handler},
1391 {BWRITERSIO_TEXDP3, instr_handler},
1392 {BWRITERSIO_TEXDP3TEX, instr_handler},
1393 {BWRITERSIO_END, NULL},
1394 };
1395
1396 static const struct bytecode_backend ps_1_0123_backend = {
1397 ps_1_x_header,
1398 end,
1399 ps_1_0123_srcreg,
1400 ps_1_0123_dstreg,
1401 sm_1_x_opcode,
1402 ps_1_0123_handlers
1403 };
1404
1405 static void ps_1_4_srcreg(struct bc_writer *This, const struct shader_reg *reg,
1406 struct bytecode_buffer *buffer) {
1407 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1408 if(reg->rel_reg) {
1409 WARN("Relative addressing not supported in <= ps_3_0\n");
1410 This->state = E_INVALIDARG;
1411 return;
1412 }
1413
1414 switch(reg->type) {
1415 case BWRITERSPR_INPUT:
1416 token |= map_ps_input(This, reg);
1417 break;
1418
1419 /* Can be mapped 1:1 */
1420 case BWRITERSPR_TEMP:
1421 case BWRITERSPR_CONST:
1422 token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1423 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1424 break;
1425
1426 default:
1427 WARN("Invalid register type for ps_1_4 shader\n");
1428 This->state = E_INVALIDARG;
1429 return;
1430 }
1431
1432 token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
1433
1434 if(reg->srcmod == BWRITERSPSM_ABS || reg->srcmod == BWRITERSPSM_ABSNEG ||
1435 reg->srcmod == BWRITERSPSM_NOT) {
1436 WARN("Invalid source modifier %u for ps_1_4\n", reg->srcmod);
1437 This->state = E_INVALIDARG;
1438 return;
1439 }
1440 token |= d3d9_srcmod(reg->srcmod);
1441 put_dword(buffer, token);
1442 }
1443
1444 static void ps_1_4_dstreg(struct bc_writer *This, const struct shader_reg *reg,
1445 struct bytecode_buffer *buffer,
1446 DWORD shift, DWORD mod) {
1447 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1448
1449 if(reg->rel_reg) {
1450 WARN("Relative addressing not supported for destination registers\n");
1451 This->state = E_INVALIDARG;
1452 return;
1453 }
1454
1455 switch(reg->type) {
1456 case BWRITERSPR_TEMP: /* 1:1 mapping */
1457 token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1458 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1459 break;
1460
1461 /* For texkill */
1462 case BWRITERSPR_INPUT:
1463 token |= map_ps_input(This, reg);
1464 break;
1465
1466 default:
1467 WARN("Invalid dest register type for 1.x pshader\n");
1468 This->state = E_INVALIDARG;
1469 return;
1470 }
1471
1472 token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
1473 token |= d3d9_dstmod(mod);
1474
1475 token |= d3d9_writemask(reg->u.writemask);
1476 put_dword(buffer, token);
1477 }
1478
1479 static void instr_ps_1_4_mov(struct bc_writer *This,
1480 const struct instruction *instr,
1481 struct bytecode_buffer *buffer) {
1482 DWORD token = D3DSIO_MOV & D3DSI_OPCODE_MASK;
1483
1484 if(instr->dst.type == BWRITERSPR_TEMP && instr->src[0].type == BWRITERSPR_INPUT) {
1485 if(instr->src[0].regnum == This->t_regnum[0] ||
1486 instr->src[0].regnum == This->t_regnum[1] ||
1487 instr->src[0].regnum == This->t_regnum[2] ||
1488 instr->src[0].regnum == This->t_regnum[3] ||
1489 instr->src[0].regnum == This->t_regnum[4] ||
1490 instr->src[0].regnum == This->t_regnum[5]) {
1491 /* Similar to a regular mov, but a different opcode */
1492 token = D3DSIO_TEXCOORD & D3DSI_OPCODE_MASK;
1493 } else if(instr->src[0].regnum == This->v_regnum[0] ||
1494 instr->src[0].regnum == This->v_regnum[1]) {
1495 /* Handled by the normal mov below. Just drop out of the if condition */
1496 } else {
1497 WARN("Unsupported varying -> temp mov in ps_1_4\n");
1498 This->state = E_INVALIDARG;
1499 return;
1500 }
1501 }
1502
1503 This->funcs->opcode(This, instr, token, buffer);
1504 This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1505 This->funcs->srcreg(This, &instr->src[0], buffer);
1506 }
1507
1508 static void instr_ps_1_4_texld(struct bc_writer *This,
1509 const struct instruction *instr,
1510 struct bytecode_buffer *buffer) {
1511 if(instr->src[1].type != BWRITERSPR_SAMPLER ||
1512 instr->src[1].regnum > 5) {
1513 WARN("Unsupported sampler type %u regnum %u\n",
1514 instr->src[1].type, instr->src[1].regnum);
1515 This->state = E_INVALIDARG;
1516 return;
1517 } else if(instr->dst.type != BWRITERSPR_TEMP) {
1518 WARN("Can only sample into a temp register\n");
1519 This->state = E_INVALIDARG;
1520 return;
1521 }
1522
1523 if(instr->src[1].regnum != instr->dst.regnum) {
1524 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_4\n",
1525 instr->src[1].regnum, instr->dst.regnum);
1526 This->state = E_INVALIDARG;
1527 return;
1528 }
1529
1530 This->funcs->opcode(This, instr, D3DSIO_TEX & D3DSI_OPCODE_MASK, buffer);
1531 This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
1532 This->funcs->srcreg(This, &instr->src[0], buffer);
1533 }
1534
1535 static const struct instr_handler_table ps_1_4_handlers[] = {
1536 {BWRITERSIO_ADD, instr_handler},
1537 {BWRITERSIO_NOP, instr_handler},
1538 {BWRITERSIO_MOV, instr_ps_1_4_mov},
1539 {BWRITERSIO_SUB, instr_handler},
1540 {BWRITERSIO_MAD, instr_handler},
1541 {BWRITERSIO_MUL, instr_handler},
1542 {BWRITERSIO_DP3, instr_handler},
1543 {BWRITERSIO_DP4, instr_handler},
1544 {BWRITERSIO_LRP, instr_handler},
1545
1546 /* pshader instructions */
1547 {BWRITERSIO_CND, instr_handler},
1548 {BWRITERSIO_CMP, instr_handler},
1549 {BWRITERSIO_TEXKILL, instr_handler},
1550 {BWRITERSIO_TEX, instr_ps_1_4_texld},
1551 {BWRITERSIO_TEXDEPTH, instr_handler},
1552 {BWRITERSIO_BEM, instr_handler},
1553
1554 {BWRITERSIO_PHASE, instr_handler},
1555 {BWRITERSIO_END, NULL},
1556 };
1557
1558 static const struct bytecode_backend ps_1_4_backend = {
1559 ps_1_4_header,
1560 end,
1561 ps_1_4_srcreg,
1562 ps_1_4_dstreg,
1563 sm_1_x_opcode,
1564 ps_1_4_handlers
1565 };
1566
1567 static void write_constB(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
1568 write_const(shader->constB, shader->num_cb, D3DSIO_DEFB, D3DSPR_CONSTBOOL, buffer, len);
1569 }
1570
1571 static void write_constI(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
1572 write_const(shader->constI, shader->num_ci, D3DSIO_DEFI, D3DSPR_CONSTINT, buffer, len);
1573 }
1574
1575 static void vs_2_header(struct bc_writer *This,
1576 const struct bwriter_shader *shader,
1577 struct bytecode_buffer *buffer) {
1578 HRESULT hr;
1579
1580 hr = vs_find_builtin_varyings(This, shader);
1581 if(FAILED(hr)) {
1582 This->state = hr;
1583 return;
1584 }
1585
1586 write_declarations(This, buffer, TRUE, shader->inputs, shader->num_inputs, BWRITERSPR_INPUT);
1587 write_constF(shader, buffer, TRUE);
1588 write_constB(shader, buffer, TRUE);
1589 write_constI(shader, buffer, TRUE);
1590 }
1591
1592 static void vs_2_srcreg(struct bc_writer *This,
1593 const struct shader_reg *reg,
1594 struct bytecode_buffer *buffer) {
1595 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1596 DWORD has_swizzle;
1597 DWORD component;
1598 DWORD d3d9reg;
1599
1600 switch(reg->type) {
1601 case BWRITERSPR_OUTPUT:
1602 /* Map the swizzle to a writemask, the format expected
1603 by map_vs_output
1604 */
1605 switch(reg->u.swizzle) {
1606 case BWRITERVS_SWIZZLE_X:
1607 component = BWRITERSP_WRITEMASK_0;
1608 break;
1609 case BWRITERVS_SWIZZLE_Y:
1610 component = BWRITERSP_WRITEMASK_1;
1611 break;
1612 case BWRITERVS_SWIZZLE_Z:
1613 component = BWRITERSP_WRITEMASK_2;
1614 break;
1615 case BWRITERVS_SWIZZLE_W:
1616 component = BWRITERSP_WRITEMASK_3;
1617 break;
1618 default:
1619 component = 0;
1620 }
1621 token |= map_vs_output(This, reg->regnum, component, &has_swizzle);
1622 break;
1623
1624 case BWRITERSPR_RASTOUT:
1625 case BWRITERSPR_ATTROUT:
1626 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1627 * but are unexpected. If we hit this path it might be due to an error.
1628 */
1629 FIXME("Unexpected register type %u\n", reg->type);
1630 /* drop through */
1631 case BWRITERSPR_INPUT:
1632 case BWRITERSPR_TEMP:
1633 case BWRITERSPR_CONST:
1634 case BWRITERSPR_ADDR:
1635 case BWRITERSPR_CONSTINT:
1636 case BWRITERSPR_CONSTBOOL:
1637 case BWRITERSPR_LABEL:
1638 d3d9reg = d3d9_register(reg->type);
1639 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1640 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1641 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1642 break;
1643
1644 case BWRITERSPR_LOOP:
1645 if(reg->regnum != 0) {
1646 WARN("Only regnum 0 is supported for the loop index register in vs_2_0\n");
1647 This->state = E_INVALIDARG;
1648 return;
1649 }
1650 token |= (D3DSPR_LOOP << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1651 token |= (D3DSPR_LOOP << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1652 token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
1653 break;
1654
1655 case BWRITERSPR_PREDICATE:
1656 if(This->version != BWRITERVS_VERSION(2, 1)){
1657 WARN("Predicate register is allowed only in vs_2_x\n");
1658 This->state = E_INVALIDARG;
1659 return;
1660 }
1661 if(reg->regnum > 0) {
1662 WARN("Only predicate register 0 is supported\n");
1663 This->state = E_INVALIDARG;
1664 return;
1665 }
1666 token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1667 token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1668 token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
1669
1670 break;
1671
1672 default:
1673 WARN("Invalid register type for 2.0 vshader\n");
1674 This->state = E_INVALIDARG;
1675 return;
1676 }
1677
1678 token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
1679
1680 token |= d3d9_srcmod(reg->srcmod);
1681
1682 if(reg->rel_reg)
1683 token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
1684
1685 put_dword(buffer, token);
1686
1687 /* vs_2_0 and newer write the register containing the index explicitly in the
1688 * binary code
1689 */
1690 if(token & D3DVS_ADDRMODE_RELATIVE)
1691 vs_2_srcreg(This, reg->rel_reg, buffer);
1692 }
1693
1694 static void sm_2_opcode(struct bc_writer *This,
1695 const struct instruction *instr,
1696 DWORD token, struct bytecode_buffer *buffer) {
1697 /* From sm 2 onwards instruction length is encoded in the opcode field */
1698 int dsts = instr->has_dst ? 1 : 0;
1699 token |= instrlen(instr, instr->num_srcs, dsts) << D3DSI_INSTLENGTH_SHIFT;
1700 if(instr->comptype)
1701 token |= (d3d9_comparetype(instr->comptype) << 16) & (0xf << 16);
1702 if(instr->has_predicate)
1703 token |= D3DSHADER_INSTRUCTION_PREDICATED;
1704 put_dword(buffer,token);
1705 }
1706
1707 static const struct instr_handler_table vs_2_0_handlers[] = {
1708 {BWRITERSIO_ADD, instr_handler},
1709 {BWRITERSIO_NOP, instr_handler},
1710 {BWRITERSIO_MOV, instr_handler},
1711 {BWRITERSIO_SUB, instr_handler},
1712 {BWRITERSIO_MAD, instr_handler},
1713 {BWRITERSIO_MUL, instr_handler},
1714 {BWRITERSIO_RCP, instr_handler},
1715 {BWRITERSIO_RSQ, instr_handler},
1716 {BWRITERSIO_DP3, instr_handler},
1717 {BWRITERSIO_DP4, instr_handler},
1718 {BWRITERSIO_MIN, instr_handler},
1719 {BWRITERSIO_MAX, instr_handler},
1720 {BWRITERSIO_SLT, instr_handler},
1721 {BWRITERSIO_SGE, instr_handler},
1722 {BWRITERSIO_ABS, instr_handler},
1723 {BWRITERSIO_EXP, instr_handler},
1724 {BWRITERSIO_LOG, instr_handler},
1725 {BWRITERSIO_EXPP, instr_handler},
1726 {BWRITERSIO_LOGP, instr_handler},
1727 {BWRITERSIO_DST, instr_handler},
1728 {BWRITERSIO_LRP, instr_handler},
1729 {BWRITERSIO_FRC, instr_handler},
1730 {BWRITERSIO_CRS, instr_handler},
1731 {BWRITERSIO_SGN, instr_handler},
1732 {BWRITERSIO_NRM, instr_handler},
1733 {BWRITERSIO_SINCOS, instr_handler},
1734 {BWRITERSIO_M4x4, instr_handler},
1735 {BWRITERSIO_M4x3, instr_handler},
1736 {BWRITERSIO_M3x4, instr_handler},
1737 {BWRITERSIO_M3x3, instr_handler},
1738 {BWRITERSIO_M3x2, instr_handler},
1739 {BWRITERSIO_LIT, instr_handler},
1740 {BWRITERSIO_POW, instr_handler},
1741 {BWRITERSIO_MOVA, instr_handler},
1742
1743 {BWRITERSIO_CALL, instr_handler},
1744 {BWRITERSIO_CALLNZ, instr_handler},
1745 {BWRITERSIO_REP, instr_handler},
1746 {BWRITERSIO_ENDREP, instr_handler},
1747 {BWRITERSIO_IF, instr_handler},
1748 {BWRITERSIO_LABEL, instr_handler},
1749 {BWRITERSIO_ELSE, instr_handler},
1750 {BWRITERSIO_ENDIF, instr_handler},
1751 {BWRITERSIO_LOOP, instr_handler},
1752 {BWRITERSIO_RET, instr_handler},
1753 {BWRITERSIO_ENDLOOP, instr_handler},
1754
1755 {BWRITERSIO_END, NULL},
1756 };
1757
1758 static const struct bytecode_backend vs_2_0_backend = {
1759 vs_2_header,
1760 end,
1761 vs_2_srcreg,
1762 vs_12_dstreg,
1763 sm_2_opcode,
1764 vs_2_0_handlers
1765 };
1766
1767 static const struct instr_handler_table vs_2_x_handlers[] = {
1768 {BWRITERSIO_ADD, instr_handler},
1769 {BWRITERSIO_NOP, instr_handler},
1770 {BWRITERSIO_MOV, instr_handler},
1771 {BWRITERSIO_SUB, instr_handler},
1772 {BWRITERSIO_MAD, instr_handler},
1773 {BWRITERSIO_MUL, instr_handler},
1774 {BWRITERSIO_RCP, instr_handler},
1775 {BWRITERSIO_RSQ, instr_handler},
1776 {BWRITERSIO_DP3, instr_handler},
1777 {BWRITERSIO_DP4, instr_handler},
1778 {BWRITERSIO_MIN, instr_handler},
1779 {BWRITERSIO_MAX, instr_handler},
1780 {BWRITERSIO_SLT, instr_handler},
1781 {BWRITERSIO_SGE, instr_handler},
1782 {BWRITERSIO_ABS, instr_handler},
1783 {BWRITERSIO_EXP, instr_handler},
1784 {BWRITERSIO_LOG, instr_handler},
1785 {BWRITERSIO_EXPP, instr_handler},
1786 {BWRITERSIO_LOGP, instr_handler},
1787 {BWRITERSIO_DST, instr_handler},
1788 {BWRITERSIO_LRP, instr_handler},
1789 {BWRITERSIO_FRC, instr_handler},
1790 {BWRITERSIO_CRS, instr_handler},
1791 {BWRITERSIO_SGN, instr_handler},
1792 {BWRITERSIO_NRM, instr_handler},
1793 {BWRITERSIO_SINCOS, instr_handler},
1794 {BWRITERSIO_M4x4, instr_handler},
1795 {BWRITERSIO_M4x3, instr_handler},
1796 {BWRITERSIO_M3x4, instr_handler},
1797 {BWRITERSIO_M3x3, instr_handler},
1798 {BWRITERSIO_M3x2, instr_handler},
1799 {BWRITERSIO_LIT, instr_handler},
1800 {BWRITERSIO_POW, instr_handler},
1801 {BWRITERSIO_MOVA, instr_handler},
1802
1803 {BWRITERSIO_CALL, instr_handler},
1804 {BWRITERSIO_CALLNZ, instr_handler},
1805 {BWRITERSIO_REP, instr_handler},
1806 {BWRITERSIO_ENDREP, instr_handler},
1807 {BWRITERSIO_IF, instr_handler},
1808 {BWRITERSIO_LABEL, instr_handler},
1809 {BWRITERSIO_IFC, instr_handler},
1810 {BWRITERSIO_ELSE, instr_handler},
1811 {BWRITERSIO_ENDIF, instr_handler},
1812 {BWRITERSIO_BREAK, instr_handler},
1813 {BWRITERSIO_BREAKC, instr_handler},
1814 {BWRITERSIO_LOOP, instr_handler},
1815 {BWRITERSIO_RET, instr_handler},
1816 {BWRITERSIO_ENDLOOP, instr_handler},
1817
1818 {BWRITERSIO_SETP, instr_handler},
1819 {BWRITERSIO_BREAKP, instr_handler},
1820
1821 {BWRITERSIO_END, NULL},
1822 };
1823
1824 static const struct bytecode_backend vs_2_x_backend = {
1825 vs_2_header,
1826 end,
1827 vs_2_srcreg,
1828 vs_12_dstreg,
1829 sm_2_opcode,
1830 vs_2_x_handlers
1831 };
1832
1833 static void write_samplers(const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
1834 DWORD i;
1835 DWORD instr_dcl = D3DSIO_DCL | (2 << D3DSI_INSTLENGTH_SHIFT);
1836 DWORD token;
1837 const DWORD reg = (1<<31) |
1838 ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) |
1839 ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) |
1840 D3DSP_WRITEMASK_ALL;
1841
1842 for(i = 0; i < shader->num_samplers; i++) {
1843 /* Write the DCL instruction */
1844 put_dword(buffer, instr_dcl);
1845 token = (1<<31);
1846 /* Already shifted */
1847 token |= (d3d9_sampler(shader->samplers[i].type)) & D3DSP_TEXTURETYPE_MASK;
1848 put_dword(buffer, token);
1849 token = reg | (shader->samplers[i].regnum & D3DSP_REGNUM_MASK);
1850 token |= d3d9_dstmod(shader->samplers[i].mod);
1851 put_dword(buffer, token);
1852 }
1853 }
1854
1855 static void ps_2_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
1856 HRESULT hr = find_ps_builtin_semantics(This, shader, 8);
1857 if(FAILED(hr)) {
1858 This->state = hr;
1859 return;
1860 }
1861
1862 write_declarations(This, buffer, TRUE, shader->inputs, shader->num_inputs, BWRITERSPR_INPUT);
1863 write_samplers(shader, buffer);
1864 write_constF(shader, buffer, TRUE);
1865 write_constB(shader, buffer, TRUE);
1866 write_constI(shader, buffer, TRUE);
1867 }
1868
1869 static void ps_2_srcreg(struct bc_writer *This,
1870 const struct shader_reg *reg,
1871 struct bytecode_buffer *buffer) {
1872 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1873 DWORD d3d9reg;
1874 if(reg->rel_reg) {
1875 WARN("Relative addressing not supported in <= ps_3_0\n");
1876 This->state = E_INVALIDARG;
1877 return;
1878 }
1879
1880 switch(reg->type) {
1881 case BWRITERSPR_INPUT:
1882 token |= map_ps_input(This, reg);
1883 break;
1884
1885 /* Can be mapped 1:1 */
1886 case BWRITERSPR_TEMP:
1887 case BWRITERSPR_CONST:
1888 case BWRITERSPR_COLOROUT:
1889 case BWRITERSPR_CONSTBOOL:
1890 case BWRITERSPR_CONSTINT:
1891 case BWRITERSPR_SAMPLER:
1892 case BWRITERSPR_LABEL:
1893 case BWRITERSPR_DEPTHOUT:
1894 d3d9reg = d3d9_register(reg->type);
1895 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1896 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1897 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1898 break;
1899
1900 case BWRITERSPR_PREDICATE:
1901 if(This->version != BWRITERPS_VERSION(2, 1)){
1902 WARN("Predicate register not supported in ps_2_0\n");
1903 This->state = E_INVALIDARG;
1904 }
1905 if(reg->regnum) {
1906 WARN("Predicate register with regnum %u not supported\n",
1907 reg->regnum);
1908 This->state = E_INVALIDARG;
1909 }
1910 token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1911 token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1912 token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
1913 break;
1914
1915 default:
1916 WARN("Invalid register type for ps_2_0 shader\n");
1917 This->state = E_INVALIDARG;
1918 return;
1919 }
1920
1921 token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
1922
1923 token |= d3d9_srcmod(reg->srcmod);
1924 put_dword(buffer, token);
1925 }
1926
1927 static void ps_2_0_dstreg(struct bc_writer *This,
1928 const struct shader_reg *reg,
1929 struct bytecode_buffer *buffer,
1930 DWORD shift, DWORD mod) {
1931 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1932 DWORD d3d9reg;
1933
1934 if(reg->rel_reg) {
1935 WARN("Relative addressing not supported for destination registers\n");
1936 This->state = E_INVALIDARG;
1937 return;
1938 }
1939
1940 switch(reg->type) {
1941 case BWRITERSPR_TEMP: /* 1:1 mapping */
1942 case BWRITERSPR_COLOROUT:
1943 case BWRITERSPR_DEPTHOUT:
1944 d3d9reg = d3d9_register(reg->type);
1945 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1946 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1947 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1948 break;
1949
1950 case BWRITERSPR_PREDICATE:
1951 if(This->version != BWRITERPS_VERSION(2, 1)){
1952 WARN("Predicate register not supported in ps_2_0\n");
1953 This->state = E_INVALIDARG;
1954 }
1955 token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1956 token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1957 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1958 break;
1959
1960 /* texkill uses the input register as a destination parameter */
1961 case BWRITERSPR_INPUT:
1962 token |= map_ps_input(This, reg);
1963 break;
1964
1965 default:
1966 WARN("Invalid dest register type for 2.x pshader\n");
1967 This->state = E_INVALIDARG;
1968 return;
1969 }
1970
1971 token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
1972 token |= d3d9_dstmod(mod);
1973
1974 token |= d3d9_writemask(reg->u.writemask);
1975 put_dword(buffer, token);
1976 }
1977
1978 static const struct instr_handler_table ps_2_0_handlers[] = {
1979 {BWRITERSIO_ADD, instr_handler},
1980 {BWRITERSIO_NOP, instr_handler},
1981 {BWRITERSIO_MOV, instr_handler},
1982 {BWRITERSIO_SUB, instr_handler},
1983 {BWRITERSIO_MAD, instr_handler},
1984 {BWRITERSIO_MUL, instr_handler},
1985 {BWRITERSIO_RCP, instr_handler},
1986 {BWRITERSIO_RSQ, instr_handler},
1987 {BWRITERSIO_DP3, instr_handler},
1988 {BWRITERSIO_DP4, instr_handler},
1989 {BWRITERSIO_MIN, instr_handler},
1990 {BWRITERSIO_MAX, instr_handler},
1991 {BWRITERSIO_ABS, instr_handler},
1992 {BWRITERSIO_EXP, instr_handler},
1993 {BWRITERSIO_LOG, instr_handler},
1994 {BWRITERSIO_EXPP, instr_handler},
1995 {BWRITERSIO_LOGP, instr_handler},
1996 {BWRITERSIO_LRP, instr_handler},
1997 {BWRITERSIO_FRC, instr_handler},
1998 {BWRITERSIO_CRS, instr_handler},
1999 {BWRITERSIO_NRM, instr_handler},
2000 {BWRITERSIO_SINCOS, instr_handler},
2001 {BWRITERSIO_M4x4, instr_handler},
2002 {BWRITERSIO_M4x3, instr_handler},
2003 {BWRITERSIO_M3x4, instr_handler},
2004 {BWRITERSIO_M3x3, instr_handler},
2005 {BWRITERSIO_M3x2, instr_handler},
2006 {BWRITERSIO_POW, instr_handler},
2007 {BWRITERSIO_DP2ADD, instr_handler},
2008 {BWRITERSIO_CMP, instr_handler},
2009
2010 {BWRITERSIO_TEX, instr_handler},
2011 {BWRITERSIO_TEXLDP, instr_handler},
2012 {BWRITERSIO_TEXLDB, instr_handler},
2013 {BWRITERSIO_TEXKILL, instr_handler},
2014
2015 {BWRITERSIO_END, NULL},
2016 };
2017
2018 static const struct bytecode_backend ps_2_0_backend = {
2019 ps_2_header,
2020 end,
2021 ps_2_srcreg,
2022 ps_2_0_dstreg,
2023 sm_2_opcode,
2024 ps_2_0_handlers
2025 };
2026
2027 static const struct instr_handler_table ps_2_x_handlers[] = {
2028 {BWRITERSIO_ADD, instr_handler},
2029 {BWRITERSIO_NOP, instr_handler},
2030 {BWRITERSIO_MOV, instr_handler},
2031 {BWRITERSIO_SUB, instr_handler},
2032 {BWRITERSIO_MAD, instr_handler},
2033 {BWRITERSIO_MUL, instr_handler},
2034 {BWRITERSIO_RCP, instr_handler},
2035 {BWRITERSIO_RSQ, instr_handler},
2036 {BWRITERSIO_DP3, instr_handler},
2037 {BWRITERSIO_DP4, instr_handler},
2038 {BWRITERSIO_MIN, instr_handler},
2039 {BWRITERSIO_MAX, instr_handler},
2040 {BWRITERSIO_ABS, instr_handler},
2041 {BWRITERSIO_EXP, instr_handler},
2042 {BWRITERSIO_LOG, instr_handler},
2043 {BWRITERSIO_EXPP, instr_handler},
2044 {BWRITERSIO_LOGP, instr_handler},
2045 {BWRITERSIO_LRP, instr_handler},
2046 {BWRITERSIO_FRC, instr_handler},
2047 {BWRITERSIO_CRS, instr_handler},
2048 {BWRITERSIO_NRM, instr_handler},
2049 {BWRITERSIO_SINCOS, instr_handler},
2050 {BWRITERSIO_M4x4, instr_handler},
2051 {BWRITERSIO_M4x3, instr_handler},
2052 {BWRITERSIO_M3x4, instr_handler},
2053 {BWRITERSIO_M3x3, instr_handler},
2054 {BWRITERSIO_M3x2, instr_handler},
2055 {BWRITERSIO_POW, instr_handler},
2056 {BWRITERSIO_DP2ADD, instr_handler},
2057 {BWRITERSIO_CMP, instr_handler},
2058
2059 {BWRITERSIO_CALL, instr_handler},
2060 {BWRITERSIO_CALLNZ, instr_handler},
2061 {BWRITERSIO_REP, instr_handler},
2062 {BWRITERSIO_ENDREP, instr_handler},
2063 {BWRITERSIO_IF, instr_handler},
2064 {BWRITERSIO_LABEL, instr_handler},
2065 {BWRITERSIO_IFC, instr_handler},
2066 {BWRITERSIO_ELSE, instr_handler},
2067 {BWRITERSIO_ENDIF, instr_handler},
2068 {BWRITERSIO_BREAK, instr_handler},
2069 {BWRITERSIO_BREAKC, instr_handler},
2070 {BWRITERSIO_RET, instr_handler},
2071
2072 {BWRITERSIO_TEX, instr_handler},
2073 {BWRITERSIO_TEXLDP, instr_handler},
2074 {BWRITERSIO_TEXLDB, instr_handler},
2075 {BWRITERSIO_TEXKILL, instr_handler},
2076 {BWRITERSIO_DSX, instr_handler},
2077 {BWRITERSIO_DSY, instr_handler},
2078
2079 {BWRITERSIO_SETP, instr_handler},
2080 {BWRITERSIO_BREAKP, instr_handler},
2081
2082 {BWRITERSIO_TEXLDD, instr_handler},
2083
2084 {BWRITERSIO_END, NULL},
2085 };
2086
2087 static const struct bytecode_backend ps_2_x_backend = {
2088 ps_2_header,
2089 end,
2090 ps_2_srcreg,
2091 ps_2_0_dstreg,
2092 sm_2_opcode,
2093 ps_2_x_handlers
2094 };
2095
2096 static void sm_3_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
2097 write_declarations(This, buffer, TRUE, shader->inputs, shader->num_inputs, BWRITERSPR_INPUT);
2098 write_declarations(This, buffer, TRUE, shader->outputs, shader->num_outputs, BWRITERSPR_OUTPUT);
2099 write_constF(shader, buffer, TRUE);
2100 write_constB(shader, buffer, TRUE);
2101 write_constI(shader, buffer, TRUE);
2102 write_samplers(shader, buffer);
2103 }
2104
2105 static void sm_3_srcreg(struct bc_writer *This,
2106 const struct shader_reg *reg,
2107 struct bytecode_buffer *buffer) {
2108 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
2109 DWORD d3d9reg;
2110
2111 d3d9reg = d3d9_register(reg->type);
2112 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
2113 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
2114 token |= reg->regnum & D3DSP_REGNUM_MASK;
2115
2116 token |= d3d9_swizzle(reg->u.swizzle) & D3DVS_SWIZZLE_MASK;
2117 token |= d3d9_srcmod(reg->srcmod);
2118
2119 if(reg->rel_reg) {
2120 if(reg->type == BWRITERSPR_CONST && This->version == BWRITERPS_VERSION(3, 0)) {
2121 WARN("c%u[...] is unsupported in ps_3_0\n", reg->regnum);
2122 This->state = E_INVALIDARG;
2123 return;
2124 }
2125 if(((reg->rel_reg->type == BWRITERSPR_ADDR && This->version == BWRITERVS_VERSION(3, 0)) ||
2126 reg->rel_reg->type == BWRITERSPR_LOOP) &&
2127 reg->rel_reg->regnum == 0) {
2128 token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
2129 } else {
2130 WARN("Unsupported relative addressing register\n");
2131 This->state = E_INVALIDARG;
2132 return;
2133 }
2134 }
2135
2136 put_dword(buffer, token);
2137
2138 /* vs_2_0 and newer write the register containing the index explicitly in the
2139 * binary code
2140 */
2141 if(token & D3DVS_ADDRMODE_RELATIVE) {
2142 sm_3_srcreg(This, reg->rel_reg, buffer);
2143 }
2144 }
2145
2146 static void sm_3_dstreg(struct bc_writer *This,
2147 const struct shader_reg *reg,
2148 struct bytecode_buffer *buffer,
2149 DWORD shift, DWORD mod) {
2150 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
2151 DWORD d3d9reg;
2152
2153 if(reg->rel_reg) {
2154 if(This->version == BWRITERVS_VERSION(3, 0) &&
2155 reg->type == BWRITERSPR_OUTPUT) {
2156 token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
2157 } else {
2158 WARN("Relative addressing not supported for this shader type or register type\n");
2159 This->state = E_INVALIDARG;
2160 return;
2161 }
2162 }
2163
2164 d3d9reg = d3d9_register(reg->type);
2165 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
2166 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
2167 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
2168
2169 token |= d3d9_dstmod(mod);
2170
2171 token |= d3d9_writemask(reg->u.writemask);
2172 put_dword(buffer, token);
2173
2174 /* vs_2_0 and newer write the register containing the index explicitly in the
2175 * binary code
2176 */
2177 if(token & D3DVS_ADDRMODE_RELATIVE) {
2178 sm_3_srcreg(This, reg->rel_reg, buffer);
2179 }
2180 }
2181
2182 static const struct instr_handler_table vs_3_handlers[] = {
2183 {BWRITERSIO_ADD, instr_handler},
2184 {BWRITERSIO_NOP, instr_handler},
2185 {BWRITERSIO_MOV, instr_handler},
2186 {BWRITERSIO_SUB, instr_handler},
2187 {BWRITERSIO_MAD, instr_handler},
2188 {BWRITERSIO_MUL, instr_handler},
2189 {BWRITERSIO_RCP, instr_handler},
2190 {BWRITERSIO_RSQ, instr_handler},
2191 {BWRITERSIO_DP3, instr_handler},
2192 {BWRITERSIO_DP4, instr_handler},
2193 {BWRITERSIO_MIN, instr_handler},
2194 {BWRITERSIO_MAX, instr_handler},
2195 {BWRITERSIO_SLT, instr_handler},
2196 {BWRITERSIO_SGE, instr_handler},
2197 {BWRITERSIO_ABS, instr_handler},
2198 {BWRITERSIO_EXP, instr_handler},
2199 {BWRITERSIO_LOG, instr_handler},
2200 {BWRITERSIO_EXPP, instr_handler},
2201 {BWRITERSIO_LOGP, instr_handler},
2202 {BWRITERSIO_DST, instr_handler},
2203 {BWRITERSIO_LRP, instr_handler},
2204 {BWRITERSIO_FRC, instr_handler},
2205 {BWRITERSIO_CRS, instr_handler},
2206 {BWRITERSIO_SGN, instr_handler},
2207 {BWRITERSIO_NRM, instr_handler},
2208 {BWRITERSIO_SINCOS, instr_handler},
2209 {BWRITERSIO_M4x4, instr_handler},
2210 {BWRITERSIO_M4x3, instr_handler},
2211 {BWRITERSIO_M3x4, instr_handler},
2212 {BWRITERSIO_M3x3, instr_handler},
2213 {BWRITERSIO_M3x2, instr_handler},
2214 {BWRITERSIO_LIT, instr_handler},
2215 {BWRITERSIO_POW, instr_handler},
2216 {BWRITERSIO_MOVA, instr_handler},
2217
2218 {BWRITERSIO_CALL, instr_handler},
2219 {BWRITERSIO_CALLNZ, instr_handler},
2220 {BWRITERSIO_REP, instr_handler},
2221 {BWRITERSIO_ENDREP, instr_handler},
2222 {BWRITERSIO_IF, instr_handler},
2223 {BWRITERSIO_LABEL, instr_handler},
2224 {BWRITERSIO_IFC, instr_handler},
2225 {BWRITERSIO_ELSE, instr_handler},
2226 {BWRITERSIO_ENDIF, instr_handler},
2227 {BWRITERSIO_BREAK, instr_handler},
2228 {BWRITERSIO_BREAKC, instr_handler},
2229 {BWRITERSIO_LOOP, instr_handler},
2230 {BWRITERSIO_RET, instr_handler},
2231 {BWRITERSIO_ENDLOOP, instr_handler},
2232
2233 {BWRITERSIO_SETP, instr_handler},
2234 {BWRITERSIO_BREAKP, instr_handler},
2235 {BWRITERSIO_TEXLDL, instr_handler},
2236
2237 {BWRITERSIO_END, NULL},
2238 };
2239
2240 static const struct bytecode_backend vs_3_backend = {
2241 sm_3_header,
2242 end,
2243 sm_3_srcreg,
2244 sm_3_dstreg,
2245 sm_2_opcode,
2246 vs_3_handlers
2247 };
2248
2249 static const struct instr_handler_table ps_3_handlers[] = {
2250 {BWRITERSIO_ADD, instr_handler},
2251 {BWRITERSIO_NOP, instr_handler},
2252 {BWRITERSIO_MOV, instr_handler},
2253 {BWRITERSIO_SUB, instr_handler},
2254 {BWRITERSIO_MAD, instr_handler},
2255 {BWRITERSIO_MUL, instr_handler},
2256 {BWRITERSIO_RCP, instr_handler},
2257 {BWRITERSIO_RSQ, instr_handler},
2258 {BWRITERSIO_DP3, instr_handler},
2259 {BWRITERSIO_DP4, instr_handler},
2260 {BWRITERSIO_MIN, instr_handler},
2261 {BWRITERSIO_MAX, instr_handler},
2262 {BWRITERSIO_ABS, instr_handler},
2263 {BWRITERSIO_EXP, instr_handler},
2264 {BWRITERSIO_LOG, instr_handler},
2265 {BWRITERSIO_EXPP, instr_handler},
2266 {BWRITERSIO_LOGP, instr_handler},
2267 {BWRITERSIO_LRP, instr_handler},
2268 {BWRITERSIO_FRC, instr_handler},
2269 {BWRITERSIO_CRS, instr_handler},
2270 {BWRITERSIO_NRM, instr_handler},
2271 {BWRITERSIO_SINCOS, instr_handler},
2272 {BWRITERSIO_M4x4, instr_handler},
2273 {BWRITERSIO_M4x3, instr_handler},
2274 {BWRITERSIO_M3x4, instr_handler},
2275 {BWRITERSIO_M3x3, instr_handler},
2276 {BWRITERSIO_M3x2, instr_handler},
2277 {BWRITERSIO_POW, instr_handler},
2278 {BWRITERSIO_DP2ADD, instr_handler},
2279 {BWRITERSIO_CMP, instr_handler},
2280
2281 {BWRITERSIO_CALL, instr_handler},
2282 {BWRITERSIO_CALLNZ, instr_handler},
2283 {BWRITERSIO_REP, instr_handler},
2284 {BWRITERSIO_ENDREP, instr_handler},
2285 {BWRITERSIO_IF, instr_handler},
2286 {BWRITERSIO_LABEL, instr_handler},
2287 {BWRITERSIO_IFC, instr_handler},
2288 {BWRITERSIO_ELSE, instr_handler},
2289 {BWRITERSIO_ENDIF, instr_handler},
2290 {BWRITERSIO_BREAK, instr_handler},
2291 {BWRITERSIO_BREAKC, instr_handler},
2292 {BWRITERSIO_LOOP, instr_handler},
2293 {BWRITERSIO_RET, instr_handler},
2294 {BWRITERSIO_ENDLOOP, instr_handler},
2295
2296 {BWRITERSIO_SETP, instr_handler},
2297 {BWRITERSIO_BREAKP, instr_handler},
2298 {BWRITERSIO_TEXLDL, instr_handler},
2299
2300 {BWRITERSIO_TEX, instr_handler},
2301 {BWRITERSIO_TEXLDP, instr_handler},
2302 {BWRITERSIO_TEXLDB, instr_handler},
2303 {BWRITERSIO_TEXKILL, instr_handler},
2304 {BWRITERSIO_DSX, instr_handler},
2305 {BWRITERSIO_DSY, instr_handler},
2306 {BWRITERSIO_TEXLDD, instr_handler},
2307
2308 {BWRITERSIO_END, NULL},
2309 };
2310
2311 static const struct bytecode_backend ps_3_backend = {
2312 sm_3_header,
2313 end,
2314 sm_3_srcreg,
2315 sm_3_dstreg,
2316 sm_2_opcode,
2317 ps_3_handlers
2318 };
2319
2320 static void init_vs10_dx9_writer(struct bc_writer *writer) {
2321 TRACE("Creating DirectX9 vertex shader 1.0 writer\n");
2322 writer->funcs = &vs_1_x_backend;
2323 }
2324
2325 static void init_vs11_dx9_writer(struct bc_writer *writer) {
2326 TRACE("Creating DirectX9 vertex shader 1.1 writer\n");
2327 writer->funcs = &vs_1_x_backend;
2328 }
2329
2330 static void init_vs20_dx9_writer(struct bc_writer *writer) {
2331 TRACE("Creating DirectX9 vertex shader 2.0 writer\n");
2332 writer->funcs = &vs_2_0_backend;
2333 }
2334
2335 static void init_vs2x_dx9_writer(struct bc_writer *writer) {
2336 TRACE("Creating DirectX9 vertex shader 2.x writer\n");
2337 writer->funcs = &vs_2_x_backend;
2338 }
2339
2340 static void init_vs30_dx9_writer(struct bc_writer *writer) {
2341 TRACE("Creating DirectX9 vertex shader 3.0 writer\n");
2342 writer->funcs = &vs_3_backend;
2343 }
2344
2345 static void init_ps10_dx9_writer(struct bc_writer *writer) {
2346 TRACE("Creating DirectX9 pixel shader 1.0 writer\n");
2347 writer->funcs = &ps_1_0123_backend;
2348 }
2349
2350 static void init_ps11_dx9_writer(struct bc_writer *writer) {
2351 TRACE("Creating DirectX9 pixel shader 1.1 writer\n");
2352 writer->funcs = &ps_1_0123_backend;
2353 }
2354
2355 static void init_ps12_dx9_writer(struct bc_writer *writer) {
2356 TRACE("Creating DirectX9 pixel shader 1.2 writer\n");
2357 writer->funcs = &ps_1_0123_backend;
2358 }
2359
2360 static void init_ps13_dx9_writer(struct bc_writer *writer) {
2361 TRACE("Creating DirectX9 pixel shader 1.3 writer\n");
2362 writer->funcs = &ps_1_0123_backend;
2363 }
2364
2365 static void init_ps14_dx9_writer(struct bc_writer *writer) {
2366 TRACE("Creating DirectX9 pixel shader 1.4 writer\n");
2367 writer->funcs = &ps_1_4_backend;
2368 }
2369
2370 static void init_ps20_dx9_writer(struct bc_writer *writer) {
2371 TRACE("Creating DirectX9 pixel shader 2.0 writer\n");
2372 writer->funcs = &ps_2_0_backend;
2373 }
2374
2375 static void init_ps2x_dx9_writer(struct bc_writer *writer) {
2376 TRACE("Creating DirectX9 pixel shader 2.x writer\n");
2377 writer->funcs = &ps_2_x_backend;
2378 }
2379
2380 static void init_ps30_dx9_writer(struct bc_writer *writer) {
2381 TRACE("Creating DirectX9 pixel shader 3.0 writer\n");
2382 writer->funcs = &ps_3_backend;
2383 }
2384
2385 static struct bc_writer *create_writer(DWORD version, DWORD dxversion) {
2386 struct bc_writer *ret = d3dcompiler_alloc(sizeof(*ret));
2387
2388 if(!ret) {
2389 WARN("Failed to allocate a bytecode writer instance\n");
2390 return NULL;
2391 }
2392
2393 switch(version) {
2394 case BWRITERVS_VERSION(1, 0):
2395 if(dxversion != 9) {
2396 WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion);
2397 goto fail;
2398 }
2399 init_vs10_dx9_writer(ret);
2400 break;
2401 case BWRITERVS_VERSION(1, 1):
2402 if(dxversion != 9) {
2403 WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion);
2404 goto fail;
2405 }
2406 init_vs11_dx9_writer(ret);
2407 break;
2408 case BWRITERVS_VERSION(2, 0):
2409 if(dxversion != 9) {
2410 WARN("Unsupported dxversion for vertex shader 2.0 requested: %u\n", dxversion);
2411 goto fail;
2412 }
2413 init_vs20_dx9_writer(ret);
2414 break;
2415 case BWRITERVS_VERSION(2, 1):
2416 if(dxversion != 9) {
2417 WARN("Unsupported dxversion for vertex shader 2.x requested: %u\n", dxversion);
2418 goto fail;
2419 }
2420 init_vs2x_dx9_writer(ret);
2421 break;
2422 case BWRITERVS_VERSION(3, 0):
2423 if(dxversion != 9) {
2424 WARN("Unsupported dxversion for vertex shader 3.0 requested: %u\n", dxversion);
2425 goto fail;
2426 }
2427 init_vs30_dx9_writer(ret);
2428 break;
2429
2430 case BWRITERPS_VERSION(1, 0):
2431 if(dxversion != 9) {
2432 WARN("Unsupported dxversion for pixel shader 1.0 requested: %u\n", dxversion);
2433 goto fail;
2434 }
2435 init_ps10_dx9_writer(ret);
2436 break;
2437 case BWRITERPS_VERSION(1, 1):
2438 if(dxversion != 9) {
2439 WARN("Unsupported dxversion for pixel shader 1.1 requested: %u\n", dxversion);
2440 goto fail;
2441 }
2442 init_ps11_dx9_writer(ret);
2443 break;
2444 case BWRITERPS_VERSION(1, 2):
2445 if(dxversion != 9) {
2446 WARN("Unsupported dxversion for pixel shader 1.2 requested: %u\n", dxversion);
2447 goto fail;
2448 }
2449 init_ps12_dx9_writer(ret);
2450 break;
2451 case BWRITERPS_VERSION(1, 3):
2452 if(dxversion != 9) {
2453 WARN("Unsupported dxversion for pixel shader 1.3 requested: %u\n", dxversion);
2454 goto fail;
2455 }
2456 init_ps13_dx9_writer(ret);
2457 break;
2458 case BWRITERPS_VERSION(1, 4):
2459 if(dxversion != 9) {
2460 WARN("Unsupported dxversion for pixel shader 1.4 requested: %u\n", dxversion);
2461 goto fail;
2462 }
2463 init_ps14_dx9_writer(ret);
2464 break;
2465
2466 case BWRITERPS_VERSION(2, 0):
2467 if(dxversion != 9) {
2468 WARN("Unsupported dxversion for pixel shader 2.0 requested: %u\n", dxversion);
2469 goto fail;
2470 }
2471 init_ps20_dx9_writer(ret);
2472 break;
2473
2474 case BWRITERPS_VERSION(2, 1):
2475 if(dxversion != 9) {
2476 WARN("Unsupported dxversion for pixel shader 2.x requested: %u\n", dxversion);
2477 goto fail;
2478 }
2479 init_ps2x_dx9_writer(ret);
2480 break;
2481
2482 case BWRITERPS_VERSION(3, 0):
2483 if(dxversion != 9) {
2484 WARN("Unsupported dxversion for pixel shader 3.0 requested: %u\n", dxversion);
2485 goto fail;
2486 }
2487 init_ps30_dx9_writer(ret);
2488 break;
2489
2490 default:
2491 WARN("Unexpected shader version requested: %08x\n", version);
2492 goto fail;
2493 }
2494 ret->version = version;
2495 return ret;
2496
2497 fail:
2498 d3dcompiler_free(ret);
2499 return NULL;
2500 }
2501
2502 static HRESULT call_instr_handler(struct bc_writer *writer,
2503 const struct instruction *instr,
2504 struct bytecode_buffer *buffer) {
2505 DWORD i=0;
2506
2507 while(writer->funcs->instructions[i].opcode != BWRITERSIO_END) {
2508 if(instr->opcode == writer->funcs->instructions[i].opcode) {
2509 if(!writer->funcs->instructions[i].func) {
2510 WARN("Opcode %u not supported by this profile\n", instr->opcode);
2511 return E_INVALIDARG;
2512 }
2513 writer->funcs->instructions[i].func(writer, instr, buffer);
2514 return S_OK;
2515 }
2516 i++;
2517 }
2518
2519 FIXME("Unhandled instruction %u - %s\n", instr->opcode,
2520 debug_print_opcode(instr->opcode));
2521 return E_INVALIDARG;
2522 }
2523
2524 HRESULT SlWriteBytecode(const struct bwriter_shader *shader, int dxversion, DWORD **result, DWORD *size)
2525 {
2526 struct bc_writer *writer;
2527 struct bytecode_buffer *buffer = NULL;
2528 HRESULT hr;
2529 unsigned int i;
2530
2531 if(!shader){
2532 ERR("NULL shader structure, aborting\n");
2533 return E_FAIL;
2534 }
2535 writer = create_writer(shader->version, dxversion);
2536 *result = NULL;
2537
2538 if(!writer) {
2539 WARN("Could not create a bytecode writer instance. Either unsupported version\n");
2540 WARN("or out of memory\n");
2541 hr = E_FAIL;
2542 goto error;
2543 }
2544
2545 buffer = allocate_buffer();
2546 if(!buffer) {
2547 WARN("Failed to allocate a buffer for the shader bytecode\n");
2548 hr = E_FAIL;
2549 goto error;
2550 }
2551
2552 /* Write shader type and version */
2553 put_dword(buffer, shader->version);
2554
2555 writer->funcs->header(writer, shader, buffer);
2556 if(FAILED(writer->state)) {
2557 hr = writer->state;
2558 goto error;
2559 }
2560
2561 for(i = 0; i < shader->num_instrs; i++) {
2562 hr = call_instr_handler(writer, shader->instr[i], buffer);
2563 if(FAILED(hr)) {
2564 goto error;
2565 }
2566 }
2567
2568 if(FAILED(writer->state)) {
2569 hr = writer->state;
2570 goto error;
2571 }
2572
2573 writer->funcs->end(writer, shader, buffer);
2574
2575 if(FAILED(buffer->state)) {
2576 hr = buffer->state;
2577 goto error;
2578 }
2579
2580 *size = buffer->size * sizeof(DWORD);
2581 *result = buffer->data;
2582 buffer->data = NULL;
2583 hr = S_OK;
2584
2585 error:
2586 if(buffer) {
2587 d3dcompiler_free(buffer->data);
2588 d3dcompiler_free(buffer);
2589 }
2590 d3dcompiler_free(writer);
2591 return hr;
2592 }
2593
2594 void SlDeleteShader(struct bwriter_shader *shader) {
2595 unsigned int i, j;
2596
2597 TRACE("Deleting shader %p\n", shader);
2598
2599 for(i = 0; i < shader->num_cf; i++) {
2600 d3dcompiler_free(shader->constF[i]);
2601 }
2602 d3dcompiler_free(shader->constF);
2603 for(i = 0; i < shader->num_ci; i++) {
2604 d3dcompiler_free(shader->constI[i]);
2605 }
2606 d3dcompiler_free(shader->constI);
2607 for(i = 0; i < shader->num_cb; i++) {
2608 d3dcompiler_free(shader->constB[i]);
2609 }
2610 d3dcompiler_free(shader->constB);
2611
2612 d3dcompiler_free(shader->inputs);
2613 d3dcompiler_free(shader->outputs);
2614 d3dcompiler_free(shader->samplers);
2615
2616 for(i = 0; i < shader->num_instrs; i++) {
2617 for(j = 0; j < shader->instr[i]->num_srcs; j++) {
2618 d3dcompiler_free(shader->instr[i]->src[j].rel_reg);
2619 }
2620 d3dcompiler_free(shader->instr[i]->src);
2621 d3dcompiler_free(shader->instr[i]->dst.rel_reg);
2622 d3dcompiler_free(shader->instr[i]);
2623 }
2624 d3dcompiler_free(shader->instr);
2625
2626 d3dcompiler_free(shader);
2627 }