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