2 * Direct3D bytecode output functions
4 * Copyright 2008 Stefan Dösinger
5 * Copyright 2009 Matteo Bruni
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
25 #include "wine/debug.h"
27 #include "d3d9types.h"
28 #include "d3dcompiler_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(asmshader
);
32 /****************************************************************
33 * General assembler shader construction helper routines follow *
34 ****************************************************************/
35 /* struct instruction *alloc_instr
37 * Allocates a new instruction structure with srcs registers
40 * srcs: Number of source registers to allocate
43 * A pointer to the allocated instruction structure
44 * NULL in case of an allocation failure
46 struct instruction
*alloc_instr(unsigned int srcs
) {
47 struct instruction
*ret
= asm_alloc(sizeof(*ret
));
49 ERR("Failed to allocate memory for an instruction structure\n");
54 ret
->src
= asm_alloc(srcs
* sizeof(*ret
->src
));
56 ERR("Failed to allocate memory for instruction registers\n");
65 /* void add_instruction
67 * Adds a new instruction to the shader's instructions array and grows the instruction array
70 * The function does NOT copy the instruction structure. Make sure not to release the
71 * instruction or any of its substructures like registers.
74 * shader: Shader to add the instruction to
75 * instr: Instruction to add to the shader
77 BOOL
add_instruction(struct bwriter_shader
*shader
, struct instruction
*instr
) {
78 struct instruction
**new_instructions
;
80 if(!shader
) return FALSE
;
82 if(shader
->instr_alloc_size
== 0) {
83 shader
->instr
= asm_alloc(sizeof(*shader
->instr
) * INSTRARRAY_INITIAL_SIZE
);
85 ERR("Failed to allocate the shader instruction array\n");
88 shader
->instr_alloc_size
= INSTRARRAY_INITIAL_SIZE
;
89 } else if(shader
->instr_alloc_size
== shader
->num_instrs
) {
90 new_instructions
= asm_realloc(shader
->instr
,
91 sizeof(*shader
->instr
) * (shader
->instr_alloc_size
) * 2);
92 if(!new_instructions
) {
93 ERR("Failed to grow the shader instruction array\n");
96 shader
->instr
= new_instructions
;
97 shader
->instr_alloc_size
= shader
->instr_alloc_size
* 2;
98 } else if(shader
->num_instrs
> shader
->instr_alloc_size
) {
99 ERR("More instructions than allocated. This should not happen\n");
103 shader
->instr
[shader
->num_instrs
] = instr
;
104 shader
->num_instrs
++;
108 BOOL
add_constF(struct bwriter_shader
*shader
, DWORD reg
, float x
, float y
, float z
, float w
) {
109 struct constant
*newconst
;
112 struct constant
**newarray
;
113 newarray
= asm_realloc(shader
->constF
,
114 sizeof(*shader
->constF
) * (shader
->num_cf
+ 1));
116 ERR("Failed to grow the constants array\n");
119 shader
->constF
= newarray
;
121 shader
->constF
= asm_alloc(sizeof(*shader
->constF
));
122 if(!shader
->constF
) {
123 ERR("Failed to allocate the constants array\n");
128 newconst
= asm_alloc(sizeof(*newconst
));
130 ERR("Failed to allocate a new constant\n");
133 newconst
->regnum
= reg
;
134 newconst
->value
[0].f
= x
;
135 newconst
->value
[1].f
= y
;
136 newconst
->value
[2].f
= z
;
137 newconst
->value
[3].f
= w
;
138 shader
->constF
[shader
->num_cf
] = newconst
;
144 BOOL
add_constI(struct bwriter_shader
*shader
, DWORD reg
, INT x
, INT y
, INT z
, INT w
) {
145 struct constant
*newconst
;
148 struct constant
**newarray
;
149 newarray
= asm_realloc(shader
->constI
,
150 sizeof(*shader
->constI
) * (shader
->num_ci
+ 1));
152 ERR("Failed to grow the constants array\n");
155 shader
->constI
= newarray
;
157 shader
->constI
= asm_alloc(sizeof(*shader
->constI
));
158 if(!shader
->constI
) {
159 ERR("Failed to allocate the constants array\n");
164 newconst
= asm_alloc(sizeof(*newconst
));
166 ERR("Failed to allocate a new constant\n");
169 newconst
->regnum
= reg
;
170 newconst
->value
[0].i
= x
;
171 newconst
->value
[1].i
= y
;
172 newconst
->value
[2].i
= z
;
173 newconst
->value
[3].i
= w
;
174 shader
->constI
[shader
->num_ci
] = newconst
;
180 BOOL
add_constB(struct bwriter_shader
*shader
, DWORD reg
, BOOL x
) {
181 struct constant
*newconst
;
184 struct constant
**newarray
;
185 newarray
= asm_realloc(shader
->constB
,
186 sizeof(*shader
->constB
) * (shader
->num_cb
+ 1));
188 ERR("Failed to grow the constants array\n");
191 shader
->constB
= newarray
;
193 shader
->constB
= asm_alloc(sizeof(*shader
->constB
));
194 if(!shader
->constB
) {
195 ERR("Failed to allocate the constants array\n");
200 newconst
= asm_alloc(sizeof(*newconst
));
202 ERR("Failed to allocate a new constant\n");
205 newconst
->regnum
= reg
;
206 newconst
->value
[0].b
= x
;
207 shader
->constB
[shader
->num_cb
] = newconst
;
213 BOOL
record_declaration(struct bwriter_shader
*shader
, DWORD usage
,
214 DWORD usage_idx
, DWORD mod
, BOOL output
,
215 DWORD regnum
, DWORD writemask
, BOOL builtin
) {
217 struct declaration
**decl
;
220 if(!shader
) return FALSE
;
223 num
= &shader
->num_outputs
;
224 decl
= &shader
->outputs
;
226 num
= &shader
->num_inputs
;
227 decl
= &shader
->inputs
;
231 *decl
= asm_alloc(sizeof(**decl
));
233 ERR("Error allocating declarations array\n");
237 struct declaration
*newdecl
;
238 for(i
= 0; i
< *num
; i
++) {
239 if((*decl
)[i
].regnum
== regnum
&& ((*decl
)[i
].writemask
& writemask
)) {
240 WARN("Declaration of register %u already exists, writemask match 0x%x\n",
241 regnum
, (*decl
)[i
].writemask
& writemask
);
245 newdecl
= asm_realloc(*decl
,
246 sizeof(**decl
) * ((*num
) + 1));
248 ERR("Error reallocating declarations array\n");
253 (*decl
)[*num
].usage
= usage
;
254 (*decl
)[*num
].usage_idx
= usage_idx
;
255 (*decl
)[*num
].regnum
= regnum
;
256 (*decl
)[*num
].mod
= mod
;
257 (*decl
)[*num
].writemask
= writemask
;
258 (*decl
)[*num
].builtin
= builtin
;
264 BOOL
record_sampler(struct bwriter_shader
*shader
, DWORD samptype
, DWORD mod
, DWORD regnum
) {
267 if(!shader
) return FALSE
;
269 if(shader
->num_samplers
== 0) {
270 shader
->samplers
= asm_alloc(sizeof(*shader
->samplers
));
271 if(!shader
->samplers
) {
272 ERR("Error allocating samplers array\n");
276 struct samplerdecl
*newarray
;
278 for(i
= 0; i
< shader
->num_samplers
; i
++) {
279 if(shader
->samplers
[i
].regnum
== regnum
) {
280 WARN("Sampler %u already declared\n", regnum
);
281 /* This is not an error as far as the assembler is concerned.
282 * Direct3D might refuse to load the compiled shader though
287 newarray
= asm_realloc(shader
->samplers
,
288 sizeof(*shader
->samplers
) * (shader
->num_samplers
+ 1));
290 ERR("Error reallocating samplers array\n");
293 shader
->samplers
= newarray
;
296 shader
->samplers
[shader
->num_samplers
].type
= samptype
;
297 shader
->samplers
[shader
->num_samplers
].mod
= mod
;
298 shader
->samplers
[shader
->num_samplers
].regnum
= regnum
;
299 shader
->num_samplers
++;
304 /* shader bytecode buffer manipulation functions.
305 * allocate_buffer creates a new buffer structure, put_dword adds a new
306 * DWORD to the buffer. In the rare case of a memory allocation failure
307 * when trying to grow the buffer a flag is set in the buffer to mark it
308 * invalid. This avoids return value checking and passing in many places
310 static struct bytecode_buffer
*allocate_buffer(void) {
311 struct bytecode_buffer
*ret
;
313 ret
= asm_alloc(sizeof(*ret
));
314 if(!ret
) return NULL
;
316 ret
->alloc_size
= BYTECODEBUFFER_INITIAL_SIZE
;
317 ret
->data
= asm_alloc(sizeof(DWORD
) * ret
->alloc_size
);
326 static void put_dword(struct bytecode_buffer
*buffer
, DWORD value
) {
327 if(FAILED(buffer
->state
)) return;
329 if(buffer
->alloc_size
== buffer
->size
) {
331 buffer
->alloc_size
*= 2;
332 newarray
= asm_realloc(buffer
->data
,
333 sizeof(DWORD
) * buffer
->alloc_size
);
335 ERR("Failed to grow the buffer data memory\n");
336 buffer
->state
= E_OUTOFMEMORY
;
339 buffer
->data
= newarray
;
341 buffer
->data
[buffer
->size
++] = value
;
344 /* bwriter -> d3d9 conversion functions. */
345 static DWORD
d3d9_swizzle(DWORD bwriter_swizzle
)
347 /* Currently a NOP, but this allows changing the internal definitions
348 * without side effects. */
351 if ((bwriter_swizzle
& BWRITERVS_X_X
) == BWRITERVS_X_X
) ret
|= D3DVS_X_X
;
352 if ((bwriter_swizzle
& BWRITERVS_X_Y
) == BWRITERVS_X_Y
) ret
|= D3DVS_X_Y
;
353 if ((bwriter_swizzle
& BWRITERVS_X_Z
) == BWRITERVS_X_Z
) ret
|= D3DVS_X_Z
;
354 if ((bwriter_swizzle
& BWRITERVS_X_W
) == BWRITERVS_X_W
) ret
|= D3DVS_X_W
;
356 if ((bwriter_swizzle
& BWRITERVS_Y_X
) == BWRITERVS_Y_X
) ret
|= D3DVS_Y_X
;
357 if ((bwriter_swizzle
& BWRITERVS_Y_Y
) == BWRITERVS_Y_Y
) ret
|= D3DVS_Y_Y
;
358 if ((bwriter_swizzle
& BWRITERVS_Y_Z
) == BWRITERVS_Y_Z
) ret
|= D3DVS_Y_Z
;
359 if ((bwriter_swizzle
& BWRITERVS_Y_W
) == BWRITERVS_Y_W
) ret
|= D3DVS_Y_W
;
361 if ((bwriter_swizzle
& BWRITERVS_Z_X
) == BWRITERVS_Z_X
) ret
|= D3DVS_Z_X
;
362 if ((bwriter_swizzle
& BWRITERVS_Z_Y
) == BWRITERVS_Z_Y
) ret
|= D3DVS_Z_Y
;
363 if ((bwriter_swizzle
& BWRITERVS_Z_Z
) == BWRITERVS_Z_Z
) ret
|= D3DVS_Z_Z
;
364 if ((bwriter_swizzle
& BWRITERVS_Z_W
) == BWRITERVS_Z_W
) ret
|= D3DVS_Z_W
;
366 if ((bwriter_swizzle
& BWRITERVS_W_X
) == BWRITERVS_W_X
) ret
|= D3DVS_W_X
;
367 if ((bwriter_swizzle
& BWRITERVS_W_Y
) == BWRITERVS_W_Y
) ret
|= D3DVS_W_Y
;
368 if ((bwriter_swizzle
& BWRITERVS_W_Z
) == BWRITERVS_W_Z
) ret
|= D3DVS_W_Z
;
369 if ((bwriter_swizzle
& BWRITERVS_W_W
) == BWRITERVS_W_W
) ret
|= D3DVS_W_W
;
374 static DWORD
d3d9_writemask(DWORD bwriter_writemask
)
378 if (bwriter_writemask
& BWRITERSP_WRITEMASK_0
) ret
|= D3DSP_WRITEMASK_0
;
379 if (bwriter_writemask
& BWRITERSP_WRITEMASK_1
) ret
|= D3DSP_WRITEMASK_1
;
380 if (bwriter_writemask
& BWRITERSP_WRITEMASK_2
) ret
|= D3DSP_WRITEMASK_2
;
381 if (bwriter_writemask
& BWRITERSP_WRITEMASK_3
) ret
|= D3DSP_WRITEMASK_3
;
386 static DWORD
d3d9_srcmod(DWORD bwriter_srcmod
)
388 switch (bwriter_srcmod
)
390 case BWRITERSPSM_NONE
: return D3DSPSM_NONE
;
391 case BWRITERSPSM_NEG
: return D3DSPSM_NEG
;
392 case BWRITERSPSM_BIAS
: return D3DSPSM_BIAS
;
393 case BWRITERSPSM_BIASNEG
: return D3DSPSM_BIASNEG
;
394 case BWRITERSPSM_SIGN
: return D3DSPSM_SIGN
;
395 case BWRITERSPSM_SIGNNEG
: return D3DSPSM_SIGNNEG
;
396 case BWRITERSPSM_COMP
: return D3DSPSM_COMP
;
397 case BWRITERSPSM_X2
: return D3DSPSM_X2
;
398 case BWRITERSPSM_X2NEG
: return D3DSPSM_X2NEG
;
399 case BWRITERSPSM_DZ
: return D3DSPSM_DZ
;
400 case BWRITERSPSM_DW
: return D3DSPSM_DW
;
401 case BWRITERSPSM_ABS
: return D3DSPSM_ABS
;
402 case BWRITERSPSM_ABSNEG
: return D3DSPSM_ABSNEG
;
403 case BWRITERSPSM_NOT
: return D3DSPSM_NOT
;
405 FIXME("Unhandled BWRITERSPSM token %#x.\n", bwriter_srcmod
);
410 static DWORD
d3d9_dstmod(DWORD bwriter_mod
)
414 if (bwriter_mod
& BWRITERSPDM_SATURATE
) ret
|= D3DSPDM_SATURATE
;
415 if (bwriter_mod
& BWRITERSPDM_PARTIALPRECISION
) ret
|= D3DSPDM_PARTIALPRECISION
;
416 if (bwriter_mod
& BWRITERSPDM_MSAMPCENTROID
) ret
|= D3DSPDM_MSAMPCENTROID
;
421 static DWORD
d3d9_comparetype(DWORD asmshader_comparetype
)
423 switch (asmshader_comparetype
)
425 case BWRITER_COMPARISON_GT
: return D3DSPC_GT
;
426 case BWRITER_COMPARISON_EQ
: return D3DSPC_EQ
;
427 case BWRITER_COMPARISON_GE
: return D3DSPC_GE
;
428 case BWRITER_COMPARISON_LT
: return D3DSPC_LT
;
429 case BWRITER_COMPARISON_NE
: return D3DSPC_NE
;
430 case BWRITER_COMPARISON_LE
: return D3DSPC_LE
;
432 FIXME("Unexpected BWRITER_COMPARISON type %#x.\n", asmshader_comparetype
);
437 static DWORD
d3d9_sampler(DWORD bwriter_sampler
)
439 if (bwriter_sampler
== BWRITERSTT_UNKNOWN
) return D3DSTT_UNKNOWN
;
440 if (bwriter_sampler
== BWRITERSTT_1D
) return D3DSTT_1D
;
441 if (bwriter_sampler
== BWRITERSTT_2D
) return D3DSTT_2D
;
442 if (bwriter_sampler
== BWRITERSTT_CUBE
) return D3DSTT_CUBE
;
443 if (bwriter_sampler
== BWRITERSTT_VOLUME
) return D3DSTT_VOLUME
;
444 FIXME("Unexpected BWRITERSAMPLER_TEXTURE_TYPE type %#x.\n", bwriter_sampler
);
449 static DWORD
d3d9_register(DWORD bwriter_register
)
451 if (bwriter_register
== BWRITERSPR_TEMP
) return D3DSPR_TEMP
;
452 if (bwriter_register
== BWRITERSPR_INPUT
) return D3DSPR_INPUT
;
453 if (bwriter_register
== BWRITERSPR_CONST
) return D3DSPR_CONST
;
454 if (bwriter_register
== BWRITERSPR_ADDR
) return D3DSPR_ADDR
;
455 if (bwriter_register
== BWRITERSPR_TEXTURE
) return D3DSPR_TEXTURE
;
456 if (bwriter_register
== BWRITERSPR_RASTOUT
) return D3DSPR_RASTOUT
;
457 if (bwriter_register
== BWRITERSPR_ATTROUT
) return D3DSPR_ATTROUT
;
458 if (bwriter_register
== BWRITERSPR_TEXCRDOUT
) return D3DSPR_TEXCRDOUT
;
459 if (bwriter_register
== BWRITERSPR_OUTPUT
) return D3DSPR_OUTPUT
;
460 if (bwriter_register
== BWRITERSPR_CONSTINT
) return D3DSPR_CONSTINT
;
461 if (bwriter_register
== BWRITERSPR_COLOROUT
) return D3DSPR_COLOROUT
;
462 if (bwriter_register
== BWRITERSPR_DEPTHOUT
) return D3DSPR_DEPTHOUT
;
463 if (bwriter_register
== BWRITERSPR_SAMPLER
) return D3DSPR_SAMPLER
;
464 if (bwriter_register
== BWRITERSPR_CONSTBOOL
) return D3DSPR_CONSTBOOL
;
465 if (bwriter_register
== BWRITERSPR_LOOP
) return D3DSPR_LOOP
;
466 if (bwriter_register
== BWRITERSPR_MISCTYPE
) return D3DSPR_MISCTYPE
;
467 if (bwriter_register
== BWRITERSPR_LABEL
) return D3DSPR_LABEL
;
468 if (bwriter_register
== BWRITERSPR_PREDICATE
) return D3DSPR_PREDICATE
;
470 FIXME("Unexpected BWRITERSPR %#x.\n", bwriter_register
);
474 static DWORD
d3d9_opcode(DWORD bwriter_opcode
)
476 switch (bwriter_opcode
)
478 case BWRITERSIO_NOP
: return D3DSIO_NOP
;
479 case BWRITERSIO_MOV
: return D3DSIO_MOV
;
480 case BWRITERSIO_ADD
: return D3DSIO_ADD
;
481 case BWRITERSIO_SUB
: return D3DSIO_SUB
;
482 case BWRITERSIO_MAD
: return D3DSIO_MAD
;
483 case BWRITERSIO_MUL
: return D3DSIO_MUL
;
484 case BWRITERSIO_RCP
: return D3DSIO_RCP
;
485 case BWRITERSIO_RSQ
: return D3DSIO_RSQ
;
486 case BWRITERSIO_DP3
: return D3DSIO_DP3
;
487 case BWRITERSIO_DP4
: return D3DSIO_DP4
;
488 case BWRITERSIO_MIN
: return D3DSIO_MIN
;
489 case BWRITERSIO_MAX
: return D3DSIO_MAX
;
490 case BWRITERSIO_SLT
: return D3DSIO_SLT
;
491 case BWRITERSIO_SGE
: return D3DSIO_SGE
;
492 case BWRITERSIO_EXP
: return D3DSIO_EXP
;
493 case BWRITERSIO_LOG
: return D3DSIO_LOG
;
494 case BWRITERSIO_LIT
: return D3DSIO_LIT
;
495 case BWRITERSIO_DST
: return D3DSIO_DST
;
496 case BWRITERSIO_LRP
: return D3DSIO_LRP
;
497 case BWRITERSIO_FRC
: return D3DSIO_FRC
;
498 case BWRITERSIO_M4x4
: return D3DSIO_M4x4
;
499 case BWRITERSIO_M4x3
: return D3DSIO_M4x3
;
500 case BWRITERSIO_M3x4
: return D3DSIO_M3x4
;
501 case BWRITERSIO_M3x3
: return D3DSIO_M3x3
;
502 case BWRITERSIO_M3x2
: return D3DSIO_M3x2
;
503 case BWRITERSIO_CALL
: return D3DSIO_CALL
;
504 case BWRITERSIO_CALLNZ
: return D3DSIO_CALLNZ
;
505 case BWRITERSIO_LOOP
: return D3DSIO_LOOP
;
506 case BWRITERSIO_RET
: return D3DSIO_RET
;
507 case BWRITERSIO_ENDLOOP
: return D3DSIO_ENDLOOP
;
508 case BWRITERSIO_LABEL
: return D3DSIO_LABEL
;
509 case BWRITERSIO_DCL
: return D3DSIO_DCL
;
510 case BWRITERSIO_POW
: return D3DSIO_POW
;
511 case BWRITERSIO_CRS
: return D3DSIO_CRS
;
512 case BWRITERSIO_SGN
: return D3DSIO_SGN
;
513 case BWRITERSIO_ABS
: return D3DSIO_ABS
;
514 case BWRITERSIO_NRM
: return D3DSIO_NRM
;
515 case BWRITERSIO_SINCOS
: return D3DSIO_SINCOS
;
516 case BWRITERSIO_REP
: return D3DSIO_REP
;
517 case BWRITERSIO_ENDREP
: return D3DSIO_ENDREP
;
518 case BWRITERSIO_IF
: return D3DSIO_IF
;
519 case BWRITERSIO_IFC
: return D3DSIO_IFC
;
520 case BWRITERSIO_ELSE
: return D3DSIO_ELSE
;
521 case BWRITERSIO_ENDIF
: return D3DSIO_ENDIF
;
522 case BWRITERSIO_BREAK
: return D3DSIO_BREAK
;
523 case BWRITERSIO_BREAKC
: return D3DSIO_BREAKC
;
524 case BWRITERSIO_MOVA
: return D3DSIO_MOVA
;
525 case BWRITERSIO_DEFB
: return D3DSIO_DEFB
;
526 case BWRITERSIO_DEFI
: return D3DSIO_DEFI
;
528 case BWRITERSIO_TEXCOORD
: return D3DSIO_TEXCOORD
;
529 case BWRITERSIO_TEXKILL
: return D3DSIO_TEXKILL
;
530 case BWRITERSIO_TEX
: return D3DSIO_TEX
;
531 case BWRITERSIO_TEXBEM
: return D3DSIO_TEXBEM
;
532 case BWRITERSIO_TEXBEML
: return D3DSIO_TEXBEML
;
533 case BWRITERSIO_TEXREG2AR
: return D3DSIO_TEXREG2AR
;
534 case BWRITERSIO_TEXREG2GB
: return D3DSIO_TEXREG2GB
;
535 case BWRITERSIO_TEXM3x2PAD
: return D3DSIO_TEXM3x2PAD
;
536 case BWRITERSIO_TEXM3x2TEX
: return D3DSIO_TEXM3x2TEX
;
537 case BWRITERSIO_TEXM3x3PAD
: return D3DSIO_TEXM3x3PAD
;
538 case BWRITERSIO_TEXM3x3TEX
: return D3DSIO_TEXM3x3TEX
;
539 case BWRITERSIO_TEXM3x3SPEC
: return D3DSIO_TEXM3x3SPEC
;
540 case BWRITERSIO_TEXM3x3VSPEC
:return D3DSIO_TEXM3x3VSPEC
;
541 case BWRITERSIO_EXPP
: return D3DSIO_EXPP
;
542 case BWRITERSIO_LOGP
: return D3DSIO_LOGP
;
543 case BWRITERSIO_CND
: return D3DSIO_CND
;
544 case BWRITERSIO_DEF
: return D3DSIO_DEF
;
545 case BWRITERSIO_TEXREG2RGB
: return D3DSIO_TEXREG2RGB
;
546 case BWRITERSIO_TEXDP3TEX
: return D3DSIO_TEXDP3TEX
;
547 case BWRITERSIO_TEXM3x2DEPTH
:return D3DSIO_TEXM3x2DEPTH
;
548 case BWRITERSIO_TEXDP3
: return D3DSIO_TEXDP3
;
549 case BWRITERSIO_TEXM3x3
: return D3DSIO_TEXM3x3
;
550 case BWRITERSIO_TEXDEPTH
: return D3DSIO_TEXDEPTH
;
551 case BWRITERSIO_CMP
: return D3DSIO_CMP
;
552 case BWRITERSIO_BEM
: return D3DSIO_BEM
;
553 case BWRITERSIO_DP2ADD
: return D3DSIO_DP2ADD
;
554 case BWRITERSIO_DSX
: return D3DSIO_DSX
;
555 case BWRITERSIO_DSY
: return D3DSIO_DSY
;
556 case BWRITERSIO_TEXLDD
: return D3DSIO_TEXLDD
;
557 case BWRITERSIO_SETP
: return D3DSIO_SETP
;
558 case BWRITERSIO_TEXLDL
: return D3DSIO_TEXLDL
;
559 case BWRITERSIO_BREAKP
: return D3DSIO_BREAKP
;
561 case BWRITERSIO_PHASE
: return D3DSIO_PHASE
;
562 case BWRITERSIO_COMMENT
: return D3DSIO_COMMENT
;
563 case BWRITERSIO_END
: return D3DSIO_END
;
565 case BWRITERSIO_TEXLDP
: return D3DSIO_TEX
| D3DSI_TEXLD_PROJECT
;
566 case BWRITERSIO_TEXLDB
: return D3DSIO_TEX
| D3DSI_TEXLD_BIAS
;
569 FIXME("Unhandled BWRITERSIO token %#x.\n", bwriter_opcode
);
574 /******************************************************
575 * Implementation of the writer functions starts here *
576 ******************************************************/
577 static void write_declarations(struct bc_writer
*This
,
578 struct bytecode_buffer
*buffer
, BOOL len
,
579 const struct declaration
*decls
, unsigned int num
, DWORD type
) {
581 DWORD instr_dcl
= D3DSIO_DCL
;
583 struct shader_reg reg
;
585 ZeroMemory(®
, sizeof(reg
));
588 instr_dcl
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
591 for(i
= 0; i
< num
; i
++) {
592 if(decls
[i
].builtin
) continue;
594 /* Write the DCL instruction */
595 put_dword(buffer
, instr_dcl
);
597 /* Write the usage and index */
598 token
= (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
599 token
|= (decls
[i
].usage
<< D3DSP_DCL_USAGE_SHIFT
) & D3DSP_DCL_USAGE_MASK
;
600 token
|= (decls
[i
].usage_idx
<< D3DSP_DCL_USAGEINDEX_SHIFT
) & D3DSP_DCL_USAGEINDEX_MASK
;
601 put_dword(buffer
, token
);
603 /* Write the dest register */
605 reg
.regnum
= decls
[i
].regnum
;
606 reg
.u
.writemask
= decls
[i
].writemask
;
607 This
->funcs
->dstreg(This
, ®
, buffer
, 0, decls
[i
].mod
);
611 static void write_const(struct constant
**consts
, int num
, DWORD opcode
, DWORD reg_type
, struct bytecode_buffer
*buffer
, BOOL len
) {
613 DWORD instr_def
= opcode
;
614 const DWORD reg
= (1<<31) |
615 ((reg_type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
) |
616 ((reg_type
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
) |
620 if(opcode
== D3DSIO_DEFB
)
621 instr_def
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
623 instr_def
|= 5 << D3DSI_INSTLENGTH_SHIFT
;
626 for(i
= 0; i
< num
; i
++) {
627 /* Write the DEF instruction */
628 put_dword(buffer
, instr_def
);
630 put_dword(buffer
, reg
| (consts
[i
]->regnum
& D3DSP_REGNUM_MASK
));
631 put_dword(buffer
, consts
[i
]->value
[0].d
);
632 if(opcode
!= D3DSIO_DEFB
) {
633 put_dword(buffer
, consts
[i
]->value
[1].d
);
634 put_dword(buffer
, consts
[i
]->value
[2].d
);
635 put_dword(buffer
, consts
[i
]->value
[3].d
);
640 static void write_constF(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
641 write_const(shader
->constF
, shader
->num_cf
, D3DSIO_DEF
, D3DSPR_CONST
, buffer
, len
);
644 /* This function looks for VS 1/2 registers mapping to VS 3 output registers */
645 static HRESULT
vs_find_builtin_varyings(struct bc_writer
*This
, const struct bwriter_shader
*shader
) {
647 DWORD usage
, usage_idx
, writemask
, regnum
;
649 for(i
= 0; i
< shader
->num_outputs
; i
++) {
650 if(!shader
->outputs
[i
].builtin
) continue;
652 usage
= shader
->outputs
[i
].usage
;
653 usage_idx
= shader
->outputs
[i
].usage_idx
;
654 writemask
= shader
->outputs
[i
].writemask
;
655 regnum
= shader
->outputs
[i
].regnum
;
658 case BWRITERDECLUSAGE_POSITION
:
659 case BWRITERDECLUSAGE_POSITIONT
:
661 WARN("dcl_position%u not supported in sm 1/2 shaders\n", usage_idx
);
664 TRACE("o%u is oPos\n", regnum
);
665 This
->oPos_regnum
= regnum
;
668 case BWRITERDECLUSAGE_COLOR
:
670 WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx
);
673 if(writemask
!= BWRITERSP_WRITEMASK_ALL
) {
674 WARN("Only WRITEMASK_ALL is supported on color in sm 1/2\n");
677 TRACE("o%u is oD%u\n", regnum
, usage_idx
);
678 This
->oD_regnum
[usage_idx
] = regnum
;
681 case BWRITERDECLUSAGE_TEXCOORD
:
683 WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx
);
686 if(writemask
!= (BWRITERSP_WRITEMASK_0
) &&
687 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
) &&
688 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
| BWRITERSP_WRITEMASK_2
) &&
689 writemask
!= (BWRITERSP_WRITEMASK_ALL
)) {
690 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
693 TRACE("o%u is oT%u\n", regnum
, usage_idx
);
694 This
->oT_regnum
[usage_idx
] = regnum
;
697 case BWRITERDECLUSAGE_PSIZE
:
699 WARN("dcl_psize%u not supported in sm 1/2 shaders\n", usage_idx
);
702 TRACE("o%u writemask 0x%08x is oPts\n", regnum
, writemask
);
703 This
->oPts_regnum
= regnum
;
704 This
->oPts_mask
= writemask
;
707 case BWRITERDECLUSAGE_FOG
:
709 WARN("dcl_fog%u not supported in sm 1 shaders\n", usage_idx
);
712 if(writemask
!= BWRITERSP_WRITEMASK_0
&& writemask
!= BWRITERSP_WRITEMASK_1
&&
713 writemask
!= BWRITERSP_WRITEMASK_2
&& writemask
!= BWRITERSP_WRITEMASK_3
) {
714 WARN("Unsupported fog writemask\n");
717 TRACE("o%u writemask 0x%08x is oFog\n", regnum
, writemask
);
718 This
->oFog_regnum
= regnum
;
719 This
->oFog_mask
= writemask
;
723 WARN("Varying type %u is not supported in shader model 1.x\n", usage
);
731 static void vs_1_x_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
734 if(shader
->num_ci
|| shader
->num_cb
) {
735 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
736 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
737 This
->state
= E_INVALIDARG
;
741 hr
= vs_find_builtin_varyings(This
, shader
);
747 /* Declare the shader type and version */
748 put_dword(buffer
, This
->version
);
750 write_declarations(This
, buffer
, FALSE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
751 write_constF(shader
, buffer
, FALSE
);
755 static HRESULT
find_ps_builtin_semantics(struct bc_writer
*This
,
756 const struct bwriter_shader
*shader
,
759 DWORD usage
, usage_idx
, writemask
, regnum
;
761 This
->v_regnum
[0] = -1; This
->v_regnum
[1] = -1;
762 for(i
= 0; i
< 8; i
++) This
->t_regnum
[i
] = -1;
764 for(i
= 0; i
< shader
->num_inputs
; i
++) {
765 if(!shader
->inputs
[i
].builtin
) continue;
767 usage
= shader
->inputs
[i
].usage
;
768 usage_idx
= shader
->inputs
[i
].usage_idx
;
769 writemask
= shader
->inputs
[i
].writemask
;
770 regnum
= shader
->inputs
[i
].regnum
;
773 case BWRITERDECLUSAGE_COLOR
:
775 WARN("dcl_color%u not supported in sm 1 shaders\n", usage_idx
);
778 if(writemask
!= BWRITERSP_WRITEMASK_ALL
) {
779 WARN("Only WRITEMASK_ALL is supported on color in sm 1\n");
782 TRACE("v%u is v%u\n", regnum
, usage_idx
);
783 This
->v_regnum
[usage_idx
] = regnum
;
786 case BWRITERDECLUSAGE_TEXCOORD
:
787 if(usage_idx
> texcoords
) {
788 WARN("dcl_texcoord%u not supported in this shader version\n", usage_idx
);
791 if(writemask
!= (BWRITERSP_WRITEMASK_0
) &&
792 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
) &&
793 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
| BWRITERSP_WRITEMASK_2
) &&
794 writemask
!= (BWRITERSP_WRITEMASK_ALL
)) {
795 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
797 writemask
= BWRITERSP_WRITEMASK_ALL
;
799 TRACE("v%u is t%u\n", regnum
, usage_idx
);
800 This
->t_regnum
[usage_idx
] = regnum
;
804 WARN("Varying type %u is not supported in shader model 1.x\n", usage
);
812 static void ps_1_x_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
815 /* First check the constants and varyings, and complain if unsupported things are used */
816 if(shader
->num_ci
|| shader
->num_cb
) {
817 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
818 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
819 This
->state
= E_INVALIDARG
;
823 hr
= find_ps_builtin_semantics(This
, shader
, 4);
829 /* Declare the shader type and version */
830 put_dword(buffer
, This
->version
);
831 write_constF(shader
, buffer
, FALSE
);
834 static void ps_1_4_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
837 /* First check the constants and varyings, and complain if unsupported things are used */
838 if(shader
->num_ci
|| shader
->num_cb
) {
839 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
840 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
841 This
->state
= E_INVALIDARG
;
844 hr
= find_ps_builtin_semantics(This
, shader
, 6);
850 /* Declare the shader type and version */
851 put_dword(buffer
, This
->version
);
852 write_constF(shader
, buffer
, FALSE
);
855 static void end(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
856 put_dword(buffer
, D3DSIO_END
);
859 static DWORD
map_vs_output(struct bc_writer
*This
, DWORD regnum
, DWORD mask
, DWORD
*has_components
) {
863 *has_components
= TRUE
;
864 if(regnum
== This
->oPos_regnum
) {
865 token
|= (D3DSPR_RASTOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
866 token
|= D3DSRO_POSITION
& D3DSP_REGNUM_MASK
; /* No shift */
869 if(regnum
== This
->oFog_regnum
&& mask
== This
->oFog_mask
) {
870 token
|= (D3DSPR_RASTOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
871 token
|= D3DSRO_FOG
& D3DSP_REGNUM_MASK
; /* No shift */
872 token
|= D3DSP_WRITEMASK_ALL
;
873 *has_components
= FALSE
;
876 if(regnum
== This
->oPts_regnum
&& mask
== This
->oPts_mask
) {
877 token
|= (D3DSPR_RASTOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
878 token
|= D3DSRO_POINT_SIZE
& D3DSP_REGNUM_MASK
; /* No shift */
879 token
|= D3DSP_WRITEMASK_ALL
;
880 *has_components
= FALSE
;
883 for(i
= 0; i
< 2; i
++) {
884 if(regnum
== This
->oD_regnum
[i
]) {
885 token
|= (D3DSPR_ATTROUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
886 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
890 for(i
= 0; i
< 8; i
++) {
891 if(regnum
== This
->oT_regnum
[i
]) {
892 token
|= (D3DSPR_TEXCRDOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
893 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
898 /* The varying must be undeclared - if an unsupported varying was declared,
899 * the vs_find_builtin_varyings function would have caught it and this code
901 WARN("Undeclared varying %u\n", regnum
);
902 This
->state
= E_INVALIDARG
;
906 static void vs_12_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
907 struct bytecode_buffer
*buffer
,
908 DWORD shift
, DWORD mod
) {
909 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
913 WARN("Relative addressing not supported for destination registers\n");
914 This
->state
= E_INVALIDARG
;
919 case BWRITERSPR_OUTPUT
:
920 token
|= map_vs_output(This
, reg
->regnum
, reg
->u
.writemask
, &has_wmask
);
923 case BWRITERSPR_RASTOUT
:
924 case BWRITERSPR_ATTROUT
:
925 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
926 * but are unexpected. If we hit this path it might be due to an error.
928 FIXME("Unexpected register type %u\n", reg
->type
);
930 case BWRITERSPR_INPUT
:
931 case BWRITERSPR_TEMP
:
932 case BWRITERSPR_CONST
:
933 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
934 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
938 case BWRITERSPR_ADDR
:
939 if(reg
->regnum
!= 0) {
940 WARN("Only a0 exists\n");
941 This
->state
= E_INVALIDARG
;
944 token
|= (D3DSPR_ADDR
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
945 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
949 case BWRITERSPR_PREDICATE
:
950 if(This
->version
!= BWRITERVS_VERSION(2, 1)){
951 WARN("Predicate register is allowed only in vs_2_x\n");
952 This
->state
= E_INVALIDARG
;
955 if(reg
->regnum
!= 0) {
956 WARN("Only predicate register p0 exists\n");
957 This
->state
= E_INVALIDARG
;
960 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
961 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
962 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
967 WARN("Invalid register type for 1.x-2.x vertex shader\n");
968 This
->state
= E_INVALIDARG
;
972 /* strictly speaking there are no modifiers in vs_2_0 and vs_1_x, but they can be written
973 * into the bytecode and since the compiler doesn't do such checks write them
974 * (the checks are done by the undocumented shader validator)
976 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
977 token
|= d3d9_dstmod(mod
);
980 token
|= d3d9_writemask(reg
->u
.writemask
);
982 put_dword(buffer
, token
);
985 static void vs_1_x_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
986 struct bytecode_buffer
*buffer
) {
987 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
992 case BWRITERSPR_OUTPUT
:
993 /* Map the swizzle to a writemask, the format expected
996 switch(reg
->u
.swizzle
) {
997 case BWRITERVS_SWIZZLE_X
:
998 component
= BWRITERSP_WRITEMASK_0
;
1000 case BWRITERVS_SWIZZLE_Y
:
1001 component
= BWRITERSP_WRITEMASK_1
;
1003 case BWRITERVS_SWIZZLE_Z
:
1004 component
= BWRITERSP_WRITEMASK_2
;
1006 case BWRITERVS_SWIZZLE_W
:
1007 component
= BWRITERSP_WRITEMASK_3
;
1012 token
|= map_vs_output(This
, reg
->regnum
, component
, &has_swizzle
);
1015 case BWRITERSPR_RASTOUT
:
1016 case BWRITERSPR_ATTROUT
:
1017 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1018 * but are unexpected. If we hit this path it might be due to an error.
1020 FIXME("Unexpected register type %u\n", reg
->type
);
1022 case BWRITERSPR_INPUT
:
1023 case BWRITERSPR_TEMP
:
1024 case BWRITERSPR_CONST
:
1025 case BWRITERSPR_ADDR
:
1026 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1027 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1029 if(reg
->rel_reg
->type
!= BWRITERSPR_ADDR
||
1030 reg
->rel_reg
->regnum
!= 0 ||
1031 reg
->rel_reg
->u
.swizzle
!= BWRITERVS_SWIZZLE_X
) {
1032 WARN("Relative addressing in vs_1_x is only allowed with a0.x\n");
1033 This
->state
= E_INVALIDARG
;
1036 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1041 WARN("Invalid register type for 1.x vshader\n");
1042 This
->state
= E_INVALIDARG
;
1046 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1048 token
|= d3d9_srcmod(reg
->srcmod
);
1049 put_dword(buffer
, token
);
1052 static void write_srcregs(struct bc_writer
*This
, const struct instruction
*instr
,
1053 struct bytecode_buffer
*buffer
){
1055 if(instr
->has_predicate
){
1056 This
->funcs
->srcreg(This
, &instr
->predicate
, buffer
);
1058 for(i
= 0; i
< instr
->num_srcs
; i
++){
1059 This
->funcs
->srcreg(This
, &instr
->src
[i
], buffer
);
1063 static DWORD
map_ps13_temp(struct bc_writer
*This
, const struct shader_reg
*reg
) {
1065 if(reg
->regnum
== T0_REG
) {
1066 token
|= (D3DSPR_TEXTURE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1067 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
1068 } else if(reg
->regnum
== T1_REG
) {
1069 token
|= (D3DSPR_TEXTURE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1070 token
|= 1 & D3DSP_REGNUM_MASK
; /* No shift */
1071 } else if(reg
->regnum
== T2_REG
) {
1072 token
|= (D3DSPR_TEXTURE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1073 token
|= 2 & D3DSP_REGNUM_MASK
; /* No shift */
1074 } else if(reg
->regnum
== T3_REG
) {
1075 token
|= (D3DSPR_TEXTURE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1076 token
|= 3 & D3DSP_REGNUM_MASK
; /* No shift */
1078 token
|= (D3DSPR_TEMP
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1079 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1084 static DWORD
map_ps_input(struct bc_writer
*This
,
1085 const struct shader_reg
*reg
) {
1087 /* Map color interpolators */
1088 for(i
= 0; i
< 2; i
++) {
1089 if(reg
->regnum
== This
->v_regnum
[i
]) {
1090 token
|= (D3DSPR_INPUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1091 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
1095 for(i
= 0; i
< 8; i
++) {
1096 if(reg
->regnum
== This
->t_regnum
[i
]) {
1097 token
|= (D3DSPR_TEXTURE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1098 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
1103 WARN("Invalid ps 1/2 varying\n");
1104 This
->state
= E_INVALIDARG
;
1108 static void ps_1_0123_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1109 struct bytecode_buffer
*buffer
) {
1110 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1112 WARN("Relative addressing not supported in <= ps_3_0\n");
1113 This
->state
= E_INVALIDARG
;
1118 case BWRITERSPR_INPUT
:
1119 token
|= map_ps_input(This
, reg
);
1122 /* Take care about the texture temporaries. There's a problem: They aren't
1123 * declared anywhere, so we can only hardcode the values that are used
1124 * to map ps_1_3 shaders to the common shader structure
1126 case BWRITERSPR_TEMP
:
1127 token
|= map_ps13_temp(This
, reg
);
1130 case BWRITERSPR_CONST
: /* Can be mapped 1:1 */
1131 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1132 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1136 WARN("Invalid register type for <= ps_1_3 shader\n");
1137 This
->state
= E_INVALIDARG
;
1141 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1143 if(reg
->srcmod
== BWRITERSPSM_DZ
|| reg
->srcmod
== BWRITERSPSM_DW
||
1144 reg
->srcmod
== BWRITERSPSM_ABS
|| reg
->srcmod
== BWRITERSPSM_ABSNEG
||
1145 reg
->srcmod
== BWRITERSPSM_NOT
) {
1146 WARN("Invalid source modifier %u for <= ps_1_3\n", reg
->srcmod
);
1147 This
->state
= E_INVALIDARG
;
1150 token
|= d3d9_srcmod(reg
->srcmod
);
1151 put_dword(buffer
, token
);
1154 static void ps_1_0123_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1155 struct bytecode_buffer
*buffer
,
1156 DWORD shift
, DWORD mod
) {
1157 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1160 WARN("Relative addressing not supported for destination registers\n");
1161 This
->state
= E_INVALIDARG
;
1166 case BWRITERSPR_TEMP
:
1167 token
|= map_ps13_temp(This
, reg
);
1170 /* texkill uses the input register as a destination parameter */
1171 case BWRITERSPR_INPUT
:
1172 token
|= map_ps_input(This
, reg
);
1176 WARN("Invalid dest register type for 1.x pshader\n");
1177 This
->state
= E_INVALIDARG
;
1181 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1182 token
|= d3d9_dstmod(mod
);
1184 token
|= d3d9_writemask(reg
->u
.writemask
);
1185 put_dword(buffer
, token
);
1188 /* The length of an instruction consists of the destination register (if any),
1189 * the number of source registers, the number of address registers used for
1190 * indirect addressing, and optionally the predicate register
1192 static DWORD
instrlen(const struct instruction
*instr
, unsigned int srcs
, unsigned int dsts
) {
1194 DWORD ret
= srcs
+ dsts
+ (instr
->has_predicate
? 1 : 0);
1197 if(instr
->dst
.rel_reg
) ret
++;
1199 for(i
= 0; i
< srcs
; i
++) {
1200 if(instr
->src
[i
].rel_reg
) ret
++;
1205 static void sm_1_x_opcode(struct bc_writer
*This
,
1206 const struct instruction
*instr
,
1207 DWORD token
, struct bytecode_buffer
*buffer
) {
1208 /* In sm_1_x instruction length isn't encoded */
1210 token
|= D3DSI_COISSUE
;
1212 put_dword(buffer
, token
);
1215 static void instr_handler(struct bc_writer
*This
,
1216 const struct instruction
*instr
,
1217 struct bytecode_buffer
*buffer
) {
1218 DWORD token
= d3d9_opcode(instr
->opcode
);
1220 This
->funcs
->opcode(This
, instr
, token
, buffer
);
1221 if(instr
->has_dst
) This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1222 write_srcregs(This
, instr
, buffer
);
1225 static const struct instr_handler_table vs_1_x_handlers
[] = {
1226 {BWRITERSIO_ADD
, instr_handler
},
1227 {BWRITERSIO_NOP
, instr_handler
},
1228 {BWRITERSIO_MOV
, instr_handler
},
1229 {BWRITERSIO_SUB
, instr_handler
},
1230 {BWRITERSIO_MAD
, instr_handler
},
1231 {BWRITERSIO_MUL
, instr_handler
},
1232 {BWRITERSIO_RCP
, instr_handler
},
1233 {BWRITERSIO_RSQ
, instr_handler
},
1234 {BWRITERSIO_DP3
, instr_handler
},
1235 {BWRITERSIO_DP4
, instr_handler
},
1236 {BWRITERSIO_MIN
, instr_handler
},
1237 {BWRITERSIO_MAX
, instr_handler
},
1238 {BWRITERSIO_SLT
, instr_handler
},
1239 {BWRITERSIO_SGE
, instr_handler
},
1240 {BWRITERSIO_EXP
, instr_handler
},
1241 {BWRITERSIO_LOG
, instr_handler
},
1242 {BWRITERSIO_EXPP
, instr_handler
},
1243 {BWRITERSIO_LOGP
, instr_handler
},
1244 {BWRITERSIO_DST
, instr_handler
},
1245 {BWRITERSIO_FRC
, instr_handler
},
1246 {BWRITERSIO_M4x4
, instr_handler
},
1247 {BWRITERSIO_M4x3
, instr_handler
},
1248 {BWRITERSIO_M3x4
, instr_handler
},
1249 {BWRITERSIO_M3x3
, instr_handler
},
1250 {BWRITERSIO_M3x2
, instr_handler
},
1251 {BWRITERSIO_LIT
, instr_handler
},
1253 {BWRITERSIO_END
, NULL
}, /* Sentinel value, it signals
1254 the end of the list */
1257 static const struct bytecode_backend vs_1_x_backend
= {
1266 static void instr_ps_1_0123_texld(struct bc_writer
*This
,
1267 const struct instruction
*instr
,
1268 struct bytecode_buffer
*buffer
) {
1270 struct shader_reg reg
;
1273 if(instr
->src
[1].type
!= BWRITERSPR_SAMPLER
||
1274 instr
->src
[1].regnum
> 3) {
1275 WARN("Unsupported sampler type %u regnum %u\n",
1276 instr
->src
[1].type
, instr
->src
[1].regnum
);
1277 This
->state
= E_INVALIDARG
;
1279 } else if(instr
->dst
.type
!= BWRITERSPR_TEMP
) {
1280 WARN("Can only sample into a temp register\n");
1281 This
->state
= E_INVALIDARG
;
1285 idx
= instr
->src
[1].regnum
;
1286 if((idx
== 0 && instr
->dst
.regnum
!= T0_REG
) ||
1287 (idx
== 1 && instr
->dst
.regnum
!= T1_REG
) ||
1288 (idx
== 2 && instr
->dst
.regnum
!= T2_REG
) ||
1289 (idx
== 3 && instr
->dst
.regnum
!= T3_REG
)) {
1290 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_x\n",
1291 idx
, instr
->dst
.regnum
);
1292 This
->state
= E_INVALIDARG
;
1295 if(instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1296 /* A simple non-dependent read tex instruction */
1297 if(instr
->src
[0].regnum
!= This
->t_regnum
[idx
]) {
1298 WARN("Cannot sample from s%u with texture address data from interpolator %u\n",
1299 idx
, instr
->src
[0].regnum
);
1300 This
->state
= E_INVALIDARG
;
1303 This
->funcs
->opcode(This
, instr
, D3DSIO_TEX
& D3DSI_OPCODE_MASK
, buffer
);
1305 /* map the temp dstreg to the ps_1_3 texture temporary register */
1306 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1307 } else if(instr
->src
[0].type
== BWRITERSPR_TEMP
) {
1309 swizzlemask
= (3 << BWRITERVS_SWIZZLE_SHIFT
) |
1310 (3 << (BWRITERVS_SWIZZLE_SHIFT
+ 2)) |
1311 (3 << (BWRITERVS_SWIZZLE_SHIFT
+ 4));
1312 if((instr
->src
[0].u
.swizzle
& swizzlemask
) == (BWRITERVS_X_X
| BWRITERVS_Y_Y
| BWRITERVS_Z_Z
)) {
1313 TRACE("writing texreg2rgb\n");
1314 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2RGB
& D3DSI_OPCODE_MASK
, buffer
);
1315 } else if(instr
->src
[0].u
.swizzle
== (BWRITERVS_X_W
| BWRITERVS_Y_X
| BWRITERVS_Z_X
| BWRITERVS_W_X
)) {
1316 TRACE("writing texreg2ar\n");
1317 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2AR
& D3DSI_OPCODE_MASK
, buffer
);
1318 } else if(instr
->src
[0].u
.swizzle
== (BWRITERVS_X_Y
| BWRITERVS_Y_Z
| BWRITERVS_Z_Z
| BWRITERVS_W_Z
)) {
1319 TRACE("writing texreg2gb\n");
1320 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2GB
& D3DSI_OPCODE_MASK
, buffer
);
1322 WARN("Unsupported src addr swizzle in dependent texld: 0x%08x\n", instr
->src
[0].u
.swizzle
);
1323 This
->state
= E_INVALIDARG
;
1327 /* Dst and src reg can be mapped normally. Both registers are temporary registers in the
1328 * source shader and have to be mapped to the temporary form of the texture registers. However,
1329 * the src reg doesn't have a swizzle
1331 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1332 reg
= instr
->src
[0];
1333 reg
.u
.swizzle
= BWRITERVS_NOSWIZZLE
;
1334 This
->funcs
->srcreg(This
, ®
, buffer
);
1336 WARN("Invalid address data source register\n");
1337 This
->state
= E_INVALIDARG
;
1342 static void instr_ps_1_0123_mov(struct bc_writer
*This
,
1343 const struct instruction
*instr
,
1344 struct bytecode_buffer
*buffer
) {
1345 DWORD token
= D3DSIO_MOV
& D3DSI_OPCODE_MASK
;
1347 if(instr
->dst
.type
== BWRITERSPR_TEMP
&& instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1348 if((instr
->dst
.regnum
== T0_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[0]) ||
1349 (instr
->dst
.regnum
== T1_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[1]) ||
1350 (instr
->dst
.regnum
== T2_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[2]) ||
1351 (instr
->dst
.regnum
== T3_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[3])) {
1352 if(instr
->dstmod
& BWRITERSPDM_SATURATE
) {
1353 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXCOORD
& D3DSI_OPCODE_MASK
, buffer
);
1354 /* Remove the SATURATE flag, it's implicit to the instruction */
1355 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
& (~BWRITERSPDM_SATURATE
));
1358 WARN("A varying -> temp copy is only supported with the SATURATE modifier in <=ps_1_3\n");
1359 This
->state
= E_INVALIDARG
;
1362 } else if(instr
->src
[0].regnum
== This
->v_regnum
[0] ||
1363 instr
->src
[0].regnum
== This
->v_regnum
[1]) {
1364 /* Handled by the normal mov below. Just drop out of the if condition */
1366 WARN("Unsupported varying -> temp mov in <= ps_1_3\n");
1367 This
->state
= E_INVALIDARG
;
1372 This
->funcs
->opcode(This
, instr
, token
, buffer
);
1373 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1374 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1377 static const struct instr_handler_table ps_1_0123_handlers
[] = {
1378 {BWRITERSIO_ADD
, instr_handler
},
1379 {BWRITERSIO_NOP
, instr_handler
},
1380 {BWRITERSIO_MOV
, instr_ps_1_0123_mov
},
1381 {BWRITERSIO_SUB
, instr_handler
},
1382 {BWRITERSIO_MAD
, instr_handler
},
1383 {BWRITERSIO_MUL
, instr_handler
},
1384 {BWRITERSIO_DP3
, instr_handler
},
1385 {BWRITERSIO_DP4
, instr_handler
},
1386 {BWRITERSIO_LRP
, instr_handler
},
1388 /* pshader instructions */
1389 {BWRITERSIO_CND
, instr_handler
},
1390 {BWRITERSIO_CMP
, instr_handler
},
1391 {BWRITERSIO_TEXKILL
, instr_handler
},
1392 {BWRITERSIO_TEX
, instr_ps_1_0123_texld
},
1393 {BWRITERSIO_TEXBEM
, instr_handler
},
1394 {BWRITERSIO_TEXBEML
, instr_handler
},
1395 {BWRITERSIO_TEXM3x2PAD
, instr_handler
},
1396 {BWRITERSIO_TEXM3x3PAD
, instr_handler
},
1397 {BWRITERSIO_TEXM3x3SPEC
, instr_handler
},
1398 {BWRITERSIO_TEXM3x3VSPEC
, instr_handler
},
1399 {BWRITERSIO_TEXM3x3TEX
, instr_handler
},
1400 {BWRITERSIO_TEXM3x3
, instr_handler
},
1401 {BWRITERSIO_TEXM3x2DEPTH
, instr_handler
},
1402 {BWRITERSIO_TEXM3x2TEX
, instr_handler
},
1403 {BWRITERSIO_TEXDP3
, instr_handler
},
1404 {BWRITERSIO_TEXDP3TEX
, instr_handler
},
1405 {BWRITERSIO_END
, NULL
},
1408 static const struct bytecode_backend ps_1_0123_backend
= {
1417 static void ps_1_4_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1418 struct bytecode_buffer
*buffer
) {
1419 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1421 WARN("Relative addressing not supported in <= ps_3_0\n");
1422 This
->state
= E_INVALIDARG
;
1427 case BWRITERSPR_INPUT
:
1428 token
|= map_ps_input(This
, reg
);
1431 /* Can be mapped 1:1 */
1432 case BWRITERSPR_TEMP
:
1433 case BWRITERSPR_CONST
:
1434 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1435 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1439 WARN("Invalid register type for ps_1_4 shader\n");
1440 This
->state
= E_INVALIDARG
;
1444 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1446 if(reg
->srcmod
== BWRITERSPSM_ABS
|| reg
->srcmod
== BWRITERSPSM_ABSNEG
||
1447 reg
->srcmod
== BWRITERSPSM_NOT
) {
1448 WARN("Invalid source modifier %u for ps_1_4\n", reg
->srcmod
);
1449 This
->state
= E_INVALIDARG
;
1452 token
|= d3d9_srcmod(reg
->srcmod
);
1453 put_dword(buffer
, token
);
1456 static void ps_1_4_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1457 struct bytecode_buffer
*buffer
,
1458 DWORD shift
, DWORD mod
) {
1459 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1462 WARN("Relative addressing not supported for destination registers\n");
1463 This
->state
= E_INVALIDARG
;
1468 case BWRITERSPR_TEMP
: /* 1:1 mapping */
1469 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1470 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1474 case BWRITERSPR_INPUT
:
1475 token
|= map_ps_input(This
, reg
);
1479 WARN("Invalid dest register type for 1.x pshader\n");
1480 This
->state
= E_INVALIDARG
;
1484 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1485 token
|= d3d9_dstmod(mod
);
1487 token
|= d3d9_writemask(reg
->u
.writemask
);
1488 put_dword(buffer
, token
);
1491 static void instr_ps_1_4_mov(struct bc_writer
*This
,
1492 const struct instruction
*instr
,
1493 struct bytecode_buffer
*buffer
) {
1494 DWORD token
= D3DSIO_MOV
& D3DSI_OPCODE_MASK
;
1496 if(instr
->dst
.type
== BWRITERSPR_TEMP
&& instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1497 if(instr
->src
[0].regnum
== This
->t_regnum
[0] ||
1498 instr
->src
[0].regnum
== This
->t_regnum
[1] ||
1499 instr
->src
[0].regnum
== This
->t_regnum
[2] ||
1500 instr
->src
[0].regnum
== This
->t_regnum
[3] ||
1501 instr
->src
[0].regnum
== This
->t_regnum
[4] ||
1502 instr
->src
[0].regnum
== This
->t_regnum
[5]) {
1503 /* Similar to a regular mov, but a different opcode */
1504 token
= D3DSIO_TEXCOORD
& D3DSI_OPCODE_MASK
;
1505 } else if(instr
->src
[0].regnum
== This
->v_regnum
[0] ||
1506 instr
->src
[0].regnum
== This
->v_regnum
[1]) {
1507 /* Handled by the normal mov below. Just drop out of the if condition */
1509 WARN("Unsupported varying -> temp mov in ps_1_4\n");
1510 This
->state
= E_INVALIDARG
;
1515 This
->funcs
->opcode(This
, instr
, token
, buffer
);
1516 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1517 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1520 static void instr_ps_1_4_texld(struct bc_writer
*This
,
1521 const struct instruction
*instr
,
1522 struct bytecode_buffer
*buffer
) {
1523 if(instr
->src
[1].type
!= BWRITERSPR_SAMPLER
||
1524 instr
->src
[1].regnum
> 5) {
1525 WARN("Unsupported sampler type %u regnum %u\n",
1526 instr
->src
[1].type
, instr
->src
[1].regnum
);
1527 This
->state
= E_INVALIDARG
;
1529 } else if(instr
->dst
.type
!= BWRITERSPR_TEMP
) {
1530 WARN("Can only sample into a temp register\n");
1531 This
->state
= E_INVALIDARG
;
1535 if(instr
->src
[1].regnum
!= instr
->dst
.regnum
) {
1536 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_4\n",
1537 instr
->src
[1].regnum
, instr
->dst
.regnum
);
1538 This
->state
= E_INVALIDARG
;
1542 This
->funcs
->opcode(This
, instr
, D3DSIO_TEX
& D3DSI_OPCODE_MASK
, buffer
);
1543 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1544 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1547 static const struct instr_handler_table ps_1_4_handlers
[] = {
1548 {BWRITERSIO_ADD
, instr_handler
},
1549 {BWRITERSIO_NOP
, instr_handler
},
1550 {BWRITERSIO_MOV
, instr_ps_1_4_mov
},
1551 {BWRITERSIO_SUB
, instr_handler
},
1552 {BWRITERSIO_MAD
, instr_handler
},
1553 {BWRITERSIO_MUL
, instr_handler
},
1554 {BWRITERSIO_DP3
, instr_handler
},
1555 {BWRITERSIO_DP4
, instr_handler
},
1556 {BWRITERSIO_LRP
, instr_handler
},
1558 /* pshader instructions */
1559 {BWRITERSIO_CND
, instr_handler
},
1560 {BWRITERSIO_CMP
, instr_handler
},
1561 {BWRITERSIO_TEXKILL
, instr_handler
},
1562 {BWRITERSIO_TEX
, instr_ps_1_4_texld
},
1563 {BWRITERSIO_TEXDEPTH
, instr_handler
},
1564 {BWRITERSIO_BEM
, instr_handler
},
1566 {BWRITERSIO_PHASE
, instr_handler
},
1567 {BWRITERSIO_END
, NULL
},
1570 static const struct bytecode_backend ps_1_4_backend
= {
1579 static void write_constB(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
1580 write_const(shader
->constB
, shader
->num_cb
, D3DSIO_DEFB
, D3DSPR_CONSTBOOL
, buffer
, len
);
1583 static void write_constI(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
1584 write_const(shader
->constI
, shader
->num_ci
, D3DSIO_DEFI
, D3DSPR_CONSTINT
, buffer
, len
);
1587 static void vs_2_header(struct bc_writer
*This
,
1588 const struct bwriter_shader
*shader
,
1589 struct bytecode_buffer
*buffer
) {
1592 hr
= vs_find_builtin_varyings(This
, shader
);
1598 /* Declare the shader type and version */
1599 put_dword(buffer
, This
->version
);
1601 write_declarations(This
, buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
1602 write_constF(shader
, buffer
, TRUE
);
1603 write_constB(shader
, buffer
, TRUE
);
1604 write_constI(shader
, buffer
, TRUE
);
1608 static void vs_2_srcreg(struct bc_writer
*This
,
1609 const struct shader_reg
*reg
,
1610 struct bytecode_buffer
*buffer
) {
1611 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1617 case BWRITERSPR_OUTPUT
:
1618 /* Map the swizzle to a writemask, the format expected
1621 switch(reg
->u
.swizzle
) {
1622 case BWRITERVS_SWIZZLE_X
:
1623 component
= BWRITERSP_WRITEMASK_0
;
1625 case BWRITERVS_SWIZZLE_Y
:
1626 component
= BWRITERSP_WRITEMASK_1
;
1628 case BWRITERVS_SWIZZLE_Z
:
1629 component
= BWRITERSP_WRITEMASK_2
;
1631 case BWRITERVS_SWIZZLE_W
:
1632 component
= BWRITERSP_WRITEMASK_3
;
1637 token
|= map_vs_output(This
, reg
->regnum
, component
, &has_swizzle
);
1640 case BWRITERSPR_RASTOUT
:
1641 case BWRITERSPR_ATTROUT
:
1642 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1643 * but are unexpected. If we hit this path it might be due to an error.
1645 FIXME("Unexpected register type %u\n", reg
->type
);
1647 case BWRITERSPR_INPUT
:
1648 case BWRITERSPR_TEMP
:
1649 case BWRITERSPR_CONST
:
1650 case BWRITERSPR_ADDR
:
1651 case BWRITERSPR_CONSTINT
:
1652 case BWRITERSPR_CONSTBOOL
:
1653 case BWRITERSPR_LABEL
:
1654 d3d9reg
= d3d9_register(reg
->type
);
1655 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1656 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1657 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1660 case BWRITERSPR_LOOP
:
1661 if(reg
->regnum
!= 0) {
1662 WARN("Only regnum 0 is supported for the loop index register in vs_2_0\n");
1663 This
->state
= E_INVALIDARG
;
1666 token
|= (D3DSPR_LOOP
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1667 token
|= (D3DSPR_LOOP
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1668 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
1671 case BWRITERSPR_PREDICATE
:
1672 if(This
->version
!= BWRITERVS_VERSION(2, 1)){
1673 WARN("Predicate register is allowed only in vs_2_x\n");
1674 This
->state
= E_INVALIDARG
;
1677 if(reg
->regnum
> 0) {
1678 WARN("Only predicate register 0 is supported\n");
1679 This
->state
= E_INVALIDARG
;
1682 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1683 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1684 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
1689 WARN("Invalid register type for 2.0 vshader\n");
1690 This
->state
= E_INVALIDARG
;
1694 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1696 token
|= d3d9_srcmod(reg
->srcmod
);
1699 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1701 put_dword(buffer
, token
);
1703 /* vs_2_0 and newer write the register containing the index explicitly in the
1706 if(token
& D3DVS_ADDRMODE_RELATIVE
)
1707 vs_2_srcreg(This
, reg
->rel_reg
, buffer
);
1710 static void sm_2_opcode(struct bc_writer
*This
,
1711 const struct instruction
*instr
,
1712 DWORD token
, struct bytecode_buffer
*buffer
) {
1713 /* From sm 2 onwards instruction length is encoded in the opcode field */
1714 int dsts
= instr
->has_dst
? 1 : 0;
1715 token
|= instrlen(instr
, instr
->num_srcs
, dsts
) << D3DSI_INSTLENGTH_SHIFT
;
1717 token
|= (d3d9_comparetype(instr
->comptype
) << 16) & (0xf << 16);
1718 if(instr
->has_predicate
)
1719 token
|= D3DSHADER_INSTRUCTION_PREDICATED
;
1720 put_dword(buffer
,token
);
1723 static const struct instr_handler_table vs_2_0_handlers
[] = {
1724 {BWRITERSIO_ADD
, instr_handler
},
1725 {BWRITERSIO_NOP
, instr_handler
},
1726 {BWRITERSIO_MOV
, instr_handler
},
1727 {BWRITERSIO_SUB
, instr_handler
},
1728 {BWRITERSIO_MAD
, instr_handler
},
1729 {BWRITERSIO_MUL
, instr_handler
},
1730 {BWRITERSIO_RCP
, instr_handler
},
1731 {BWRITERSIO_RSQ
, instr_handler
},
1732 {BWRITERSIO_DP3
, instr_handler
},
1733 {BWRITERSIO_DP4
, instr_handler
},
1734 {BWRITERSIO_MIN
, instr_handler
},
1735 {BWRITERSIO_MAX
, instr_handler
},
1736 {BWRITERSIO_SLT
, instr_handler
},
1737 {BWRITERSIO_SGE
, instr_handler
},
1738 {BWRITERSIO_ABS
, instr_handler
},
1739 {BWRITERSIO_EXP
, instr_handler
},
1740 {BWRITERSIO_LOG
, instr_handler
},
1741 {BWRITERSIO_EXPP
, instr_handler
},
1742 {BWRITERSIO_LOGP
, instr_handler
},
1743 {BWRITERSIO_DST
, instr_handler
},
1744 {BWRITERSIO_LRP
, instr_handler
},
1745 {BWRITERSIO_FRC
, instr_handler
},
1746 {BWRITERSIO_CRS
, instr_handler
},
1747 {BWRITERSIO_SGN
, instr_handler
},
1748 {BWRITERSIO_NRM
, instr_handler
},
1749 {BWRITERSIO_SINCOS
, instr_handler
},
1750 {BWRITERSIO_M4x4
, instr_handler
},
1751 {BWRITERSIO_M4x3
, instr_handler
},
1752 {BWRITERSIO_M3x4
, instr_handler
},
1753 {BWRITERSIO_M3x3
, instr_handler
},
1754 {BWRITERSIO_M3x2
, instr_handler
},
1755 {BWRITERSIO_LIT
, instr_handler
},
1756 {BWRITERSIO_POW
, instr_handler
},
1757 {BWRITERSIO_MOVA
, instr_handler
},
1759 {BWRITERSIO_CALL
, instr_handler
},
1760 {BWRITERSIO_CALLNZ
, instr_handler
},
1761 {BWRITERSIO_REP
, instr_handler
},
1762 {BWRITERSIO_ENDREP
, instr_handler
},
1763 {BWRITERSIO_IF
, instr_handler
},
1764 {BWRITERSIO_LABEL
, instr_handler
},
1765 {BWRITERSIO_ELSE
, instr_handler
},
1766 {BWRITERSIO_ENDIF
, instr_handler
},
1767 {BWRITERSIO_LOOP
, instr_handler
},
1768 {BWRITERSIO_RET
, instr_handler
},
1769 {BWRITERSIO_ENDLOOP
, instr_handler
},
1771 {BWRITERSIO_END
, NULL
},
1774 static const struct bytecode_backend vs_2_0_backend
= {
1783 static const struct instr_handler_table vs_2_x_handlers
[] = {
1784 {BWRITERSIO_ADD
, instr_handler
},
1785 {BWRITERSIO_NOP
, instr_handler
},
1786 {BWRITERSIO_MOV
, instr_handler
},
1787 {BWRITERSIO_SUB
, instr_handler
},
1788 {BWRITERSIO_MAD
, instr_handler
},
1789 {BWRITERSIO_MUL
, instr_handler
},
1790 {BWRITERSIO_RCP
, instr_handler
},
1791 {BWRITERSIO_RSQ
, instr_handler
},
1792 {BWRITERSIO_DP3
, instr_handler
},
1793 {BWRITERSIO_DP4
, instr_handler
},
1794 {BWRITERSIO_MIN
, instr_handler
},
1795 {BWRITERSIO_MAX
, instr_handler
},
1796 {BWRITERSIO_SLT
, instr_handler
},
1797 {BWRITERSIO_SGE
, instr_handler
},
1798 {BWRITERSIO_ABS
, instr_handler
},
1799 {BWRITERSIO_EXP
, instr_handler
},
1800 {BWRITERSIO_LOG
, instr_handler
},
1801 {BWRITERSIO_EXPP
, instr_handler
},
1802 {BWRITERSIO_LOGP
, instr_handler
},
1803 {BWRITERSIO_DST
, instr_handler
},
1804 {BWRITERSIO_LRP
, instr_handler
},
1805 {BWRITERSIO_FRC
, instr_handler
},
1806 {BWRITERSIO_CRS
, instr_handler
},
1807 {BWRITERSIO_SGN
, instr_handler
},
1808 {BWRITERSIO_NRM
, instr_handler
},
1809 {BWRITERSIO_SINCOS
, instr_handler
},
1810 {BWRITERSIO_M4x4
, instr_handler
},
1811 {BWRITERSIO_M4x3
, instr_handler
},
1812 {BWRITERSIO_M3x4
, instr_handler
},
1813 {BWRITERSIO_M3x3
, instr_handler
},
1814 {BWRITERSIO_M3x2
, instr_handler
},
1815 {BWRITERSIO_LIT
, instr_handler
},
1816 {BWRITERSIO_POW
, instr_handler
},
1817 {BWRITERSIO_MOVA
, instr_handler
},
1819 {BWRITERSIO_CALL
, instr_handler
},
1820 {BWRITERSIO_CALLNZ
, instr_handler
},
1821 {BWRITERSIO_REP
, instr_handler
},
1822 {BWRITERSIO_ENDREP
, instr_handler
},
1823 {BWRITERSIO_IF
, instr_handler
},
1824 {BWRITERSIO_LABEL
, instr_handler
},
1825 {BWRITERSIO_IFC
, instr_handler
},
1826 {BWRITERSIO_ELSE
, instr_handler
},
1827 {BWRITERSIO_ENDIF
, instr_handler
},
1828 {BWRITERSIO_BREAK
, instr_handler
},
1829 {BWRITERSIO_BREAKC
, instr_handler
},
1830 {BWRITERSIO_LOOP
, instr_handler
},
1831 {BWRITERSIO_RET
, instr_handler
},
1832 {BWRITERSIO_ENDLOOP
, instr_handler
},
1834 {BWRITERSIO_SETP
, instr_handler
},
1835 {BWRITERSIO_BREAKP
, instr_handler
},
1837 {BWRITERSIO_END
, NULL
},
1840 static const struct bytecode_backend vs_2_x_backend
= {
1849 static void write_samplers(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1851 DWORD instr_dcl
= D3DSIO_DCL
| (2 << D3DSI_INSTLENGTH_SHIFT
);
1853 const DWORD reg
= (1<<31) |
1854 ((D3DSPR_SAMPLER
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
) |
1855 ((D3DSPR_SAMPLER
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
) |
1856 D3DSP_WRITEMASK_ALL
;
1858 for(i
= 0; i
< shader
->num_samplers
; i
++) {
1859 /* Write the DCL instruction */
1860 put_dword(buffer
, instr_dcl
);
1862 /* Already shifted */
1863 token
|= (d3d9_sampler(shader
->samplers
[i
].type
)) & D3DSP_TEXTURETYPE_MASK
;
1864 put_dword(buffer
, token
);
1865 token
= reg
| (shader
->samplers
[i
].regnum
& D3DSP_REGNUM_MASK
);
1866 token
|= d3d9_dstmod(shader
->samplers
[i
].mod
);
1867 put_dword(buffer
, token
);
1871 static void ps_2_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1872 HRESULT hr
= find_ps_builtin_semantics(This
, shader
, 8);
1878 /* Declare the shader type and version */
1879 put_dword(buffer
, This
->version
);
1880 write_declarations(This
, buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
1881 write_samplers(shader
, buffer
);
1882 write_constF(shader
, buffer
, TRUE
);
1883 write_constB(shader
, buffer
, TRUE
);
1884 write_constI(shader
, buffer
, TRUE
);
1887 static void ps_2_srcreg(struct bc_writer
*This
,
1888 const struct shader_reg
*reg
,
1889 struct bytecode_buffer
*buffer
) {
1890 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1893 WARN("Relative addressing not supported in <= ps_3_0\n");
1894 This
->state
= E_INVALIDARG
;
1899 case BWRITERSPR_INPUT
:
1900 token
|= map_ps_input(This
, reg
);
1903 /* Can be mapped 1:1 */
1904 case BWRITERSPR_TEMP
:
1905 case BWRITERSPR_CONST
:
1906 case BWRITERSPR_COLOROUT
:
1907 case BWRITERSPR_CONSTBOOL
:
1908 case BWRITERSPR_CONSTINT
:
1909 case BWRITERSPR_SAMPLER
:
1910 case BWRITERSPR_LABEL
:
1911 case BWRITERSPR_DEPTHOUT
:
1912 d3d9reg
= d3d9_register(reg
->type
);
1913 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1914 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1915 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1918 case BWRITERSPR_PREDICATE
:
1919 if(This
->version
!= BWRITERPS_VERSION(2, 1)){
1920 WARN("Predicate register not supported in ps_2_0\n");
1921 This
->state
= E_INVALIDARG
;
1924 WARN("Predicate register with regnum %u not supported\n",
1926 This
->state
= E_INVALIDARG
;
1928 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1929 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1930 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
1934 WARN("Invalid register type for ps_2_0 shader\n");
1935 This
->state
= E_INVALIDARG
;
1939 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1941 token
|= d3d9_srcmod(reg
->srcmod
);
1942 put_dword(buffer
, token
);
1945 static void ps_2_0_dstreg(struct bc_writer
*This
,
1946 const struct shader_reg
*reg
,
1947 struct bytecode_buffer
*buffer
,
1948 DWORD shift
, DWORD mod
) {
1949 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1953 WARN("Relative addressing not supported for destination registers\n");
1954 This
->state
= E_INVALIDARG
;
1959 case BWRITERSPR_TEMP
: /* 1:1 mapping */
1960 case BWRITERSPR_COLOROUT
:
1961 case BWRITERSPR_DEPTHOUT
:
1962 d3d9reg
= d3d9_register(reg
->type
);
1963 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1964 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1965 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1968 case BWRITERSPR_PREDICATE
:
1969 if(This
->version
!= BWRITERPS_VERSION(2, 1)){
1970 WARN("Predicate register not supported in ps_2_0\n");
1971 This
->state
= E_INVALIDARG
;
1973 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1974 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1975 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1978 /* texkill uses the input register as a destination parameter */
1979 case BWRITERSPR_INPUT
:
1980 token
|= map_ps_input(This
, reg
);
1984 WARN("Invalid dest register type for 2.x pshader\n");
1985 This
->state
= E_INVALIDARG
;
1989 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1990 token
|= d3d9_dstmod(mod
);
1992 token
|= d3d9_writemask(reg
->u
.writemask
);
1993 put_dword(buffer
, token
);
1996 static const struct instr_handler_table ps_2_0_handlers
[] = {
1997 {BWRITERSIO_ADD
, instr_handler
},
1998 {BWRITERSIO_NOP
, instr_handler
},
1999 {BWRITERSIO_MOV
, instr_handler
},
2000 {BWRITERSIO_SUB
, instr_handler
},
2001 {BWRITERSIO_MAD
, instr_handler
},
2002 {BWRITERSIO_MUL
, instr_handler
},
2003 {BWRITERSIO_RCP
, instr_handler
},
2004 {BWRITERSIO_RSQ
, instr_handler
},
2005 {BWRITERSIO_DP3
, instr_handler
},
2006 {BWRITERSIO_DP4
, instr_handler
},
2007 {BWRITERSIO_MIN
, instr_handler
},
2008 {BWRITERSIO_MAX
, instr_handler
},
2009 {BWRITERSIO_ABS
, instr_handler
},
2010 {BWRITERSIO_EXP
, instr_handler
},
2011 {BWRITERSIO_LOG
, instr_handler
},
2012 {BWRITERSIO_EXPP
, instr_handler
},
2013 {BWRITERSIO_LOGP
, instr_handler
},
2014 {BWRITERSIO_LRP
, instr_handler
},
2015 {BWRITERSIO_FRC
, instr_handler
},
2016 {BWRITERSIO_CRS
, instr_handler
},
2017 {BWRITERSIO_NRM
, instr_handler
},
2018 {BWRITERSIO_SINCOS
, instr_handler
},
2019 {BWRITERSIO_M4x4
, instr_handler
},
2020 {BWRITERSIO_M4x3
, instr_handler
},
2021 {BWRITERSIO_M3x4
, instr_handler
},
2022 {BWRITERSIO_M3x3
, instr_handler
},
2023 {BWRITERSIO_M3x2
, instr_handler
},
2024 {BWRITERSIO_POW
, instr_handler
},
2025 {BWRITERSIO_DP2ADD
, instr_handler
},
2026 {BWRITERSIO_CMP
, instr_handler
},
2028 {BWRITERSIO_TEX
, instr_handler
},
2029 {BWRITERSIO_TEXLDP
, instr_handler
},
2030 {BWRITERSIO_TEXLDB
, instr_handler
},
2031 {BWRITERSIO_TEXKILL
, instr_handler
},
2033 {BWRITERSIO_END
, NULL
},
2036 static const struct bytecode_backend ps_2_0_backend
= {
2045 static const struct instr_handler_table ps_2_x_handlers
[] = {
2046 {BWRITERSIO_ADD
, instr_handler
},
2047 {BWRITERSIO_NOP
, instr_handler
},
2048 {BWRITERSIO_MOV
, instr_handler
},
2049 {BWRITERSIO_SUB
, instr_handler
},
2050 {BWRITERSIO_MAD
, instr_handler
},
2051 {BWRITERSIO_MUL
, instr_handler
},
2052 {BWRITERSIO_RCP
, instr_handler
},
2053 {BWRITERSIO_RSQ
, instr_handler
},
2054 {BWRITERSIO_DP3
, instr_handler
},
2055 {BWRITERSIO_DP4
, instr_handler
},
2056 {BWRITERSIO_MIN
, instr_handler
},
2057 {BWRITERSIO_MAX
, instr_handler
},
2058 {BWRITERSIO_ABS
, instr_handler
},
2059 {BWRITERSIO_EXP
, instr_handler
},
2060 {BWRITERSIO_LOG
, instr_handler
},
2061 {BWRITERSIO_EXPP
, instr_handler
},
2062 {BWRITERSIO_LOGP
, instr_handler
},
2063 {BWRITERSIO_LRP
, instr_handler
},
2064 {BWRITERSIO_FRC
, instr_handler
},
2065 {BWRITERSIO_CRS
, instr_handler
},
2066 {BWRITERSIO_NRM
, instr_handler
},
2067 {BWRITERSIO_SINCOS
, instr_handler
},
2068 {BWRITERSIO_M4x4
, instr_handler
},
2069 {BWRITERSIO_M4x3
, instr_handler
},
2070 {BWRITERSIO_M3x4
, instr_handler
},
2071 {BWRITERSIO_M3x3
, instr_handler
},
2072 {BWRITERSIO_M3x2
, instr_handler
},
2073 {BWRITERSIO_POW
, instr_handler
},
2074 {BWRITERSIO_DP2ADD
, instr_handler
},
2075 {BWRITERSIO_CMP
, instr_handler
},
2077 {BWRITERSIO_CALL
, instr_handler
},
2078 {BWRITERSIO_CALLNZ
, instr_handler
},
2079 {BWRITERSIO_REP
, instr_handler
},
2080 {BWRITERSIO_ENDREP
, instr_handler
},
2081 {BWRITERSIO_IF
, instr_handler
},
2082 {BWRITERSIO_LABEL
, instr_handler
},
2083 {BWRITERSIO_IFC
, instr_handler
},
2084 {BWRITERSIO_ELSE
, instr_handler
},
2085 {BWRITERSIO_ENDIF
, instr_handler
},
2086 {BWRITERSIO_BREAK
, instr_handler
},
2087 {BWRITERSIO_BREAKC
, instr_handler
},
2088 {BWRITERSIO_RET
, instr_handler
},
2090 {BWRITERSIO_TEX
, instr_handler
},
2091 {BWRITERSIO_TEXLDP
, instr_handler
},
2092 {BWRITERSIO_TEXLDB
, instr_handler
},
2093 {BWRITERSIO_TEXKILL
, instr_handler
},
2094 {BWRITERSIO_DSX
, instr_handler
},
2095 {BWRITERSIO_DSY
, instr_handler
},
2097 {BWRITERSIO_SETP
, instr_handler
},
2098 {BWRITERSIO_BREAKP
, instr_handler
},
2100 {BWRITERSIO_TEXLDD
, instr_handler
},
2102 {BWRITERSIO_END
, NULL
},
2105 static const struct bytecode_backend ps_2_x_backend
= {
2114 static void sm_3_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
2115 /* Declare the shader type and version */
2116 put_dword(buffer
, This
->version
);
2118 write_declarations(This
, buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
2119 write_declarations(This
, buffer
, TRUE
, shader
->outputs
, shader
->num_outputs
, BWRITERSPR_OUTPUT
);
2120 write_constF(shader
, buffer
, TRUE
);
2121 write_constB(shader
, buffer
, TRUE
);
2122 write_constI(shader
, buffer
, TRUE
);
2123 write_samplers(shader
, buffer
);
2127 static void sm_3_srcreg(struct bc_writer
*This
,
2128 const struct shader_reg
*reg
,
2129 struct bytecode_buffer
*buffer
) {
2130 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
2133 d3d9reg
= d3d9_register(reg
->type
);
2134 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
2135 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
2136 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
;
2138 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
;
2139 token
|= d3d9_srcmod(reg
->srcmod
);
2142 if(reg
->type
== BWRITERSPR_CONST
&& This
->version
== BWRITERPS_VERSION(3, 0)) {
2143 WARN("c%u[...] is unsupported in ps_3_0\n", reg
->regnum
);
2144 This
->state
= E_INVALIDARG
;
2147 if(((reg
->rel_reg
->type
== BWRITERSPR_ADDR
&& This
->version
== BWRITERVS_VERSION(3, 0)) ||
2148 reg
->rel_reg
->type
== BWRITERSPR_LOOP
) &&
2149 reg
->rel_reg
->regnum
== 0) {
2150 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
2152 WARN("Unsupported relative addressing register\n");
2153 This
->state
= E_INVALIDARG
;
2158 put_dword(buffer
, token
);
2160 /* vs_2_0 and newer write the register containing the index explicitly in the
2163 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
2164 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
2168 static void sm_3_dstreg(struct bc_writer
*This
,
2169 const struct shader_reg
*reg
,
2170 struct bytecode_buffer
*buffer
,
2171 DWORD shift
, DWORD mod
) {
2172 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
2176 if(This
->version
== BWRITERVS_VERSION(3, 0) &&
2177 reg
->type
== BWRITERSPR_OUTPUT
) {
2178 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
2180 WARN("Relative addressing not supported for this shader type or register type\n");
2181 This
->state
= E_INVALIDARG
;
2186 d3d9reg
= d3d9_register(reg
->type
);
2187 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
2188 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
2189 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
2191 token
|= d3d9_dstmod(mod
);
2193 token
|= d3d9_writemask(reg
->u
.writemask
);
2194 put_dword(buffer
, token
);
2196 /* vs_2_0 and newer write the register containing the index explicitly in the
2199 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
2200 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
2204 static const struct instr_handler_table vs_3_handlers
[] = {
2205 {BWRITERSIO_ADD
, instr_handler
},
2206 {BWRITERSIO_NOP
, instr_handler
},
2207 {BWRITERSIO_MOV
, instr_handler
},
2208 {BWRITERSIO_SUB
, instr_handler
},
2209 {BWRITERSIO_MAD
, instr_handler
},
2210 {BWRITERSIO_MUL
, instr_handler
},
2211 {BWRITERSIO_RCP
, instr_handler
},
2212 {BWRITERSIO_RSQ
, instr_handler
},
2213 {BWRITERSIO_DP3
, instr_handler
},
2214 {BWRITERSIO_DP4
, instr_handler
},
2215 {BWRITERSIO_MIN
, instr_handler
},
2216 {BWRITERSIO_MAX
, instr_handler
},
2217 {BWRITERSIO_SLT
, instr_handler
},
2218 {BWRITERSIO_SGE
, instr_handler
},
2219 {BWRITERSIO_ABS
, instr_handler
},
2220 {BWRITERSIO_EXP
, instr_handler
},
2221 {BWRITERSIO_LOG
, instr_handler
},
2222 {BWRITERSIO_EXPP
, instr_handler
},
2223 {BWRITERSIO_LOGP
, instr_handler
},
2224 {BWRITERSIO_DST
, instr_handler
},
2225 {BWRITERSIO_LRP
, instr_handler
},
2226 {BWRITERSIO_FRC
, instr_handler
},
2227 {BWRITERSIO_CRS
, instr_handler
},
2228 {BWRITERSIO_SGN
, instr_handler
},
2229 {BWRITERSIO_NRM
, instr_handler
},
2230 {BWRITERSIO_SINCOS
, instr_handler
},
2231 {BWRITERSIO_M4x4
, instr_handler
},
2232 {BWRITERSIO_M4x3
, instr_handler
},
2233 {BWRITERSIO_M3x4
, instr_handler
},
2234 {BWRITERSIO_M3x3
, instr_handler
},
2235 {BWRITERSIO_M3x2
, instr_handler
},
2236 {BWRITERSIO_LIT
, instr_handler
},
2237 {BWRITERSIO_POW
, instr_handler
},
2238 {BWRITERSIO_MOVA
, instr_handler
},
2240 {BWRITERSIO_CALL
, instr_handler
},
2241 {BWRITERSIO_CALLNZ
, instr_handler
},
2242 {BWRITERSIO_REP
, instr_handler
},
2243 {BWRITERSIO_ENDREP
, instr_handler
},
2244 {BWRITERSIO_IF
, instr_handler
},
2245 {BWRITERSIO_LABEL
, instr_handler
},
2246 {BWRITERSIO_IFC
, instr_handler
},
2247 {BWRITERSIO_ELSE
, instr_handler
},
2248 {BWRITERSIO_ENDIF
, instr_handler
},
2249 {BWRITERSIO_BREAK
, instr_handler
},
2250 {BWRITERSIO_BREAKC
, instr_handler
},
2251 {BWRITERSIO_LOOP
, instr_handler
},
2252 {BWRITERSIO_RET
, instr_handler
},
2253 {BWRITERSIO_ENDLOOP
, instr_handler
},
2255 {BWRITERSIO_SETP
, instr_handler
},
2256 {BWRITERSIO_BREAKP
, instr_handler
},
2257 {BWRITERSIO_TEXLDL
, instr_handler
},
2259 {BWRITERSIO_END
, NULL
},
2262 static const struct bytecode_backend vs_3_backend
= {
2271 static const struct instr_handler_table ps_3_handlers
[] = {
2272 {BWRITERSIO_ADD
, instr_handler
},
2273 {BWRITERSIO_NOP
, instr_handler
},
2274 {BWRITERSIO_MOV
, instr_handler
},
2275 {BWRITERSIO_SUB
, instr_handler
},
2276 {BWRITERSIO_MAD
, instr_handler
},
2277 {BWRITERSIO_MUL
, instr_handler
},
2278 {BWRITERSIO_RCP
, instr_handler
},
2279 {BWRITERSIO_RSQ
, instr_handler
},
2280 {BWRITERSIO_DP3
, instr_handler
},
2281 {BWRITERSIO_DP4
, instr_handler
},
2282 {BWRITERSIO_MIN
, instr_handler
},
2283 {BWRITERSIO_MAX
, instr_handler
},
2284 {BWRITERSIO_ABS
, instr_handler
},
2285 {BWRITERSIO_EXP
, instr_handler
},
2286 {BWRITERSIO_LOG
, instr_handler
},
2287 {BWRITERSIO_EXPP
, instr_handler
},
2288 {BWRITERSIO_LOGP
, instr_handler
},
2289 {BWRITERSIO_LRP
, instr_handler
},
2290 {BWRITERSIO_FRC
, instr_handler
},
2291 {BWRITERSIO_CRS
, instr_handler
},
2292 {BWRITERSIO_NRM
, instr_handler
},
2293 {BWRITERSIO_SINCOS
, instr_handler
},
2294 {BWRITERSIO_M4x4
, instr_handler
},
2295 {BWRITERSIO_M4x3
, instr_handler
},
2296 {BWRITERSIO_M3x4
, instr_handler
},
2297 {BWRITERSIO_M3x3
, instr_handler
},
2298 {BWRITERSIO_M3x2
, instr_handler
},
2299 {BWRITERSIO_POW
, instr_handler
},
2300 {BWRITERSIO_DP2ADD
, instr_handler
},
2301 {BWRITERSIO_CMP
, instr_handler
},
2303 {BWRITERSIO_CALL
, instr_handler
},
2304 {BWRITERSIO_CALLNZ
, instr_handler
},
2305 {BWRITERSIO_REP
, instr_handler
},
2306 {BWRITERSIO_ENDREP
, instr_handler
},
2307 {BWRITERSIO_IF
, instr_handler
},
2308 {BWRITERSIO_LABEL
, instr_handler
},
2309 {BWRITERSIO_IFC
, instr_handler
},
2310 {BWRITERSIO_ELSE
, instr_handler
},
2311 {BWRITERSIO_ENDIF
, instr_handler
},
2312 {BWRITERSIO_BREAK
, instr_handler
},
2313 {BWRITERSIO_BREAKC
, instr_handler
},
2314 {BWRITERSIO_LOOP
, instr_handler
},
2315 {BWRITERSIO_RET
, instr_handler
},
2316 {BWRITERSIO_ENDLOOP
, instr_handler
},
2318 {BWRITERSIO_SETP
, instr_handler
},
2319 {BWRITERSIO_BREAKP
, instr_handler
},
2320 {BWRITERSIO_TEXLDL
, instr_handler
},
2322 {BWRITERSIO_TEX
, instr_handler
},
2323 {BWRITERSIO_TEXLDP
, instr_handler
},
2324 {BWRITERSIO_TEXLDB
, instr_handler
},
2325 {BWRITERSIO_TEXKILL
, instr_handler
},
2326 {BWRITERSIO_DSX
, instr_handler
},
2327 {BWRITERSIO_DSY
, instr_handler
},
2328 {BWRITERSIO_TEXLDD
, instr_handler
},
2330 {BWRITERSIO_END
, NULL
},
2333 static const struct bytecode_backend ps_3_backend
= {
2342 static void init_vs10_dx9_writer(struct bc_writer
*writer
) {
2343 TRACE("Creating DirectX9 vertex shader 1.0 writer\n");
2344 writer
->funcs
= &vs_1_x_backend
;
2347 static void init_vs11_dx9_writer(struct bc_writer
*writer
) {
2348 TRACE("Creating DirectX9 vertex shader 1.1 writer\n");
2349 writer
->funcs
= &vs_1_x_backend
;
2352 static void init_vs20_dx9_writer(struct bc_writer
*writer
) {
2353 TRACE("Creating DirectX9 vertex shader 2.0 writer\n");
2354 writer
->funcs
= &vs_2_0_backend
;
2357 static void init_vs2x_dx9_writer(struct bc_writer
*writer
) {
2358 TRACE("Creating DirectX9 vertex shader 2.x writer\n");
2359 writer
->funcs
= &vs_2_x_backend
;
2362 static void init_vs30_dx9_writer(struct bc_writer
*writer
) {
2363 TRACE("Creating DirectX9 vertex shader 3.0 writer\n");
2364 writer
->funcs
= &vs_3_backend
;
2367 static void init_ps10_dx9_writer(struct bc_writer
*writer
) {
2368 TRACE("Creating DirectX9 pixel shader 1.0 writer\n");
2369 writer
->funcs
= &ps_1_0123_backend
;
2372 static void init_ps11_dx9_writer(struct bc_writer
*writer
) {
2373 TRACE("Creating DirectX9 pixel shader 1.1 writer\n");
2374 writer
->funcs
= &ps_1_0123_backend
;
2377 static void init_ps12_dx9_writer(struct bc_writer
*writer
) {
2378 TRACE("Creating DirectX9 pixel shader 1.2 writer\n");
2379 writer
->funcs
= &ps_1_0123_backend
;
2382 static void init_ps13_dx9_writer(struct bc_writer
*writer
) {
2383 TRACE("Creating DirectX9 pixel shader 1.3 writer\n");
2384 writer
->funcs
= &ps_1_0123_backend
;
2387 static void init_ps14_dx9_writer(struct bc_writer
*writer
) {
2388 TRACE("Creating DirectX9 pixel shader 1.4 writer\n");
2389 writer
->funcs
= &ps_1_4_backend
;
2392 static void init_ps20_dx9_writer(struct bc_writer
*writer
) {
2393 TRACE("Creating DirectX9 pixel shader 2.0 writer\n");
2394 writer
->funcs
= &ps_2_0_backend
;
2397 static void init_ps2x_dx9_writer(struct bc_writer
*writer
) {
2398 TRACE("Creating DirectX9 pixel shader 2.x writer\n");
2399 writer
->funcs
= &ps_2_x_backend
;
2402 static void init_ps30_dx9_writer(struct bc_writer
*writer
) {
2403 TRACE("Creating DirectX9 pixel shader 3.0 writer\n");
2404 writer
->funcs
= &ps_3_backend
;
2407 static struct bc_writer
*create_writer(DWORD version
, DWORD dxversion
) {
2408 struct bc_writer
*ret
= asm_alloc(sizeof(*ret
));
2411 WARN("Failed to allocate a bytecode writer instance\n");
2416 case BWRITERVS_VERSION(1, 0):
2417 if(dxversion
!= 9) {
2418 WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion
);
2421 init_vs10_dx9_writer(ret
);
2423 case BWRITERVS_VERSION(1, 1):
2424 if(dxversion
!= 9) {
2425 WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion
);
2428 init_vs11_dx9_writer(ret
);
2430 case BWRITERVS_VERSION(2, 0):
2431 if(dxversion
!= 9) {
2432 WARN("Unsupported dxversion for vertex shader 2.0 requested: %u\n", dxversion
);
2435 init_vs20_dx9_writer(ret
);
2437 case BWRITERVS_VERSION(2, 1):
2438 if(dxversion
!= 9) {
2439 WARN("Unsupported dxversion for vertex shader 2.x requested: %u\n", dxversion
);
2442 init_vs2x_dx9_writer(ret
);
2444 case BWRITERVS_VERSION(3, 0):
2445 if(dxversion
!= 9) {
2446 WARN("Unsupported dxversion for vertex shader 3.0 requested: %u\n", dxversion
);
2449 init_vs30_dx9_writer(ret
);
2452 case BWRITERPS_VERSION(1, 0):
2453 if(dxversion
!= 9) {
2454 WARN("Unsupported dxversion for pixel shader 1.0 requested: %u\n", dxversion
);
2457 init_ps10_dx9_writer(ret
);
2459 case BWRITERPS_VERSION(1, 1):
2460 if(dxversion
!= 9) {
2461 WARN("Unsupported dxversion for pixel shader 1.1 requested: %u\n", dxversion
);
2464 init_ps11_dx9_writer(ret
);
2466 case BWRITERPS_VERSION(1, 2):
2467 if(dxversion
!= 9) {
2468 WARN("Unsupported dxversion for pixel shader 1.2 requested: %u\n", dxversion
);
2471 init_ps12_dx9_writer(ret
);
2473 case BWRITERPS_VERSION(1, 3):
2474 if(dxversion
!= 9) {
2475 WARN("Unsupported dxversion for pixel shader 1.3 requested: %u\n", dxversion
);
2478 init_ps13_dx9_writer(ret
);
2480 case BWRITERPS_VERSION(1, 4):
2481 if(dxversion
!= 9) {
2482 WARN("Unsupported dxversion for pixel shader 1.4 requested: %u\n", dxversion
);
2485 init_ps14_dx9_writer(ret
);
2488 case BWRITERPS_VERSION(2, 0):
2489 if(dxversion
!= 9) {
2490 WARN("Unsupported dxversion for pixel shader 2.0 requested: %u\n", dxversion
);
2493 init_ps20_dx9_writer(ret
);
2496 case BWRITERPS_VERSION(2, 1):
2497 if(dxversion
!= 9) {
2498 WARN("Unsupported dxversion for pixel shader 2.x requested: %u\n", dxversion
);
2501 init_ps2x_dx9_writer(ret
);
2504 case BWRITERPS_VERSION(3, 0):
2505 if(dxversion
!= 9) {
2506 WARN("Unsupported dxversion for pixel shader 3.0 requested: %u\n", dxversion
);
2509 init_ps30_dx9_writer(ret
);
2513 WARN("Unexpected shader version requested: %08x\n", version
);
2516 ret
->version
= version
;
2524 static HRESULT
call_instr_handler(struct bc_writer
*writer
,
2525 const struct instruction
*instr
,
2526 struct bytecode_buffer
*buffer
) {
2529 while(writer
->funcs
->instructions
[i
].opcode
!= BWRITERSIO_END
) {
2530 if(instr
->opcode
== writer
->funcs
->instructions
[i
].opcode
) {
2531 if(!writer
->funcs
->instructions
[i
].func
) {
2532 WARN("Opcode %u not supported by this profile\n", instr
->opcode
);
2533 return E_INVALIDARG
;
2535 writer
->funcs
->instructions
[i
].func(writer
, instr
, buffer
);
2541 FIXME("Unhandled instruction %u - %s\n", instr
->opcode
,
2542 debug_print_opcode(instr
->opcode
));
2543 return E_INVALIDARG
;
2546 /* SlWriteBytecode (wineshader.@)
2548 * Writes shader version specific bytecode from the shader passed in.
2549 * The returned bytecode can be passed to the Direct3D runtime like
2550 * IDirect3DDevice9::Create*Shader.
2553 * shader: Shader to translate into bytecode
2554 * version: Shader version to generate(d3d version token)
2555 * dxversion: DirectX version the code targets
2556 * result: the resulting shader bytecode
2561 DWORD
SlWriteBytecode(const struct bwriter_shader
*shader
, int dxversion
, DWORD
**result
) {
2562 struct bc_writer
*writer
;
2563 struct bytecode_buffer
*buffer
= NULL
;
2568 ERR("NULL shader structure, aborting\n");
2571 writer
= create_writer(shader
->version
, dxversion
);
2575 WARN("Could not create a bytecode writer instance. Either unsupported version\n");
2576 WARN("or out of memory\n");
2581 buffer
= allocate_buffer();
2583 WARN("Failed to allocate a buffer for the shader bytecode\n");
2588 writer
->funcs
->header(writer
, shader
, buffer
);
2589 if(FAILED(writer
->state
)) {
2594 for(i
= 0; i
< shader
->num_instrs
; i
++) {
2595 hr
= call_instr_handler(writer
, shader
->instr
[i
], buffer
);
2601 if(FAILED(writer
->state
)) {
2606 writer
->funcs
->end(writer
, shader
, buffer
);
2608 if(FAILED(buffer
->state
)) {
2613 /* Cut off unneeded memory from the result buffer */
2614 *result
= asm_realloc(buffer
->data
,
2615 sizeof(DWORD
) * buffer
->size
);
2617 *result
= buffer
->data
;
2619 buffer
->data
= NULL
;
2624 asm_free(buffer
->data
);
2631 void SlDeleteShader(struct bwriter_shader
*shader
) {
2634 TRACE("Deleting shader %p\n", shader
);
2636 for(i
= 0; i
< shader
->num_cf
; i
++) {
2637 asm_free(shader
->constF
[i
]);
2639 asm_free(shader
->constF
);
2640 for(i
= 0; i
< shader
->num_ci
; i
++) {
2641 asm_free(shader
->constI
[i
]);
2643 asm_free(shader
->constI
);
2644 for(i
= 0; i
< shader
->num_cb
; i
++) {
2645 asm_free(shader
->constB
[i
]);
2647 asm_free(shader
->constB
);
2649 asm_free(shader
->inputs
);
2650 asm_free(shader
->outputs
);
2651 asm_free(shader
->samplers
);
2653 for(i
= 0; i
< shader
->num_instrs
; i
++) {
2654 for(j
= 0; j
< shader
->instr
[i
]->num_srcs
; j
++) {
2655 asm_free(shader
->instr
[i
]->src
[j
].rel_reg
);
2657 asm_free(shader
->instr
[i
]->src
);
2658 asm_free(shader
->instr
[i
]);
2660 asm_free(shader
->instr
);