d3dx9: Allow modifiers on the ps dcl input instruction.
[wine] / dlls / d3dx9_36 / 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 "config.h"
24 #include "wine/port.h"
25 #include "wine/debug.h"
26
27 #include "d3dx9_36_private.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
30
31 /****************************************************************
32  * General assembler shader construction helper routines follow *
33  ****************************************************************/
34 /* struct instruction *alloc_instr
35  *
36  * Allocates a new instruction structure with srcs registers
37  *
38  * Parameters:
39  *  srcs: Number of source registers to allocate
40  *
41  * Returns:
42  *  A pointer to the allocated instruction structure
43  *  NULL in case of an allocation failure
44  */
45 struct instruction *alloc_instr(unsigned int srcs) {
46     struct instruction *ret = asm_alloc(sizeof(*ret));
47     if(!ret) {
48         ERR("Failed to allocate memory for an instruction structure\n");
49         return NULL;
50     }
51
52     if(srcs) {
53         ret->src = asm_alloc(srcs * sizeof(*ret->src));
54         if(!ret->src) {
55             ERR("Failed to allocate memory for instruction registers\n");
56             asm_free(ret);
57             return NULL;
58         }
59         ret->num_srcs = srcs;
60     }
61     return ret;
62 }
63
64 /* void add_instruction
65  *
66  * Adds a new instruction to the shader's instructions array and grows the instruction array
67  * if needed.
68  *
69  * The function does NOT copy the instruction structure. Make sure not to release the
70  * instruction or any of its substructures like registers.
71  *
72  * Parameters:
73  *  shader: Shader to add the instruction to
74  *  instr: Instruction to add to the shader
75  */
76 BOOL add_instruction(struct bwriter_shader *shader, struct instruction *instr) {
77     struct instruction      **new_instructions;
78
79     if(!shader) return FALSE;
80
81     if(shader->instr_alloc_size == 0) {
82         shader->instr = asm_alloc(sizeof(*shader->instr) * INSTRARRAY_INITIAL_SIZE);
83         if(!shader->instr) {
84             ERR("Failed to allocate the shader instruction array\n");
85             return FALSE;
86         }
87         shader->instr_alloc_size = INSTRARRAY_INITIAL_SIZE;
88     } else if(shader->instr_alloc_size == shader->num_instrs) {
89         new_instructions = asm_realloc(shader->instr,
90                                        sizeof(*shader->instr) * (shader->instr_alloc_size) * 2);
91         if(!new_instructions) {
92             ERR("Failed to grow the shader instruction array\n");
93             return FALSE;
94         }
95         shader->instr = new_instructions;
96         shader->instr_alloc_size = shader->instr_alloc_size * 2;
97     } else if(shader->num_instrs > shader->instr_alloc_size) {
98         ERR("More instructions than allocated. This should not happen\n");
99         return FALSE;
100     }
101
102     shader->instr[shader->num_instrs] = instr;
103     shader->num_instrs++;
104     return TRUE;
105 }
106
107 BOOL add_constF(struct bwriter_shader *shader, DWORD reg, float x, float y, float z, float w) {
108     struct constant *newconst;
109
110     if(shader->num_cf) {
111         struct constant **newarray;
112         newarray = asm_realloc(shader->constF,
113                                sizeof(*shader->constF) * (shader->num_cf + 1));
114         if(!newarray) {
115             ERR("Failed to grow the constants array\n");
116             return FALSE;
117         }
118         shader->constF = newarray;
119     } else {
120         shader->constF = asm_alloc(sizeof(*shader->constF));
121         if(!shader->constF) {
122             ERR("Failed to allocate the constants array\n");
123             return FALSE;
124         }
125     }
126
127     newconst = asm_alloc(sizeof(*newconst));
128     if(!newconst) {
129         ERR("Failed to allocate a new constant\n");
130         return FALSE;
131     }
132     newconst->regnum = reg;
133     newconst->value[0].f = x;
134     newconst->value[1].f = y;
135     newconst->value[2].f = z;
136     newconst->value[3].f = w;
137     shader->constF[shader->num_cf] = newconst;
138
139     shader->num_cf++;
140     return TRUE;
141 }
142
143 BOOL add_constI(struct bwriter_shader *shader, DWORD reg, INT x, INT y, INT z, INT w) {
144     struct constant *newconst;
145
146     if(shader->num_ci) {
147         struct constant **newarray;
148         newarray = asm_realloc(shader->constI,
149                                sizeof(*shader->constI) * (shader->num_ci + 1));
150         if(!newarray) {
151             ERR("Failed to grow the constants array\n");
152             return FALSE;
153         }
154         shader->constI = newarray;
155     } else {
156         shader->constI = asm_alloc(sizeof(*shader->constI));
157         if(!shader->constI) {
158             ERR("Failed to allocate the constants array\n");
159             return FALSE;
160         }
161     }
162
163     newconst = asm_alloc(sizeof(*newconst));
164     if(!newconst) {
165         ERR("Failed to allocate a new constant\n");
166         return FALSE;
167     }
168     newconst->regnum = reg;
169     newconst->value[0].i = x;
170     newconst->value[1].i = y;
171     newconst->value[2].i = z;
172     newconst->value[3].i = w;
173     shader->constI[shader->num_ci] = newconst;
174
175     shader->num_ci++;
176     return TRUE;
177 }
178
179 BOOL add_constB(struct bwriter_shader *shader, DWORD reg, BOOL x) {
180     struct constant *newconst;
181
182     if(shader->num_cb) {
183         struct constant **newarray;
184         newarray = asm_realloc(shader->constB,
185                                sizeof(*shader->constB) * (shader->num_cb + 1));
186         if(!newarray) {
187             ERR("Failed to grow the constants array\n");
188             return FALSE;
189         }
190         shader->constB = newarray;
191     } else {
192         shader->constB = asm_alloc(sizeof(*shader->constB));
193         if(!shader->constB) {
194             ERR("Failed to allocate the constants array\n");
195             return FALSE;
196         }
197     }
198
199     newconst = asm_alloc(sizeof(*newconst));
200     if(!newconst) {
201         ERR("Failed to allocate a new constant\n");
202         return FALSE;
203     }
204     newconst->regnum = reg;
205     newconst->value[0].b = x;
206     shader->constB[shader->num_cb] = newconst;
207
208     shader->num_cb++;
209     return TRUE;
210 }
211
212 BOOL record_declaration(struct bwriter_shader *shader, DWORD usage, DWORD usage_idx, DWORD mod, BOOL output, DWORD regnum, DWORD writemask) {
213     unsigned int *num;
214     struct declaration **decl;
215     unsigned int i;
216
217     if(!shader) return FALSE;
218
219     if(output) {
220         num = &shader->num_outputs;
221         decl = &shader->outputs;
222     } else {
223         num = &shader->num_inputs;
224         decl = &shader->inputs;
225     }
226
227     if(*num == 0) {
228         *decl = asm_alloc(sizeof(**decl));
229         if(!*decl) {
230             ERR("Error allocating declarations array\n");
231             return FALSE;
232         }
233     } else {
234         struct declaration *newdecl;
235         for(i = 0; i < *num; i++) {
236             if((*decl)[i].regnum == regnum && ((*decl)[i].writemask & writemask)) {
237                 WARN("Declaration of register %u already exists, writemask match 0x%x\n",
238                       regnum, (*decl)[i].writemask & writemask);
239             }
240         }
241
242         newdecl = asm_realloc(*decl,
243                               sizeof(**decl) * ((*num) + 1));
244         if(!newdecl) {
245             ERR("Error reallocating declarations array\n");
246             return FALSE;
247         }
248         *decl = newdecl;
249     }
250     (*decl)[*num].usage = usage;
251     (*decl)[*num].usage_idx = usage_idx;
252     (*decl)[*num].regnum = regnum;
253     (*decl)[*num].mod = mod;
254     (*decl)[*num].writemask = writemask;
255     (*num)++;
256
257     return TRUE;
258 }
259
260 BOOL record_sampler(struct bwriter_shader *shader, DWORD samptype, DWORD regnum) {
261     unsigned int i;
262
263     if(!shader) return FALSE;
264
265     if(shader->num_samplers == 0) {
266         shader->samplers = asm_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 = asm_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].regnum = regnum;
294     shader->num_samplers++;
295     return TRUE;
296 }
297
298
299 /* shader bytecode buffer manipulation functions.
300  * allocate_buffer creates a new buffer structure, put_dword adds a new
301  * DWORD to the buffer. In the rare case of a memory allocation failure
302  * when trying to grow the buffer a flag is set in the buffer to mark it
303  * invalid. This avoids return value checking and passing in many places
304  */
305 static struct bytecode_buffer *allocate_buffer(void) {
306     struct bytecode_buffer *ret;
307
308     ret = asm_alloc(sizeof(*ret));
309     if(!ret) return NULL;
310
311     ret->alloc_size = BYTECODEBUFFER_INITIAL_SIZE;
312     ret->data = asm_alloc(sizeof(DWORD) * ret->alloc_size);
313     if(!ret->data) {
314         asm_free(ret);
315         return NULL;
316     }
317     ret->state = S_OK;
318     return ret;
319 }
320
321 static void put_dword(struct bytecode_buffer *buffer, DWORD value) {
322     if(FAILED(buffer->state)) return;
323
324     if(buffer->alloc_size == buffer->size) {
325         DWORD *newarray;
326         buffer->alloc_size *= 2;
327         newarray = asm_realloc(buffer->data,
328                                sizeof(DWORD) * buffer->alloc_size);
329         if(!newarray) {
330             ERR("Failed to grow the buffer data memory\n");
331             buffer->state = E_OUTOFMEMORY;
332             return;
333         }
334         buffer->data = newarray;
335     }
336     buffer->data[buffer->size++] = value;
337 }
338
339 /******************************************************
340  * Implementation of the writer functions starts here *
341  ******************************************************/
342 static void write_declarations(struct bytecode_buffer *buffer, BOOL len,
343                                const struct declaration *decls, unsigned int num, DWORD type) {
344     DWORD i;
345     DWORD instr_dcl = D3DSIO_DCL;
346     DWORD token;
347
348     if(len) {
349         instr_dcl |= 2 << D3DSI_INSTLENGTH_SHIFT;
350     }
351
352     for(i = 0; i < num; i++) {
353         /* Write the DCL instruction */
354         put_dword(buffer, instr_dcl);
355
356         /* Write the usage and index */
357         token = (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
358         token |= (decls[i].usage << D3DSP_DCL_USAGE_SHIFT) & D3DSP_DCL_USAGE_MASK;
359         token |= (decls[i].usage_idx << D3DSP_DCL_USAGEINDEX_SHIFT) & D3DSP_DCL_USAGEINDEX_MASK;
360         put_dword(buffer, token);
361
362         /* Write the dest register */
363         token = (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
364         token |= (type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
365         token |= (d3d9_writemask(decls[i].writemask)) & D3DSP_WRITEMASK_ALL;
366         token |= decls[i].regnum & D3DSP_REGNUM_MASK;
367         token |= d3d9_dstmod(decls[i].mod);
368         put_dword(buffer, token);
369     }
370 }
371
372 static void write_const(struct constant **consts, int num, DWORD opcode, DWORD reg_type, struct bytecode_buffer *buffer, BOOL len) {
373     DWORD i;
374     DWORD instr_def = opcode;
375     const DWORD reg = (1<<31) |
376                       ((reg_type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) |
377                       ((reg_type << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) |
378                       D3DSP_WRITEMASK_ALL;
379
380     if(len) {
381         if(opcode == D3DSIO_DEFB)
382             instr_def |= 2 << D3DSI_INSTLENGTH_SHIFT;
383         else
384             instr_def |= 5 << D3DSI_INSTLENGTH_SHIFT;
385     }
386
387     for(i = 0; i < num; i++) {
388         /* Write the DEF instruction */
389         put_dword(buffer, instr_def);
390
391         put_dword(buffer, reg | (consts[i]->regnum & D3DSP_REGNUM_MASK));
392         put_dword(buffer, consts[i]->value[0].d);
393         if(opcode != D3DSIO_DEFB) {
394             put_dword(buffer, consts[i]->value[1].d);
395             put_dword(buffer, consts[i]->value[2].d);
396             put_dword(buffer, consts[i]->value[3].d);
397         }
398     }
399 }
400
401 static void write_constF(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
402     write_const(shader->constF, shader->num_cf, D3DSIO_DEF, D3DSPR_CONST, buffer, len);
403 }
404
405 static HRESULT vs_find_builtin_varyings(struct bc_writer *This, const struct bwriter_shader *shader) {
406     DWORD i;
407     DWORD usage, usage_idx, writemask, regnum;
408
409     for(i = 0; i < shader->num_outputs; i++) {
410         usage = shader->outputs[i].usage;
411         usage_idx = shader->outputs[i].usage_idx;
412         writemask = shader->outputs[i].writemask;
413         regnum = shader->outputs[i].regnum;
414
415         switch(usage) {
416             case BWRITERDECLUSAGE_POSITION:
417             case BWRITERDECLUSAGE_POSITIONT:
418                 if(usage_idx > 0) {
419                     WARN("dcl_position%u not supported in sm 1/2 shaders\n", usage_idx);
420                     return E_INVALIDARG;
421                 }
422                 TRACE("o%u is oPos\n", regnum);
423                 This->oPos_regnum = regnum;
424                 break;
425
426             case BWRITERDECLUSAGE_COLOR:
427                 if(usage_idx > 1) {
428                     WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx);
429                     return E_INVALIDARG;
430                 }
431                 if(writemask != BWRITERSP_WRITEMASK_ALL) {
432                     WARN("Only WRITEMASK_ALL is supported on color in sm 1/2\n");
433                     return E_INVALIDARG;
434                 }
435                 TRACE("o%u is oD%u\n", regnum, usage_idx);
436                 This->oD_regnum[usage_idx] = regnum;
437                 break;
438
439             case BWRITERDECLUSAGE_TEXCOORD:
440                 if(usage_idx >= 8) {
441                     WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx);
442                     return E_INVALIDARG;
443                 }
444                 if(writemask != (BWRITERSP_WRITEMASK_0) &&
445                    writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1) &&
446                    writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1 | BWRITERSP_WRITEMASK_2) &&
447                    writemask != (BWRITERSP_WRITEMASK_ALL)) {
448                     WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
449                     return E_INVALIDARG;
450                 }
451                 TRACE("o%u is oT%u\n", regnum, usage_idx);
452                 This->oT_regnum[usage_idx] = regnum;
453                 break;
454
455             case BWRITERDECLUSAGE_PSIZE:
456                 if(usage_idx > 0) {
457                     WARN("dcl_psize%u not supported in sm 1/2 shaders\n", usage_idx);
458                     return E_INVALIDARG;
459                 }
460                 TRACE("o%u writemask 0x%08x is oPts\n", regnum, writemask);
461                 This->oPts_regnum = regnum;
462                 This->oPts_mask = writemask;
463                 break;
464
465             case BWRITERDECLUSAGE_FOG:
466                 if(usage_idx > 0) {
467                     WARN("dcl_fog%u not supported in sm 1 shaders\n", usage_idx);
468                     return E_INVALIDARG;
469                 }
470                 if(writemask != BWRITERSP_WRITEMASK_0 && writemask != BWRITERSP_WRITEMASK_1 &&
471                    writemask != BWRITERSP_WRITEMASK_2 && writemask != BWRITERSP_WRITEMASK_3) {
472                     WARN("Unsupported fog writemask\n");
473                     return E_INVALIDARG;
474                 }
475                 TRACE("o%u writemask 0x%08x is oFog\n", regnum, writemask);
476                 This->oFog_regnum = regnum;
477                 This->oFog_mask = writemask;
478                 break;
479
480             default:
481                 WARN("Varying type %u is not supported in shader model 1.x\n", usage);
482                 return E_INVALIDARG;
483         }
484     }
485
486     return S_OK;
487 }
488
489 static void vs_1_x_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
490     HRESULT hr;
491
492     if(shader->num_ci || shader->num_cb) {
493         WARN("Int and bool constants are not supported in shader model 1 shaders\n");
494         WARN("Got %u int and %u boolean constants\n", shader->num_ci, shader->num_cb);
495         This->state = E_INVALIDARG;
496         return;
497     }
498
499     hr = vs_find_builtin_varyings(This, shader);
500     if(FAILED(hr)) {
501         This->state = hr;
502         return;
503     }
504
505     /* Declare the shader type and version */
506     put_dword(buffer, This->version);
507
508     write_declarations(buffer, FALSE, shader->inputs, shader->num_inputs, D3DSPR_INPUT);
509     write_constF(shader, buffer, FALSE);
510     return;
511 }
512
513 static HRESULT find_ps_builtin_semantics(struct bc_writer *This,
514                                          const struct bwriter_shader *shader,
515                                          DWORD texcoords) {
516     DWORD i;
517     DWORD usage, usage_idx, writemask, regnum;
518
519     This->v_regnum[0] = -1; This->v_regnum[1] = -1;
520     for(i = 0; i < 8; i++) This->t_regnum[i] = -1;
521
522     for(i = 0; i < shader->num_inputs; i++) {
523         usage = shader->inputs[i].usage;
524         usage_idx = shader->inputs[i].usage_idx;
525         writemask = shader->inputs[i].writemask;
526         regnum = shader->inputs[i].regnum;
527
528         switch(usage) {
529             case BWRITERDECLUSAGE_COLOR:
530                 if(usage_idx > 1) {
531                     WARN("dcl_color%u not supported in sm 1 shaders\n", usage_idx);
532                     return E_INVALIDARG;
533                 }
534                 if(writemask != BWRITERSP_WRITEMASK_ALL) {
535                     WARN("Only WRITEMASK_ALL is supported on color in sm 1\n");
536                     return E_INVALIDARG;
537                 }
538                 TRACE("v%u is v%u\n", regnum, usage_idx);
539                 This->v_regnum[usage_idx] = regnum;
540                 break;
541
542             case BWRITERDECLUSAGE_TEXCOORD:
543                 if(usage_idx > texcoords) {
544                     WARN("dcl_texcoord%u not supported in this shader version\n", usage_idx);
545                     return E_INVALIDARG;
546                 }
547                 if(writemask != (BWRITERSP_WRITEMASK_0) &&
548                    writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1) &&
549                    writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1 | BWRITERSP_WRITEMASK_2) &&
550                    writemask != (BWRITERSP_WRITEMASK_ALL)) {
551                     WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
552                 } else {
553                     writemask = BWRITERSP_WRITEMASK_ALL;
554                 }
555                 TRACE("v%u is t%u\n", regnum, usage_idx);
556                 This->t_regnum[usage_idx] = regnum;
557                 break;
558
559             default:
560                 WARN("Varying type %u is not supported in shader model 1.x\n", usage);
561                 return E_INVALIDARG;
562         }
563     }
564
565     return S_OK;
566 }
567
568 static void end(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
569     put_dword(buffer, D3DSIO_END);
570 }
571
572 static DWORD map_vs_output(struct bc_writer *This, DWORD regnum, DWORD mask, DWORD *has_components) {
573     DWORD token = 0;
574     DWORD i;
575
576     *has_components = TRUE;
577     if(regnum == This->oPos_regnum) {
578         token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
579         token |= D3DSRO_POSITION & D3DSP_REGNUM_MASK; /* No shift */
580         return token;
581     }
582     if(regnum == This->oFog_regnum && mask == This->oFog_mask) {
583         token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
584         token |= D3DSRO_FOG & D3DSP_REGNUM_MASK; /* No shift */
585         token |= D3DSP_WRITEMASK_ALL;
586         *has_components = FALSE;
587         return token;
588     }
589     if(regnum == This->oPts_regnum && mask == This->oPts_mask) {
590         token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
591         token |= D3DSRO_POINT_SIZE & D3DSP_REGNUM_MASK; /* No shift */
592         token |= D3DSP_WRITEMASK_ALL;
593         *has_components = FALSE;
594         return token;
595     }
596     for(i = 0; i < 2; i++) {
597         if(regnum == This->oD_regnum[i]) {
598             token |= (D3DSPR_ATTROUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
599             token |= i & D3DSP_REGNUM_MASK; /* No shift */
600             return token;
601         }
602     }
603     for(i = 0; i < 8; i++) {
604         if(regnum == This->oT_regnum[i]) {
605             token |= (D3DSPR_TEXCRDOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
606             token |= i & D3DSP_REGNUM_MASK; /* No shift */
607             return token;
608         }
609     }
610
611     /* The varying must be undeclared - if an unsupported varying was declared,
612      * the vs_find_builtin_varyings function would have caught it and this code
613      * would not run */
614     WARN("Undeclared varying %u\n", regnum);
615     This->state = E_INVALIDARG;
616     return -1;
617 }
618
619 static void vs_12_dstreg(struct bc_writer *This, const struct shader_reg *reg,
620                          struct bytecode_buffer *buffer,
621                          DWORD shift, DWORD mod) {
622     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
623     DWORD has_wmask;
624
625     if(reg->rel_reg) {
626         WARN("Relative addressing not supported for destination registers\n");
627         This->state = E_INVALIDARG;
628         return;
629     }
630
631     switch(reg->type) {
632         case BWRITERSPR_OUTPUT:
633             token |= map_vs_output(This, reg->regnum, reg->writemask, &has_wmask);
634             break;
635
636         case BWRITERSPR_RASTOUT:
637         case BWRITERSPR_ATTROUT:
638             /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
639             * but are unexpected. If we hit this path it might be due to an error.
640             */
641             FIXME("Unexpected register type %u\n", reg->type);
642             /* drop through */
643         case BWRITERSPR_INPUT:
644         case BWRITERSPR_TEMP:
645         case BWRITERSPR_CONST:
646             token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
647             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
648             has_wmask = TRUE;
649             break;
650
651         case BWRITERSPR_ADDR:
652             if(reg->regnum != 0) {
653                 WARN("Only a0 exists\n");
654                 This->state = E_INVALIDARG;
655                 return;
656             }
657             token |= (D3DSPR_ADDR << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
658             token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
659             has_wmask = TRUE;
660             break;
661
662         case BWRITERSPR_PREDICATE:
663             if(This->version != BWRITERVS_VERSION(2, 1)){
664                 WARN("Predicate register is allowed only in vs_2_x\n");
665                 This->state = E_INVALIDARG;
666                 return;
667             }
668             if(reg->regnum != 0) {
669                 WARN("Only predicate register p0 exists\n");
670                 This->state = E_INVALIDARG;
671                 return;
672             }
673             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
674             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
675             token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
676             has_wmask = TRUE;
677             break;
678
679         default:
680             WARN("Invalid register type for 1.x-2.x vertex shader\n");
681             This->state = E_INVALIDARG;
682             return;
683     }
684
685     /* strictly speaking there are no modifiers in vs_2_0 and vs_1_x, but they can be written
686      * into the bytecode and since the compiler doesn't do such checks write them
687      * (the checks are done by the undocumented shader validator)
688      */
689     token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
690     token |= d3d9_dstmod(mod);
691
692     if(has_wmask) {
693         token |= d3d9_writemask(reg->writemask);
694     }
695     put_dword(buffer, token);
696 }
697
698 static void vs_1_x_srcreg(struct bc_writer *This, const struct shader_reg *reg,
699                           struct bytecode_buffer *buffer) {
700     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
701     DWORD has_swizzle;
702     DWORD component;
703
704     switch(reg->type) {
705         case BWRITERSPR_OUTPUT:
706             /* Map the swizzle to a writemask, the format expected
707                by map_vs_output
708              */
709             switch(reg->swizzle) {
710                 case BWRITERVS_SWIZZLE_X:
711                     component = BWRITERSP_WRITEMASK_0;
712                     break;
713                 case BWRITERVS_SWIZZLE_Y:
714                     component = BWRITERSP_WRITEMASK_1;
715                     break;
716                 case BWRITERVS_SWIZZLE_Z:
717                     component = BWRITERSP_WRITEMASK_2;
718                     break;
719                 case BWRITERVS_SWIZZLE_W:
720                     component = BWRITERSP_WRITEMASK_3;
721                     break;
722                 default:
723                     component = 0;
724             }
725             token |= map_vs_output(This, reg->regnum, component, &has_swizzle);
726             break;
727
728         case BWRITERSPR_RASTOUT:
729         case BWRITERSPR_ATTROUT:
730             /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
731              * but are unexpected. If we hit this path it might be due to an error.
732              */
733             FIXME("Unexpected register type %u\n", reg->type);
734             /* drop through */
735         case BWRITERSPR_INPUT:
736         case BWRITERSPR_TEMP:
737         case BWRITERSPR_CONST:
738         case BWRITERSPR_ADDR:
739             token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
740             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
741             if(reg->rel_reg) {
742                 if(reg->rel_reg->type != BWRITERSPR_ADDR ||
743                    reg->rel_reg->regnum != 0 ||
744                    reg->rel_reg->swizzle != BWRITERVS_SWIZZLE_X) {
745                     WARN("Relative addressing in vs_1_x is only allowed with a0.x\n");
746                     This->state = E_INVALIDARG;
747                     return;
748                 }
749                 token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
750             }
751             break;
752
753         default:
754             WARN("Invalid register type for 1.x vshader\n");
755             This->state = E_INVALIDARG;
756             return;
757     }
758
759     token |= d3d9_swizzle(reg->swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
760
761     token |= d3d9_srcmod(reg->srcmod);
762     put_dword(buffer, token);
763 }
764
765 static void write_srcregs(struct bc_writer *This, const struct instruction *instr,
766                           struct bytecode_buffer *buffer){
767     unsigned int i;
768     if(instr->has_predicate){
769         This->funcs->srcreg(This, &instr->predicate, buffer);
770     }
771     for(i = 0; i < instr->num_srcs; i++){
772         This->funcs->srcreg(This, &instr->src[i], buffer);
773     }
774 }
775
776 static DWORD map_ps_input(struct bc_writer *This,
777                           const struct shader_reg *reg) {
778     DWORD i, token = 0;
779     /* Map color interpolators */
780     for(i = 0; i < 2; i++) {
781         if(reg->regnum == This->v_regnum[i]) {
782             token |= (D3DSPR_INPUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
783             token |= i & D3DSP_REGNUM_MASK; /* No shift */
784             return token;
785         }
786     }
787     for(i = 0; i < 8; i++) {
788         if(reg->regnum == This->t_regnum[i]) {
789             token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
790             token |= i & D3DSP_REGNUM_MASK; /* No shift */
791             return token;
792         }
793     }
794
795     WARN("Invalid ps 1/2 varying\n");
796     This->state = E_INVALIDARG;
797     return token;
798 }
799
800 /* The length of an instruction consists of the destination register (if any),
801  * the number of source registers, the number of address registers used for
802  * indirect addressing, and optionally the predicate register
803  */
804 static DWORD instrlen(const struct instruction *instr, unsigned int srcs, unsigned int dsts) {
805     unsigned int i;
806     DWORD ret = srcs + dsts + (instr->has_predicate ? 1 : 0);
807
808     if(dsts){
809         if(instr->dst.rel_reg) ret++;
810     }
811     for(i = 0; i < srcs; i++) {
812         if(instr->src[i].rel_reg) ret++;
813     }
814     return ret;
815 }
816
817 static void sm_1_x_opcode(struct bc_writer *This,
818                           const struct instruction *instr,
819                           DWORD token, struct bytecode_buffer *buffer) {
820     /* In sm_1_x instruction length isn't encoded */
821     if(instr->coissue){
822         token |= D3DSI_COISSUE;
823     }
824     put_dword(buffer, token);
825 }
826
827 static void instr_handler(struct bc_writer *This,
828                           const struct instruction *instr,
829                           struct bytecode_buffer *buffer) {
830     DWORD token = d3d9_opcode(instr->opcode);
831     TRACE("token: %x\n", token);
832
833     This->funcs->opcode(This, instr, token, buffer);
834     if(instr->has_dst) This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
835     write_srcregs(This, instr, buffer);
836 }
837
838 static const struct instr_handler_table vs_1_x_handlers[] = {
839     {BWRITERSIO_ADD,            instr_handler},
840     {BWRITERSIO_NOP,            instr_handler},
841     {BWRITERSIO_MOV,            instr_handler},
842     {BWRITERSIO_SUB,            instr_handler},
843     {BWRITERSIO_MAD,            instr_handler},
844     {BWRITERSIO_MUL,            instr_handler},
845     {BWRITERSIO_RCP,            instr_handler},
846     {BWRITERSIO_RSQ,            instr_handler},
847     {BWRITERSIO_DP3,            instr_handler},
848     {BWRITERSIO_DP4,            instr_handler},
849     {BWRITERSIO_MIN,            instr_handler},
850     {BWRITERSIO_MAX,            instr_handler},
851     {BWRITERSIO_SLT,            instr_handler},
852     {BWRITERSIO_SGE,            instr_handler},
853     {BWRITERSIO_EXP,            instr_handler},
854     {BWRITERSIO_LOG,            instr_handler},
855     {BWRITERSIO_EXPP,           instr_handler},
856     {BWRITERSIO_LOGP,           instr_handler},
857     {BWRITERSIO_DST,            instr_handler},
858     {BWRITERSIO_FRC,            instr_handler},
859     {BWRITERSIO_M4x4,           instr_handler},
860     {BWRITERSIO_M4x3,           instr_handler},
861     {BWRITERSIO_M3x4,           instr_handler},
862     {BWRITERSIO_M3x3,           instr_handler},
863     {BWRITERSIO_M3x2,           instr_handler},
864     {BWRITERSIO_LIT,            instr_handler},
865
866     {BWRITERSIO_END,            NULL}, /* Sentinel value, it signals
867                                           the end of the list */
868 };
869
870 static const struct bytecode_backend vs_1_x_backend = {
871     vs_1_x_header,
872     end,
873     vs_1_x_srcreg,
874     vs_12_dstreg,
875     sm_1_x_opcode,
876     vs_1_x_handlers
877 };
878
879 static void write_constB(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
880     write_const(shader->constB, shader->num_cb, D3DSIO_DEFB, D3DSPR_CONSTBOOL, buffer, len);
881 }
882
883 static void write_constI(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
884     write_const(shader->constI, shader->num_ci, D3DSIO_DEFI, D3DSPR_CONSTINT, buffer, len);
885 }
886
887 static void vs_2_header(struct bc_writer *This,
888                         const struct bwriter_shader *shader,
889                         struct bytecode_buffer *buffer) {
890     HRESULT hr;
891
892     hr = vs_find_builtin_varyings(This, shader);
893     if(FAILED(hr)) {
894         This->state = hr;
895         return;
896     }
897
898     /* Declare the shader type and version */
899     put_dword(buffer, This->version);
900
901     write_declarations(buffer, TRUE, shader->inputs, shader->num_inputs, D3DSPR_INPUT);
902     write_constF(shader, buffer, TRUE);
903     write_constB(shader, buffer, TRUE);
904     write_constI(shader, buffer, TRUE);
905     return;
906 }
907
908 static void vs_2_srcreg(struct bc_writer *This,
909                         const struct shader_reg *reg,
910                         struct bytecode_buffer *buffer) {
911     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
912     DWORD has_swizzle;
913     DWORD component;
914     DWORD d3d9reg;
915
916     switch(reg->type) {
917         case BWRITERSPR_OUTPUT:
918             /* Map the swizzle to a writemask, the format expected
919                by map_vs_output
920              */
921             switch(reg->swizzle) {
922                 case BWRITERVS_SWIZZLE_X:
923                     component = BWRITERSP_WRITEMASK_0;
924                     break;
925                 case BWRITERVS_SWIZZLE_Y:
926                     component = BWRITERSP_WRITEMASK_1;
927                     break;
928                 case BWRITERVS_SWIZZLE_Z:
929                     component = BWRITERSP_WRITEMASK_2;
930                     break;
931                 case BWRITERVS_SWIZZLE_W:
932                     component = BWRITERSP_WRITEMASK_3;
933                     break;
934                 default:
935                     component = 0;
936             }
937             token |= map_vs_output(This, reg->regnum, component, &has_swizzle);
938             break;
939
940         case BWRITERSPR_RASTOUT:
941         case BWRITERSPR_ATTROUT:
942             /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
943              * but are unexpected. If we hit this path it might be due to an error.
944              */
945             FIXME("Unexpected register type %u\n", reg->type);
946             /* drop through */
947         case BWRITERSPR_INPUT:
948         case BWRITERSPR_TEMP:
949         case BWRITERSPR_CONST:
950         case BWRITERSPR_ADDR:
951         case BWRITERSPR_CONSTINT:
952         case BWRITERSPR_CONSTBOOL:
953         case BWRITERSPR_LABEL:
954             d3d9reg = d3d9_register(reg->type);
955             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
956             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
957             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
958             break;
959
960         case BWRITERSPR_LOOP:
961             if(reg->regnum != 0) {
962                 WARN("Only regnum 0 is supported for the loop index register in vs_2_0\n");
963                 This->state = E_INVALIDARG;
964                 return;
965             }
966             token |= (D3DSPR_LOOP << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
967             token |= (D3DSPR_LOOP << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
968             token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
969             break;
970
971         case BWRITERSPR_PREDICATE:
972             if(This->version != BWRITERVS_VERSION(2, 1)){
973                 WARN("Predicate register is allowed only in vs_2_x\n");
974                 This->state = E_INVALIDARG;
975                 return;
976             }
977             if(reg->regnum > 0) {
978                 WARN("Only predicate register 0 is supported\n");
979                 This->state = E_INVALIDARG;
980                 return;
981             }
982             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
983             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
984             token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
985
986             break;
987
988         default:
989             WARN("Invalid register type for 2.0 vshader\n");
990             This->state = E_INVALIDARG;
991             return;
992     }
993
994     token |= d3d9_swizzle(reg->swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
995
996     token |= d3d9_srcmod(reg->srcmod);
997
998     if(reg->rel_reg)
999         token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
1000
1001     put_dword(buffer, token);
1002
1003     /* vs_2_0 and newer write the register containing the index explicitly in the
1004      * binary code
1005      */
1006     if(token & D3DVS_ADDRMODE_RELATIVE)
1007         vs_2_srcreg(This, reg->rel_reg, buffer);
1008 }
1009
1010 static void sm_2_opcode(struct bc_writer *This,
1011                         const struct instruction *instr,
1012                         DWORD token, struct bytecode_buffer *buffer) {
1013     /* From sm 2 onwards instruction length is encoded in the opcode field */
1014     int dsts = instr->has_dst ? 1 : 0;
1015     token |= instrlen(instr, instr->num_srcs, dsts) << D3DSI_INSTLENGTH_SHIFT;
1016     if(instr->comptype)
1017         token |= (d3d9_comparetype(instr->comptype) << 16) & (0xf << 16);
1018     if(instr->has_predicate)
1019         token |= D3DSHADER_INSTRUCTION_PREDICATED;
1020     put_dword(buffer,token);
1021 }
1022
1023 static const struct instr_handler_table vs_2_0_handlers[] = {
1024     {BWRITERSIO_ADD,            instr_handler},
1025     {BWRITERSIO_NOP,            instr_handler},
1026     {BWRITERSIO_MOV,            instr_handler},
1027     {BWRITERSIO_SUB,            instr_handler},
1028     {BWRITERSIO_MAD,            instr_handler},
1029     {BWRITERSIO_MUL,            instr_handler},
1030     {BWRITERSIO_RCP,            instr_handler},
1031     {BWRITERSIO_RSQ,            instr_handler},
1032     {BWRITERSIO_DP3,            instr_handler},
1033     {BWRITERSIO_DP4,            instr_handler},
1034     {BWRITERSIO_MIN,            instr_handler},
1035     {BWRITERSIO_MAX,            instr_handler},
1036     {BWRITERSIO_SLT,            instr_handler},
1037     {BWRITERSIO_SGE,            instr_handler},
1038     {BWRITERSIO_ABS,            instr_handler},
1039     {BWRITERSIO_EXP,            instr_handler},
1040     {BWRITERSIO_LOG,            instr_handler},
1041     {BWRITERSIO_EXPP,           instr_handler},
1042     {BWRITERSIO_LOGP,           instr_handler},
1043     {BWRITERSIO_DST,            instr_handler},
1044     {BWRITERSIO_LRP,            instr_handler},
1045     {BWRITERSIO_FRC,            instr_handler},
1046     {BWRITERSIO_CRS,            instr_handler},
1047     {BWRITERSIO_SGN,            instr_handler},
1048     {BWRITERSIO_NRM,            instr_handler},
1049     {BWRITERSIO_SINCOS,         instr_handler},
1050     {BWRITERSIO_M4x4,           instr_handler},
1051     {BWRITERSIO_M4x3,           instr_handler},
1052     {BWRITERSIO_M3x4,           instr_handler},
1053     {BWRITERSIO_M3x3,           instr_handler},
1054     {BWRITERSIO_M3x2,           instr_handler},
1055     {BWRITERSIO_LIT,            instr_handler},
1056     {BWRITERSIO_POW,            instr_handler},
1057     {BWRITERSIO_MOVA,           instr_handler},
1058
1059     {BWRITERSIO_CALL,           instr_handler},
1060     {BWRITERSIO_CALLNZ,         instr_handler},
1061     {BWRITERSIO_REP,            instr_handler},
1062     {BWRITERSIO_ENDREP,         instr_handler},
1063     {BWRITERSIO_IF,             instr_handler},
1064     {BWRITERSIO_LABEL,          instr_handler},
1065     {BWRITERSIO_ELSE,           instr_handler},
1066     {BWRITERSIO_ENDIF,          instr_handler},
1067     {BWRITERSIO_LOOP,           instr_handler},
1068     {BWRITERSIO_RET,            instr_handler},
1069     {BWRITERSIO_ENDLOOP,        instr_handler},
1070
1071     {BWRITERSIO_END,            NULL},
1072 };
1073
1074 static const struct bytecode_backend vs_2_0_backend = {
1075     vs_2_header,
1076     end,
1077     vs_2_srcreg,
1078     vs_12_dstreg,
1079     sm_2_opcode,
1080     vs_2_0_handlers
1081 };
1082
1083 static const struct instr_handler_table vs_2_x_handlers[] = {
1084     {BWRITERSIO_ADD,            instr_handler},
1085     {BWRITERSIO_NOP,            instr_handler},
1086     {BWRITERSIO_MOV,            instr_handler},
1087     {BWRITERSIO_SUB,            instr_handler},
1088     {BWRITERSIO_MAD,            instr_handler},
1089     {BWRITERSIO_MUL,            instr_handler},
1090     {BWRITERSIO_RCP,            instr_handler},
1091     {BWRITERSIO_RSQ,            instr_handler},
1092     {BWRITERSIO_DP3,            instr_handler},
1093     {BWRITERSIO_DP4,            instr_handler},
1094     {BWRITERSIO_MIN,            instr_handler},
1095     {BWRITERSIO_MAX,            instr_handler},
1096     {BWRITERSIO_SLT,            instr_handler},
1097     {BWRITERSIO_SGE,            instr_handler},
1098     {BWRITERSIO_ABS,            instr_handler},
1099     {BWRITERSIO_EXP,            instr_handler},
1100     {BWRITERSIO_LOG,            instr_handler},
1101     {BWRITERSIO_EXPP,           instr_handler},
1102     {BWRITERSIO_LOGP,           instr_handler},
1103     {BWRITERSIO_DST,            instr_handler},
1104     {BWRITERSIO_LRP,            instr_handler},
1105     {BWRITERSIO_FRC,            instr_handler},
1106     {BWRITERSIO_CRS,            instr_handler},
1107     {BWRITERSIO_SGN,            instr_handler},
1108     {BWRITERSIO_NRM,            instr_handler},
1109     {BWRITERSIO_SINCOS,         instr_handler},
1110     {BWRITERSIO_M4x4,           instr_handler},
1111     {BWRITERSIO_M4x3,           instr_handler},
1112     {BWRITERSIO_M3x4,           instr_handler},
1113     {BWRITERSIO_M3x3,           instr_handler},
1114     {BWRITERSIO_M3x2,           instr_handler},
1115     {BWRITERSIO_LIT,            instr_handler},
1116     {BWRITERSIO_POW,            instr_handler},
1117     {BWRITERSIO_MOVA,           instr_handler},
1118
1119     {BWRITERSIO_CALL,           instr_handler},
1120     {BWRITERSIO_CALLNZ,         instr_handler},
1121     {BWRITERSIO_REP,            instr_handler},
1122     {BWRITERSIO_ENDREP,         instr_handler},
1123     {BWRITERSIO_IF,             instr_handler},
1124     {BWRITERSIO_LABEL,          instr_handler},
1125     {BWRITERSIO_IFC,            instr_handler},
1126     {BWRITERSIO_ELSE,           instr_handler},
1127     {BWRITERSIO_ENDIF,          instr_handler},
1128     {BWRITERSIO_BREAK,          instr_handler},
1129     {BWRITERSIO_BREAKC,         instr_handler},
1130     {BWRITERSIO_LOOP,           instr_handler},
1131     {BWRITERSIO_RET,            instr_handler},
1132     {BWRITERSIO_ENDLOOP,        instr_handler},
1133
1134     {BWRITERSIO_SETP,           instr_handler},
1135     {BWRITERSIO_BREAKP,         instr_handler},
1136
1137     {BWRITERSIO_END,            NULL},
1138 };
1139
1140 static const struct bytecode_backend vs_2_x_backend = {
1141     vs_2_header,
1142     end,
1143     vs_2_srcreg,
1144     vs_12_dstreg,
1145     sm_2_opcode,
1146     vs_2_x_handlers
1147 };
1148
1149 static void write_samplers(const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
1150     DWORD i;
1151     DWORD instr_dcl = D3DSIO_DCL | (2 << D3DSI_INSTLENGTH_SHIFT);
1152     DWORD token;
1153     const DWORD reg = (1<<31) |
1154                       ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) |
1155                       ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) |
1156                       D3DSP_WRITEMASK_ALL;
1157
1158     for(i = 0; i < shader->num_samplers; i++) {
1159         /* Write the DCL instruction */
1160         put_dword(buffer, instr_dcl);
1161         token = (1<<31);
1162         /* Already shifted */
1163         token |= (d3d9_sampler(shader->samplers[i].type)) & D3DSP_TEXTURETYPE_MASK;
1164         put_dword(buffer, token);
1165         put_dword(buffer, reg | (shader->samplers[i].regnum & D3DSP_REGNUM_MASK));
1166     }
1167 }
1168
1169 static void ps_2_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
1170     HRESULT hr = find_ps_builtin_semantics(This, shader, 8);
1171     if(FAILED(hr)) {
1172         This->state = hr;
1173         return;
1174     }
1175
1176     /* Declare the shader type and version */
1177     put_dword(buffer, This->version);
1178     write_samplers(shader, buffer);
1179     write_constF(shader, buffer, TRUE);
1180     write_constB(shader, buffer, TRUE);
1181     write_constI(shader, buffer, TRUE);
1182 }
1183
1184 static void ps_2_srcreg(struct bc_writer *This,
1185                         const struct shader_reg *reg,
1186                         struct bytecode_buffer *buffer) {
1187     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1188     DWORD d3d9reg;
1189     if(reg->rel_reg) {
1190         WARN("Relative addressing not supported in <= ps_3_0\n");
1191         This->state = E_INVALIDARG;
1192         return;
1193     }
1194
1195     switch(reg->type) {
1196         case BWRITERSPR_INPUT:
1197             token |= map_ps_input(This, reg);
1198             break;
1199
1200             /* Can be mapped 1:1 */
1201         case BWRITERSPR_TEMP:
1202         case BWRITERSPR_CONST:
1203         case BWRITERSPR_COLOROUT:
1204         case BWRITERSPR_CONSTBOOL:
1205         case BWRITERSPR_CONSTINT:
1206         case BWRITERSPR_SAMPLER:
1207         case BWRITERSPR_LABEL:
1208         case BWRITERSPR_DEPTHOUT:
1209             d3d9reg = d3d9_register(reg->type);
1210             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1211             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1212             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1213             break;
1214
1215         case BWRITERSPR_PREDICATE:
1216             if(This->version != BWRITERPS_VERSION(2, 1)){
1217                 WARN("Predicate register not supported in ps_2_0\n");
1218                 This->state = E_INVALIDARG;
1219             }
1220             if(reg->regnum) {
1221                 WARN("Predicate register with regnum %u not supported\n",
1222                      reg->regnum);
1223                 This->state = E_INVALIDARG;
1224             }
1225             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1226             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1227             token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
1228             break;
1229
1230         default:
1231             WARN("Invalid register type for ps_2_0 shader\n");
1232             This->state = E_INVALIDARG;
1233             return;
1234     }
1235
1236     token |= d3d9_swizzle(reg->swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
1237
1238     token |= d3d9_srcmod(reg->srcmod);
1239     put_dword(buffer, token);
1240 }
1241
1242 static void ps_2_0_dstreg(struct bc_writer *This,
1243                           const struct shader_reg *reg,
1244                           struct bytecode_buffer *buffer,
1245                           DWORD shift, DWORD mod) {
1246     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1247     DWORD d3d9reg;
1248
1249     if(reg->rel_reg) {
1250         WARN("Relative addressing not supported for destination registers\n");
1251         This->state = E_INVALIDARG;
1252         return;
1253     }
1254
1255     switch(reg->type) {
1256         case BWRITERSPR_TEMP: /* 1:1 mapping */
1257         case BWRITERSPR_COLOROUT:
1258         case BWRITERSPR_DEPTHOUT:
1259             d3d9reg = d3d9_register(reg->type);
1260             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1261             token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1262             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1263             break;
1264
1265         case BWRITERSPR_PREDICATE:
1266             if(This->version != BWRITERPS_VERSION(2, 1)){
1267                 WARN("Predicate register not supported in ps_2_0\n");
1268                 This->state = E_INVALIDARG;
1269             }
1270             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1271             token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1272             token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1273             break;
1274
1275         /* texkill uses the input register as a destination parameter */
1276         case BWRITERSPR_INPUT:
1277             token |= map_ps_input(This, reg);
1278             break;
1279
1280         default:
1281             WARN("Invalid dest register type for 2.x pshader\n");
1282             This->state = E_INVALIDARG;
1283             return;
1284     }
1285
1286     token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
1287     token |= d3d9_dstmod(mod);
1288
1289     token |= d3d9_writemask(reg->writemask);
1290     put_dword(buffer, token);
1291 }
1292
1293 static const struct instr_handler_table ps_2_0_handlers[] = {
1294     {BWRITERSIO_ADD,            instr_handler},
1295     {BWRITERSIO_NOP,            instr_handler},
1296     {BWRITERSIO_MOV,            instr_handler},
1297     {BWRITERSIO_SUB,            instr_handler},
1298     {BWRITERSIO_MAD,            instr_handler},
1299     {BWRITERSIO_MUL,            instr_handler},
1300     {BWRITERSIO_RCP,            instr_handler},
1301     {BWRITERSIO_RSQ,            instr_handler},
1302     {BWRITERSIO_DP3,            instr_handler},
1303     {BWRITERSIO_DP4,            instr_handler},
1304     {BWRITERSIO_MIN,            instr_handler},
1305     {BWRITERSIO_MAX,            instr_handler},
1306     {BWRITERSIO_ABS,            instr_handler},
1307     {BWRITERSIO_EXP,            instr_handler},
1308     {BWRITERSIO_LOG,            instr_handler},
1309     {BWRITERSIO_EXPP,           instr_handler},
1310     {BWRITERSIO_LOGP,           instr_handler},
1311     {BWRITERSIO_LRP,            instr_handler},
1312     {BWRITERSIO_FRC,            instr_handler},
1313     {BWRITERSIO_CRS,            instr_handler},
1314     {BWRITERSIO_NRM,            instr_handler},
1315     {BWRITERSIO_SINCOS,         instr_handler},
1316     {BWRITERSIO_M4x4,           instr_handler},
1317     {BWRITERSIO_M4x3,           instr_handler},
1318     {BWRITERSIO_M3x4,           instr_handler},
1319     {BWRITERSIO_M3x3,           instr_handler},
1320     {BWRITERSIO_M3x2,           instr_handler},
1321     {BWRITERSIO_POW,            instr_handler},
1322     {BWRITERSIO_DP2ADD,         instr_handler},
1323     {BWRITERSIO_CMP,            instr_handler},
1324
1325     {BWRITERSIO_TEX,            instr_handler},
1326     {BWRITERSIO_TEXLDP,         instr_handler},
1327     {BWRITERSIO_TEXLDB,         instr_handler},
1328     {BWRITERSIO_TEXKILL,        instr_handler},
1329
1330     {BWRITERSIO_END,            NULL},
1331 };
1332
1333 static const struct bytecode_backend ps_2_0_backend = {
1334     ps_2_header,
1335     end,
1336     ps_2_srcreg,
1337     ps_2_0_dstreg,
1338     sm_2_opcode,
1339     ps_2_0_handlers
1340 };
1341
1342 static const struct instr_handler_table ps_2_x_handlers[] = {
1343     {BWRITERSIO_ADD,            instr_handler},
1344     {BWRITERSIO_NOP,            instr_handler},
1345     {BWRITERSIO_MOV,            instr_handler},
1346     {BWRITERSIO_SUB,            instr_handler},
1347     {BWRITERSIO_MAD,            instr_handler},
1348     {BWRITERSIO_MUL,            instr_handler},
1349     {BWRITERSIO_RCP,            instr_handler},
1350     {BWRITERSIO_RSQ,            instr_handler},
1351     {BWRITERSIO_DP3,            instr_handler},
1352     {BWRITERSIO_DP4,            instr_handler},
1353     {BWRITERSIO_MIN,            instr_handler},
1354     {BWRITERSIO_MAX,            instr_handler},
1355     {BWRITERSIO_ABS,            instr_handler},
1356     {BWRITERSIO_EXP,            instr_handler},
1357     {BWRITERSIO_LOG,            instr_handler},
1358     {BWRITERSIO_EXPP,           instr_handler},
1359     {BWRITERSIO_LOGP,           instr_handler},
1360     {BWRITERSIO_LRP,            instr_handler},
1361     {BWRITERSIO_FRC,            instr_handler},
1362     {BWRITERSIO_CRS,            instr_handler},
1363     {BWRITERSIO_NRM,            instr_handler},
1364     {BWRITERSIO_SINCOS,         instr_handler},
1365     {BWRITERSIO_M4x4,           instr_handler},
1366     {BWRITERSIO_M4x3,           instr_handler},
1367     {BWRITERSIO_M3x4,           instr_handler},
1368     {BWRITERSIO_M3x3,           instr_handler},
1369     {BWRITERSIO_M3x2,           instr_handler},
1370     {BWRITERSIO_POW,            instr_handler},
1371     {BWRITERSIO_DP2ADD,         instr_handler},
1372     {BWRITERSIO_CMP,            instr_handler},
1373
1374     {BWRITERSIO_CALL,           instr_handler},
1375     {BWRITERSIO_CALLNZ,         instr_handler},
1376     {BWRITERSIO_REP,            instr_handler},
1377     {BWRITERSIO_ENDREP,         instr_handler},
1378     {BWRITERSIO_IF,             instr_handler},
1379     {BWRITERSIO_LABEL,          instr_handler},
1380     {BWRITERSIO_IFC,            instr_handler},
1381     {BWRITERSIO_ELSE,           instr_handler},
1382     {BWRITERSIO_ENDIF,          instr_handler},
1383     {BWRITERSIO_BREAK,          instr_handler},
1384     {BWRITERSIO_BREAKC,         instr_handler},
1385     {BWRITERSIO_RET,            instr_handler},
1386
1387     {BWRITERSIO_TEX,            instr_handler},
1388     {BWRITERSIO_TEXLDP,         instr_handler},
1389     {BWRITERSIO_TEXLDB,         instr_handler},
1390     {BWRITERSIO_TEXKILL,        instr_handler},
1391     {BWRITERSIO_DSX,            instr_handler},
1392     {BWRITERSIO_DSY,            instr_handler},
1393
1394     {BWRITERSIO_SETP,           instr_handler},
1395     {BWRITERSIO_BREAKP,         instr_handler},
1396
1397     {BWRITERSIO_TEXLDD,         instr_handler},
1398
1399     {BWRITERSIO_END,            NULL},
1400 };
1401
1402 static const struct bytecode_backend ps_2_x_backend = {
1403     ps_2_header,
1404     end,
1405     ps_2_srcreg,
1406     ps_2_0_dstreg,
1407     sm_2_opcode,
1408     ps_2_x_handlers
1409 };
1410
1411 static void sm_3_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
1412     /* Declare the shader type and version */
1413     put_dword(buffer, This->version);
1414
1415     write_declarations(buffer, TRUE, shader->inputs, shader->num_inputs, D3DSPR_INPUT);
1416     write_declarations(buffer, TRUE, shader->outputs, shader->num_outputs, D3DSPR_OUTPUT);
1417     write_constF(shader, buffer, TRUE);
1418     write_constB(shader, buffer, TRUE);
1419     write_constI(shader, buffer, TRUE);
1420     write_samplers(shader, buffer);
1421     return;
1422 }
1423
1424 static void sm_3_srcreg(struct bc_writer *This,
1425                         const struct shader_reg *reg,
1426                         struct bytecode_buffer *buffer) {
1427     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1428     DWORD d3d9reg;
1429
1430     d3d9reg = d3d9_register(reg->type);
1431     token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1432     token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1433     token |= reg->regnum & D3DSP_REGNUM_MASK;
1434
1435     token |= d3d9_swizzle(reg->swizzle) & D3DVS_SWIZZLE_MASK;
1436     token |= d3d9_srcmod(reg->srcmod);
1437
1438     if(reg->rel_reg) {
1439         if(reg->type == BWRITERSPR_CONST && This->version == BWRITERPS_VERSION(3, 0)) {
1440             WARN("c%u[...] is unsupported in ps_3_0\n", reg->regnum);
1441             This->state = E_INVALIDARG;
1442             return;
1443         }
1444         if(((reg->rel_reg->type == BWRITERSPR_ADDR && This->version == BWRITERVS_VERSION(3, 0)) ||
1445            reg->rel_reg->type == BWRITERSPR_LOOP) &&
1446            reg->rel_reg->regnum == 0) {
1447             token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
1448         } else {
1449             WARN("Unsupported relative addressing register\n");
1450             This->state = E_INVALIDARG;
1451             return;
1452         }
1453     }
1454
1455     put_dword(buffer, token);
1456
1457     /* vs_2_0 and newer write the register containing the index explicitly in the
1458      * binary code
1459      */
1460     if(token & D3DVS_ADDRMODE_RELATIVE) {
1461         sm_3_srcreg(This, reg->rel_reg, buffer);
1462     }
1463 }
1464
1465 static void sm_3_dstreg(struct bc_writer *This,
1466                         const struct shader_reg *reg,
1467                         struct bytecode_buffer *buffer,
1468                         DWORD shift, DWORD mod) {
1469     DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
1470     DWORD d3d9reg;
1471
1472     if(reg->rel_reg) {
1473         if(This->version == BWRITERVS_VERSION(3, 0) &&
1474            reg->type == BWRITERSPR_OUTPUT) {
1475             token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
1476         } else {
1477             WARN("Relative addressing not supported for this shader type or register type\n");
1478             This->state = E_INVALIDARG;
1479             return;
1480         }
1481     }
1482
1483     d3d9reg = d3d9_register(reg->type);
1484     token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
1485     token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
1486     token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
1487
1488     token |= d3d9_dstmod(mod);
1489
1490     token |= d3d9_writemask(reg->writemask);
1491     put_dword(buffer, token);
1492
1493     /* vs_2_0 and newer write the register containing the index explicitly in the
1494      * binary code
1495      */
1496     if(token & D3DVS_ADDRMODE_RELATIVE) {
1497         sm_3_srcreg(This, reg->rel_reg, buffer);
1498     }
1499 }
1500
1501 static const struct instr_handler_table vs_3_handlers[] = {
1502     {BWRITERSIO_ADD,            instr_handler},
1503     {BWRITERSIO_NOP,            instr_handler},
1504     {BWRITERSIO_MOV,            instr_handler},
1505     {BWRITERSIO_SUB,            instr_handler},
1506     {BWRITERSIO_MAD,            instr_handler},
1507     {BWRITERSIO_MUL,            instr_handler},
1508     {BWRITERSIO_RCP,            instr_handler},
1509     {BWRITERSIO_RSQ,            instr_handler},
1510     {BWRITERSIO_DP3,            instr_handler},
1511     {BWRITERSIO_DP4,            instr_handler},
1512     {BWRITERSIO_MIN,            instr_handler},
1513     {BWRITERSIO_MAX,            instr_handler},
1514     {BWRITERSIO_SLT,            instr_handler},
1515     {BWRITERSIO_SGE,            instr_handler},
1516     {BWRITERSIO_ABS,            instr_handler},
1517     {BWRITERSIO_EXP,            instr_handler},
1518     {BWRITERSIO_LOG,            instr_handler},
1519     {BWRITERSIO_EXPP,           instr_handler},
1520     {BWRITERSIO_LOGP,           instr_handler},
1521     {BWRITERSIO_DST,            instr_handler},
1522     {BWRITERSIO_LRP,            instr_handler},
1523     {BWRITERSIO_FRC,            instr_handler},
1524     {BWRITERSIO_CRS,            instr_handler},
1525     {BWRITERSIO_SGN,            instr_handler},
1526     {BWRITERSIO_NRM,            instr_handler},
1527     {BWRITERSIO_SINCOS,         instr_handler},
1528     {BWRITERSIO_M4x4,           instr_handler},
1529     {BWRITERSIO_M4x3,           instr_handler},
1530     {BWRITERSIO_M3x4,           instr_handler},
1531     {BWRITERSIO_M3x3,           instr_handler},
1532     {BWRITERSIO_M3x2,           instr_handler},
1533     {BWRITERSIO_LIT,            instr_handler},
1534     {BWRITERSIO_POW,            instr_handler},
1535     {BWRITERSIO_MOVA,           instr_handler},
1536
1537     {BWRITERSIO_CALL,           instr_handler},
1538     {BWRITERSIO_CALLNZ,         instr_handler},
1539     {BWRITERSIO_REP,            instr_handler},
1540     {BWRITERSIO_ENDREP,         instr_handler},
1541     {BWRITERSIO_IF,             instr_handler},
1542     {BWRITERSIO_LABEL,          instr_handler},
1543     {BWRITERSIO_IFC,            instr_handler},
1544     {BWRITERSIO_ELSE,           instr_handler},
1545     {BWRITERSIO_ENDIF,          instr_handler},
1546     {BWRITERSIO_BREAK,          instr_handler},
1547     {BWRITERSIO_BREAKC,         instr_handler},
1548     {BWRITERSIO_LOOP,           instr_handler},
1549     {BWRITERSIO_RET,            instr_handler},
1550     {BWRITERSIO_ENDLOOP,        instr_handler},
1551
1552     {BWRITERSIO_SETP,           instr_handler},
1553     {BWRITERSIO_BREAKP,         instr_handler},
1554     {BWRITERSIO_TEXLDL,         instr_handler},
1555
1556     {BWRITERSIO_END,            NULL},
1557 };
1558
1559 static const struct bytecode_backend vs_3_backend = {
1560     sm_3_header,
1561     end,
1562     sm_3_srcreg,
1563     sm_3_dstreg,
1564     sm_2_opcode,
1565     vs_3_handlers
1566 };
1567
1568 static const struct instr_handler_table ps_3_handlers[] = {
1569     {BWRITERSIO_ADD,            instr_handler},
1570     {BWRITERSIO_NOP,            instr_handler},
1571     {BWRITERSIO_MOV,            instr_handler},
1572     {BWRITERSIO_SUB,            instr_handler},
1573     {BWRITERSIO_MAD,            instr_handler},
1574     {BWRITERSIO_MUL,            instr_handler},
1575     {BWRITERSIO_RCP,            instr_handler},
1576     {BWRITERSIO_RSQ,            instr_handler},
1577     {BWRITERSIO_DP3,            instr_handler},
1578     {BWRITERSIO_DP4,            instr_handler},
1579     {BWRITERSIO_MIN,            instr_handler},
1580     {BWRITERSIO_MAX,            instr_handler},
1581     {BWRITERSIO_ABS,            instr_handler},
1582     {BWRITERSIO_EXP,            instr_handler},
1583     {BWRITERSIO_LOG,            instr_handler},
1584     {BWRITERSIO_EXPP,           instr_handler},
1585     {BWRITERSIO_LOGP,           instr_handler},
1586     {BWRITERSIO_LRP,            instr_handler},
1587     {BWRITERSIO_FRC,            instr_handler},
1588     {BWRITERSIO_CRS,            instr_handler},
1589     {BWRITERSIO_NRM,            instr_handler},
1590     {BWRITERSIO_SINCOS,         instr_handler},
1591     {BWRITERSIO_M4x4,           instr_handler},
1592     {BWRITERSIO_M4x3,           instr_handler},
1593     {BWRITERSIO_M3x4,           instr_handler},
1594     {BWRITERSIO_M3x3,           instr_handler},
1595     {BWRITERSIO_M3x2,           instr_handler},
1596     {BWRITERSIO_POW,            instr_handler},
1597     {BWRITERSIO_DP2ADD,         instr_handler},
1598     {BWRITERSIO_CMP,            instr_handler},
1599
1600     {BWRITERSIO_CALL,           instr_handler},
1601     {BWRITERSIO_CALLNZ,         instr_handler},
1602     {BWRITERSIO_REP,            instr_handler},
1603     {BWRITERSIO_ENDREP,         instr_handler},
1604     {BWRITERSIO_IF,             instr_handler},
1605     {BWRITERSIO_LABEL,          instr_handler},
1606     {BWRITERSIO_IFC,            instr_handler},
1607     {BWRITERSIO_ELSE,           instr_handler},
1608     {BWRITERSIO_ENDIF,          instr_handler},
1609     {BWRITERSIO_BREAK,          instr_handler},
1610     {BWRITERSIO_BREAKC,         instr_handler},
1611     {BWRITERSIO_LOOP,           instr_handler},
1612     {BWRITERSIO_RET,            instr_handler},
1613     {BWRITERSIO_ENDLOOP,        instr_handler},
1614
1615     {BWRITERSIO_SETP,           instr_handler},
1616     {BWRITERSIO_BREAKP,         instr_handler},
1617     {BWRITERSIO_TEXLDL,         instr_handler},
1618
1619     {BWRITERSIO_TEX,            instr_handler},
1620     {BWRITERSIO_TEXLDP,         instr_handler},
1621     {BWRITERSIO_TEXLDB,         instr_handler},
1622     {BWRITERSIO_TEXKILL,        instr_handler},
1623     {BWRITERSIO_DSX,            instr_handler},
1624     {BWRITERSIO_DSY,            instr_handler},
1625     {BWRITERSIO_TEXLDD,         instr_handler},
1626
1627     {BWRITERSIO_END,            NULL},
1628 };
1629
1630 static const struct bytecode_backend ps_3_backend = {
1631     sm_3_header,
1632     end,
1633     sm_3_srcreg,
1634     sm_3_dstreg,
1635     sm_2_opcode,
1636     ps_3_handlers
1637 };
1638
1639 static void init_vs10_dx9_writer(struct bc_writer *writer) {
1640     TRACE("Creating DirectX9 vertex shader 1.0 writer\n");
1641     writer->funcs = &vs_1_x_backend;
1642 }
1643
1644 static void init_vs11_dx9_writer(struct bc_writer *writer) {
1645     TRACE("Creating DirectX9 vertex shader 1.1 writer\n");
1646     writer->funcs = &vs_1_x_backend;
1647 }
1648
1649 static void init_vs20_dx9_writer(struct bc_writer *writer) {
1650     TRACE("Creating DirectX9 vertex shader 2.0 writer\n");
1651     writer->funcs = &vs_2_0_backend;
1652 }
1653
1654 static void init_vs2x_dx9_writer(struct bc_writer *writer) {
1655     TRACE("Creating DirectX9 vertex shader 2.x writer\n");
1656     writer->funcs = &vs_2_x_backend;
1657 }
1658
1659 static void init_vs30_dx9_writer(struct bc_writer *writer) {
1660     TRACE("Creating DirectX9 vertex shader 3.0 writer\n");
1661     writer->funcs = &vs_3_backend;
1662 }
1663
1664 static void init_ps20_dx9_writer(struct bc_writer *writer) {
1665     TRACE("Creating DirectX9 pixel shader 2.0 writer\n");
1666     writer->funcs = &ps_2_0_backend;
1667 }
1668
1669 static void init_ps2x_dx9_writer(struct bc_writer *writer) {
1670     TRACE("Creating DirectX9 pixel shader 2.x writer\n");
1671     writer->funcs = &ps_2_x_backend;
1672 }
1673
1674 static void init_ps30_dx9_writer(struct bc_writer *writer) {
1675     TRACE("Creating DirectX9 pixel shader 3.0 writer\n");
1676     writer->funcs = &ps_3_backend;
1677 }
1678
1679 static struct bc_writer *create_writer(DWORD version, DWORD dxversion) {
1680     struct bc_writer *ret = asm_alloc(sizeof(*ret));
1681
1682     if(!ret) {
1683         WARN("Failed to allocate a bytecode writer instance\n");
1684         return NULL;
1685     }
1686
1687     switch(version) {
1688         case BWRITERVS_VERSION(1, 0):
1689             if(dxversion != 9) {
1690                 WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion);
1691                 goto fail;
1692             }
1693             init_vs10_dx9_writer(ret);
1694             break;
1695         case BWRITERVS_VERSION(1, 1):
1696             if(dxversion != 9) {
1697                 WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion);
1698                 goto fail;
1699             }
1700             init_vs11_dx9_writer(ret);
1701             break;
1702         case BWRITERVS_VERSION(2, 0):
1703             if(dxversion != 9) {
1704                 WARN("Unsupported dxversion for vertex shader 2.0 requested: %u\n", dxversion);
1705                 goto fail;
1706             }
1707             init_vs20_dx9_writer(ret);
1708             break;
1709         case BWRITERVS_VERSION(2, 1):
1710             if(dxversion != 9) {
1711                 WARN("Unsupported dxversion for vertex shader 2.x requested: %u\n", dxversion);
1712                 goto fail;
1713             }
1714             init_vs2x_dx9_writer(ret);
1715             break;
1716         case BWRITERVS_VERSION(3, 0):
1717             if(dxversion != 9) {
1718                 WARN("Unsupported dxversion for vertex shader 3.0 requested: %u\n", dxversion);
1719                 goto fail;
1720             }
1721             init_vs30_dx9_writer(ret);
1722             break;
1723
1724         case BWRITERPS_VERSION(1, 0):
1725             if(dxversion != 9) {
1726                 WARN("Unsupported dxversion for pixel shader 1.0 requested: %u\n", dxversion);
1727                 goto fail;
1728             }
1729             /* TODO: Set the appropriate writer backend */
1730             break;
1731         case BWRITERPS_VERSION(1, 1):
1732             if(dxversion != 9) {
1733                 WARN("Unsupported dxversion for pixel shader 1.1 requested: %u\n", dxversion);
1734                 goto fail;
1735             }
1736             /* TODO: Set the appropriate writer backend */
1737             break;
1738         case BWRITERPS_VERSION(1, 2):
1739             if(dxversion != 9) {
1740                 WARN("Unsupported dxversion for pixel shader 1.2 requested: %u\n", dxversion);
1741                 goto fail;
1742             }
1743             /* TODO: Set the appropriate writer backend */
1744             break;
1745         case BWRITERPS_VERSION(1, 3):
1746             if(dxversion != 9) {
1747                 WARN("Unsupported dxversion for pixel shader 1.3 requested: %u\n", dxversion);
1748                 goto fail;
1749             }
1750             /* TODO: Set the appropriate writer backend */
1751             break;
1752         case BWRITERPS_VERSION(1, 4):
1753             if(dxversion != 9) {
1754                 WARN("Unsupported dxversion for pixel shader 1.4 requested: %u\n", dxversion);
1755                 goto fail;
1756             }
1757             /* TODO: Set the appropriate writer backend */
1758             break;
1759
1760         case BWRITERPS_VERSION(2, 0):
1761             if(dxversion != 9) {
1762                 WARN("Unsupported dxversion for pixel shader 2.0 requested: %u\n", dxversion);
1763                 goto fail;
1764             }
1765             init_ps20_dx9_writer(ret);
1766             break;
1767
1768         case BWRITERPS_VERSION(2, 1):
1769             if(dxversion != 9) {
1770                 WARN("Unsupported dxversion for pixel shader 2.x requested: %u\n", dxversion);
1771                 goto fail;
1772             }
1773             init_ps2x_dx9_writer(ret);
1774             break;
1775
1776         case BWRITERPS_VERSION(3, 0):
1777             if(dxversion != 9) {
1778                 WARN("Unsupported dxversion for pixel shader 3.0 requested: %u\n", dxversion);
1779                 goto fail;
1780             }
1781             init_ps30_dx9_writer(ret);
1782             break;
1783
1784         default:
1785             WARN("Unexpected shader version requested: %08x\n", version);
1786             goto fail;
1787     }
1788     ret->version = version;
1789     return ret;
1790
1791 fail:
1792     asm_free(ret);
1793     return NULL;
1794 }
1795
1796 static HRESULT call_instr_handler(struct bc_writer *writer,
1797                                   const struct instruction *instr,
1798                                   struct bytecode_buffer *buffer) {
1799     DWORD i=0;
1800
1801     while(writer->funcs->instructions[i].opcode != BWRITERSIO_END) {
1802         if(instr->opcode == writer->funcs->instructions[i].opcode) {
1803             if(!writer->funcs->instructions[i].func) {
1804                 WARN("Opcode %u not supported by this profile\n", instr->opcode);
1805                 return E_INVALIDARG;
1806             }
1807             writer->funcs->instructions[i].func(writer, instr, buffer);
1808             return S_OK;
1809         }
1810         i++;
1811     }
1812
1813     FIXME("Unhandled instruction %u\n", instr->opcode);
1814     return E_INVALIDARG;
1815 }
1816
1817 /* SlWriteBytecode (wineshader.@)
1818  *
1819  * Writes shader version specific bytecode from the shader passed in.
1820  * The returned bytecode can be passed to the Direct3D runtime like
1821  * IDirect3DDevice9::Create*Shader.
1822  *
1823  * Parameters:
1824  *  shader: Shader to translate into bytecode
1825  *  version: Shader version to generate(d3d version token)
1826  *  dxversion: DirectX version the code targets
1827  *  result: the resulting shader bytecode
1828  *
1829  * Return values:
1830  *  S_OK on success
1831  */
1832 DWORD SlWriteBytecode(const struct bwriter_shader *shader, int dxversion, DWORD **result) {
1833     struct bc_writer *writer;
1834     struct bytecode_buffer *buffer = NULL;
1835     HRESULT hr;
1836     unsigned int i;
1837
1838     if(!shader){
1839         ERR("NULL shader structure, aborting\n");
1840         return E_FAIL;
1841     }
1842     writer = create_writer(shader->version, dxversion);
1843     *result = NULL;
1844
1845     if(!writer) {
1846         WARN("Could not create a bytecode writer instance. Either unsupported version\n");
1847         WARN("or out of memory\n");
1848         hr = E_FAIL;
1849         goto error;
1850     }
1851
1852     buffer = allocate_buffer();
1853     if(!buffer) {
1854         WARN("Failed to allocate a buffer for the shader bytecode\n");
1855         hr = E_FAIL;
1856         goto error;
1857     }
1858
1859     writer->funcs->header(writer, shader, buffer);
1860     if(FAILED(writer->state)) {
1861         hr = writer->state;
1862         goto error;
1863     }
1864
1865     for(i = 0; i < shader->num_instrs; i++) {
1866         hr = call_instr_handler(writer, shader->instr[i], buffer);
1867         if(FAILED(hr)) {
1868             goto error;
1869         }
1870     }
1871
1872     if(FAILED(writer->state)) {
1873         hr = writer->state;
1874         goto error;
1875     }
1876
1877     writer->funcs->end(writer, shader, buffer);
1878
1879     if(FAILED(buffer->state)) {
1880         hr = buffer->state;
1881         goto error;
1882     }
1883
1884     /* Cut off unneeded memory from the result buffer */
1885     *result = asm_realloc(buffer->data,
1886                          sizeof(DWORD) * buffer->size);
1887     if(!*result) {
1888         *result = buffer->data;
1889     }
1890     buffer->data = NULL;
1891     hr = S_OK;
1892
1893 error:
1894     if(buffer) {
1895         asm_free(buffer->data);
1896         asm_free(buffer);
1897     }
1898     asm_free(writer);
1899     return hr;
1900 }
1901
1902 void SlDeleteShader(struct bwriter_shader *shader) {
1903     unsigned int i, j;
1904
1905     TRACE("Deleting shader %p\n", shader);
1906
1907     for(i = 0; i < shader->num_cf; i++) {
1908         asm_free(shader->constF[i]);
1909     }
1910     asm_free(shader->constF);
1911     for(i = 0; i < shader->num_ci; i++) {
1912         asm_free(shader->constI[i]);
1913     }
1914     asm_free(shader->constI);
1915     for(i = 0; i < shader->num_cb; i++) {
1916         asm_free(shader->constB[i]);
1917     }
1918     asm_free(shader->constB);
1919
1920     asm_free(shader->inputs);
1921     asm_free(shader->outputs);
1922     asm_free(shader->samplers);
1923
1924     for(i = 0; i < shader->num_instrs; i++) {
1925         for(j = 0; j < shader->instr[i]->num_srcs; j++) {
1926             asm_free(shader->instr[i]->src[j].rel_reg);
1927         }
1928         asm_free(shader->instr[i]->src);
1929         asm_free(shader->instr[i]);
1930     }
1931     asm_free(shader->instr);
1932
1933     asm_free(shader);
1934 }