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
23 #include "d3dcompiler_private.h"
24 #include "d3d9types.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(bytecodewriter
);
28 /****************************************************************
29 * General assembler shader construction helper routines follow *
30 ****************************************************************/
31 /* struct instruction *alloc_instr
33 * Allocates a new instruction structure with srcs registers
36 * srcs: Number of source registers to allocate
39 * A pointer to the allocated instruction structure
40 * NULL in case of an allocation failure
42 struct instruction
*alloc_instr(unsigned int srcs
) {
43 struct instruction
*ret
= d3dcompiler_alloc(sizeof(*ret
));
45 ERR("Failed to allocate memory for an instruction structure\n");
50 ret
->src
= d3dcompiler_alloc(srcs
* sizeof(*ret
->src
));
52 ERR("Failed to allocate memory for instruction registers\n");
53 d3dcompiler_free(ret
);
61 /* void add_instruction
63 * Adds a new instruction to the shader's instructions array and grows the instruction array
66 * The function does NOT copy the instruction structure. Make sure not to release the
67 * instruction or any of its substructures like registers.
70 * shader: Shader to add the instruction to
71 * instr: Instruction to add to the shader
73 BOOL
add_instruction(struct bwriter_shader
*shader
, struct instruction
*instr
) {
74 struct instruction
**new_instructions
;
76 if(!shader
) return FALSE
;
78 if(shader
->instr_alloc_size
== 0) {
79 shader
->instr
= d3dcompiler_alloc(sizeof(*shader
->instr
) * INSTRARRAY_INITIAL_SIZE
);
81 ERR("Failed to allocate the shader instruction array\n");
84 shader
->instr_alloc_size
= INSTRARRAY_INITIAL_SIZE
;
85 } else if(shader
->instr_alloc_size
== shader
->num_instrs
) {
86 new_instructions
= d3dcompiler_realloc(shader
->instr
,
87 sizeof(*shader
->instr
) * (shader
->instr_alloc_size
) * 2);
88 if(!new_instructions
) {
89 ERR("Failed to grow the shader instruction array\n");
92 shader
->instr
= new_instructions
;
93 shader
->instr_alloc_size
= shader
->instr_alloc_size
* 2;
94 } else if(shader
->num_instrs
> shader
->instr_alloc_size
) {
95 ERR("More instructions than allocated. This should not happen\n");
99 shader
->instr
[shader
->num_instrs
] = instr
;
100 shader
->num_instrs
++;
104 BOOL
add_constF(struct bwriter_shader
*shader
, DWORD reg
, float x
, float y
, float z
, float w
) {
105 struct constant
*newconst
;
108 struct constant
**newarray
;
109 newarray
= d3dcompiler_realloc(shader
->constF
,
110 sizeof(*shader
->constF
) * (shader
->num_cf
+ 1));
112 ERR("Failed to grow the constants array\n");
115 shader
->constF
= newarray
;
117 shader
->constF
= d3dcompiler_alloc(sizeof(*shader
->constF
));
118 if(!shader
->constF
) {
119 ERR("Failed to allocate the constants array\n");
124 newconst
= d3dcompiler_alloc(sizeof(*newconst
));
126 ERR("Failed to allocate a new constant\n");
129 newconst
->regnum
= reg
;
130 newconst
->value
[0].f
= x
;
131 newconst
->value
[1].f
= y
;
132 newconst
->value
[2].f
= z
;
133 newconst
->value
[3].f
= w
;
134 shader
->constF
[shader
->num_cf
] = newconst
;
140 BOOL
add_constI(struct bwriter_shader
*shader
, DWORD reg
, INT x
, INT y
, INT z
, INT w
) {
141 struct constant
*newconst
;
144 struct constant
**newarray
;
145 newarray
= d3dcompiler_realloc(shader
->constI
,
146 sizeof(*shader
->constI
) * (shader
->num_ci
+ 1));
148 ERR("Failed to grow the constants array\n");
151 shader
->constI
= newarray
;
153 shader
->constI
= d3dcompiler_alloc(sizeof(*shader
->constI
));
154 if(!shader
->constI
) {
155 ERR("Failed to allocate the constants array\n");
160 newconst
= d3dcompiler_alloc(sizeof(*newconst
));
162 ERR("Failed to allocate a new constant\n");
165 newconst
->regnum
= reg
;
166 newconst
->value
[0].i
= x
;
167 newconst
->value
[1].i
= y
;
168 newconst
->value
[2].i
= z
;
169 newconst
->value
[3].i
= w
;
170 shader
->constI
[shader
->num_ci
] = newconst
;
176 BOOL
add_constB(struct bwriter_shader
*shader
, DWORD reg
, BOOL x
) {
177 struct constant
*newconst
;
180 struct constant
**newarray
;
181 newarray
= d3dcompiler_realloc(shader
->constB
,
182 sizeof(*shader
->constB
) * (shader
->num_cb
+ 1));
184 ERR("Failed to grow the constants array\n");
187 shader
->constB
= newarray
;
189 shader
->constB
= d3dcompiler_alloc(sizeof(*shader
->constB
));
190 if(!shader
->constB
) {
191 ERR("Failed to allocate the constants array\n");
196 newconst
= d3dcompiler_alloc(sizeof(*newconst
));
198 ERR("Failed to allocate a new constant\n");
201 newconst
->regnum
= reg
;
202 newconst
->value
[0].b
= x
;
203 shader
->constB
[shader
->num_cb
] = newconst
;
209 BOOL
record_declaration(struct bwriter_shader
*shader
, DWORD usage
,
210 DWORD usage_idx
, DWORD mod
, BOOL output
,
211 DWORD regnum
, DWORD writemask
, BOOL builtin
) {
213 struct declaration
**decl
;
216 if(!shader
) return FALSE
;
219 num
= &shader
->num_outputs
;
220 decl
= &shader
->outputs
;
222 num
= &shader
->num_inputs
;
223 decl
= &shader
->inputs
;
227 *decl
= d3dcompiler_alloc(sizeof(**decl
));
229 ERR("Error allocating declarations array\n");
233 struct declaration
*newdecl
;
234 for(i
= 0; i
< *num
; i
++) {
235 if((*decl
)[i
].regnum
== regnum
&& ((*decl
)[i
].writemask
& writemask
)) {
236 WARN("Declaration of register %u already exists, writemask match 0x%x\n",
237 regnum
, (*decl
)[i
].writemask
& writemask
);
241 newdecl
= d3dcompiler_realloc(*decl
,
242 sizeof(**decl
) * ((*num
) + 1));
244 ERR("Error reallocating declarations array\n");
249 (*decl
)[*num
].usage
= usage
;
250 (*decl
)[*num
].usage_idx
= usage_idx
;
251 (*decl
)[*num
].regnum
= regnum
;
252 (*decl
)[*num
].mod
= mod
;
253 (*decl
)[*num
].writemask
= writemask
;
254 (*decl
)[*num
].builtin
= builtin
;
260 BOOL
record_sampler(struct bwriter_shader
*shader
, DWORD samptype
, DWORD mod
, DWORD regnum
) {
263 if(!shader
) return FALSE
;
265 if(shader
->num_samplers
== 0) {
266 shader
->samplers
= d3dcompiler_alloc(sizeof(*shader
->samplers
));
267 if(!shader
->samplers
) {
268 ERR("Error allocating samplers array\n");
272 struct samplerdecl
*newarray
;
274 for(i
= 0; i
< shader
->num_samplers
; i
++) {
275 if(shader
->samplers
[i
].regnum
== regnum
) {
276 WARN("Sampler %u already declared\n", regnum
);
277 /* This is not an error as far as the assembler is concerned.
278 * Direct3D might refuse to load the compiled shader though
283 newarray
= d3dcompiler_realloc(shader
->samplers
,
284 sizeof(*shader
->samplers
) * (shader
->num_samplers
+ 1));
286 ERR("Error reallocating samplers array\n");
289 shader
->samplers
= newarray
;
292 shader
->samplers
[shader
->num_samplers
].type
= samptype
;
293 shader
->samplers
[shader
->num_samplers
].mod
= mod
;
294 shader
->samplers
[shader
->num_samplers
].regnum
= regnum
;
295 shader
->num_samplers
++;
300 /* shader bytecode buffer manipulation functions.
301 * allocate_buffer creates a new buffer structure, put_dword adds a new
302 * DWORD to the buffer. In the rare case of a memory allocation failure
303 * when trying to grow the buffer a flag is set in the buffer to mark it
304 * invalid. This avoids return value checking and passing in many places
306 static struct bytecode_buffer
*allocate_buffer(void) {
307 struct bytecode_buffer
*ret
;
309 ret
= d3dcompiler_alloc(sizeof(*ret
));
310 if(!ret
) return NULL
;
312 ret
->alloc_size
= BYTECODEBUFFER_INITIAL_SIZE
;
313 ret
->data
= d3dcompiler_alloc(sizeof(DWORD
) * ret
->alloc_size
);
315 d3dcompiler_free(ret
);
322 static void put_dword(struct bytecode_buffer
*buffer
, DWORD value
) {
323 if(FAILED(buffer
->state
)) return;
325 if(buffer
->alloc_size
== buffer
->size
) {
327 buffer
->alloc_size
*= 2;
328 newarray
= d3dcompiler_realloc(buffer
->data
,
329 sizeof(DWORD
) * buffer
->alloc_size
);
331 ERR("Failed to grow the buffer data memory\n");
332 buffer
->state
= E_OUTOFMEMORY
;
335 buffer
->data
= newarray
;
337 buffer
->data
[buffer
->size
++] = value
;
340 /* bwriter -> d3d9 conversion functions. */
341 static DWORD
d3d9_swizzle(DWORD bwriter_swizzle
)
343 /* Currently a NOP, but this allows changing the internal definitions
344 * without side effects. */
347 if ((bwriter_swizzle
& BWRITERVS_X_X
) == BWRITERVS_X_X
) ret
|= D3DVS_X_X
;
348 if ((bwriter_swizzle
& BWRITERVS_X_Y
) == BWRITERVS_X_Y
) ret
|= D3DVS_X_Y
;
349 if ((bwriter_swizzle
& BWRITERVS_X_Z
) == BWRITERVS_X_Z
) ret
|= D3DVS_X_Z
;
350 if ((bwriter_swizzle
& BWRITERVS_X_W
) == BWRITERVS_X_W
) ret
|= D3DVS_X_W
;
352 if ((bwriter_swizzle
& BWRITERVS_Y_X
) == BWRITERVS_Y_X
) ret
|= D3DVS_Y_X
;
353 if ((bwriter_swizzle
& BWRITERVS_Y_Y
) == BWRITERVS_Y_Y
) ret
|= D3DVS_Y_Y
;
354 if ((bwriter_swizzle
& BWRITERVS_Y_Z
) == BWRITERVS_Y_Z
) ret
|= D3DVS_Y_Z
;
355 if ((bwriter_swizzle
& BWRITERVS_Y_W
) == BWRITERVS_Y_W
) ret
|= D3DVS_Y_W
;
357 if ((bwriter_swizzle
& BWRITERVS_Z_X
) == BWRITERVS_Z_X
) ret
|= D3DVS_Z_X
;
358 if ((bwriter_swizzle
& BWRITERVS_Z_Y
) == BWRITERVS_Z_Y
) ret
|= D3DVS_Z_Y
;
359 if ((bwriter_swizzle
& BWRITERVS_Z_Z
) == BWRITERVS_Z_Z
) ret
|= D3DVS_Z_Z
;
360 if ((bwriter_swizzle
& BWRITERVS_Z_W
) == BWRITERVS_Z_W
) ret
|= D3DVS_Z_W
;
362 if ((bwriter_swizzle
& BWRITERVS_W_X
) == BWRITERVS_W_X
) ret
|= D3DVS_W_X
;
363 if ((bwriter_swizzle
& BWRITERVS_W_Y
) == BWRITERVS_W_Y
) ret
|= D3DVS_W_Y
;
364 if ((bwriter_swizzle
& BWRITERVS_W_Z
) == BWRITERVS_W_Z
) ret
|= D3DVS_W_Z
;
365 if ((bwriter_swizzle
& BWRITERVS_W_W
) == BWRITERVS_W_W
) ret
|= D3DVS_W_W
;
370 static DWORD
d3d9_writemask(DWORD bwriter_writemask
)
374 if (bwriter_writemask
& BWRITERSP_WRITEMASK_0
) ret
|= D3DSP_WRITEMASK_0
;
375 if (bwriter_writemask
& BWRITERSP_WRITEMASK_1
) ret
|= D3DSP_WRITEMASK_1
;
376 if (bwriter_writemask
& BWRITERSP_WRITEMASK_2
) ret
|= D3DSP_WRITEMASK_2
;
377 if (bwriter_writemask
& BWRITERSP_WRITEMASK_3
) ret
|= D3DSP_WRITEMASK_3
;
382 static DWORD
d3d9_srcmod(DWORD bwriter_srcmod
)
384 switch (bwriter_srcmod
)
386 case BWRITERSPSM_NONE
: return D3DSPSM_NONE
;
387 case BWRITERSPSM_NEG
: return D3DSPSM_NEG
;
388 case BWRITERSPSM_BIAS
: return D3DSPSM_BIAS
;
389 case BWRITERSPSM_BIASNEG
: return D3DSPSM_BIASNEG
;
390 case BWRITERSPSM_SIGN
: return D3DSPSM_SIGN
;
391 case BWRITERSPSM_SIGNNEG
: return D3DSPSM_SIGNNEG
;
392 case BWRITERSPSM_COMP
: return D3DSPSM_COMP
;
393 case BWRITERSPSM_X2
: return D3DSPSM_X2
;
394 case BWRITERSPSM_X2NEG
: return D3DSPSM_X2NEG
;
395 case BWRITERSPSM_DZ
: return D3DSPSM_DZ
;
396 case BWRITERSPSM_DW
: return D3DSPSM_DW
;
397 case BWRITERSPSM_ABS
: return D3DSPSM_ABS
;
398 case BWRITERSPSM_ABSNEG
: return D3DSPSM_ABSNEG
;
399 case BWRITERSPSM_NOT
: return D3DSPSM_NOT
;
401 FIXME("Unhandled BWRITERSPSM token %#x.\n", bwriter_srcmod
);
406 static DWORD
d3d9_dstmod(DWORD bwriter_mod
)
410 if (bwriter_mod
& BWRITERSPDM_SATURATE
) ret
|= D3DSPDM_SATURATE
;
411 if (bwriter_mod
& BWRITERSPDM_PARTIALPRECISION
) ret
|= D3DSPDM_PARTIALPRECISION
;
412 if (bwriter_mod
& BWRITERSPDM_MSAMPCENTROID
) ret
|= D3DSPDM_MSAMPCENTROID
;
417 static DWORD
d3d9_comparetype(DWORD asmshader_comparetype
)
419 switch (asmshader_comparetype
)
421 case BWRITER_COMPARISON_GT
: return D3DSPC_GT
;
422 case BWRITER_COMPARISON_EQ
: return D3DSPC_EQ
;
423 case BWRITER_COMPARISON_GE
: return D3DSPC_GE
;
424 case BWRITER_COMPARISON_LT
: return D3DSPC_LT
;
425 case BWRITER_COMPARISON_NE
: return D3DSPC_NE
;
426 case BWRITER_COMPARISON_LE
: return D3DSPC_LE
;
428 FIXME("Unexpected BWRITER_COMPARISON type %#x.\n", asmshader_comparetype
);
433 static DWORD
d3d9_sampler(DWORD bwriter_sampler
)
435 if (bwriter_sampler
== BWRITERSTT_UNKNOWN
) return D3DSTT_UNKNOWN
;
436 if (bwriter_sampler
== BWRITERSTT_1D
) return D3DSTT_1D
;
437 if (bwriter_sampler
== BWRITERSTT_2D
) return D3DSTT_2D
;
438 if (bwriter_sampler
== BWRITERSTT_CUBE
) return D3DSTT_CUBE
;
439 if (bwriter_sampler
== BWRITERSTT_VOLUME
) return D3DSTT_VOLUME
;
440 FIXME("Unexpected BWRITERSAMPLER_TEXTURE_TYPE type %#x.\n", bwriter_sampler
);
445 static DWORD
d3d9_register(DWORD bwriter_register
)
447 if (bwriter_register
== BWRITERSPR_TEMP
) return D3DSPR_TEMP
;
448 if (bwriter_register
== BWRITERSPR_INPUT
) return D3DSPR_INPUT
;
449 if (bwriter_register
== BWRITERSPR_CONST
) return D3DSPR_CONST
;
450 if (bwriter_register
== BWRITERSPR_ADDR
) return D3DSPR_ADDR
;
451 if (bwriter_register
== BWRITERSPR_TEXTURE
) return D3DSPR_TEXTURE
;
452 if (bwriter_register
== BWRITERSPR_RASTOUT
) return D3DSPR_RASTOUT
;
453 if (bwriter_register
== BWRITERSPR_ATTROUT
) return D3DSPR_ATTROUT
;
454 if (bwriter_register
== BWRITERSPR_TEXCRDOUT
) return D3DSPR_TEXCRDOUT
;
455 if (bwriter_register
== BWRITERSPR_OUTPUT
) return D3DSPR_OUTPUT
;
456 if (bwriter_register
== BWRITERSPR_CONSTINT
) return D3DSPR_CONSTINT
;
457 if (bwriter_register
== BWRITERSPR_COLOROUT
) return D3DSPR_COLOROUT
;
458 if (bwriter_register
== BWRITERSPR_DEPTHOUT
) return D3DSPR_DEPTHOUT
;
459 if (bwriter_register
== BWRITERSPR_SAMPLER
) return D3DSPR_SAMPLER
;
460 if (bwriter_register
== BWRITERSPR_CONSTBOOL
) return D3DSPR_CONSTBOOL
;
461 if (bwriter_register
== BWRITERSPR_LOOP
) return D3DSPR_LOOP
;
462 if (bwriter_register
== BWRITERSPR_MISCTYPE
) return D3DSPR_MISCTYPE
;
463 if (bwriter_register
== BWRITERSPR_LABEL
) return D3DSPR_LABEL
;
464 if (bwriter_register
== BWRITERSPR_PREDICATE
) return D3DSPR_PREDICATE
;
466 FIXME("Unexpected BWRITERSPR %#x.\n", bwriter_register
);
470 static DWORD
d3d9_opcode(DWORD bwriter_opcode
)
472 switch (bwriter_opcode
)
474 case BWRITERSIO_NOP
: return D3DSIO_NOP
;
475 case BWRITERSIO_MOV
: return D3DSIO_MOV
;
476 case BWRITERSIO_ADD
: return D3DSIO_ADD
;
477 case BWRITERSIO_SUB
: return D3DSIO_SUB
;
478 case BWRITERSIO_MAD
: return D3DSIO_MAD
;
479 case BWRITERSIO_MUL
: return D3DSIO_MUL
;
480 case BWRITERSIO_RCP
: return D3DSIO_RCP
;
481 case BWRITERSIO_RSQ
: return D3DSIO_RSQ
;
482 case BWRITERSIO_DP3
: return D3DSIO_DP3
;
483 case BWRITERSIO_DP4
: return D3DSIO_DP4
;
484 case BWRITERSIO_MIN
: return D3DSIO_MIN
;
485 case BWRITERSIO_MAX
: return D3DSIO_MAX
;
486 case BWRITERSIO_SLT
: return D3DSIO_SLT
;
487 case BWRITERSIO_SGE
: return D3DSIO_SGE
;
488 case BWRITERSIO_EXP
: return D3DSIO_EXP
;
489 case BWRITERSIO_LOG
: return D3DSIO_LOG
;
490 case BWRITERSIO_LIT
: return D3DSIO_LIT
;
491 case BWRITERSIO_DST
: return D3DSIO_DST
;
492 case BWRITERSIO_LRP
: return D3DSIO_LRP
;
493 case BWRITERSIO_FRC
: return D3DSIO_FRC
;
494 case BWRITERSIO_M4x4
: return D3DSIO_M4x4
;
495 case BWRITERSIO_M4x3
: return D3DSIO_M4x3
;
496 case BWRITERSIO_M3x4
: return D3DSIO_M3x4
;
497 case BWRITERSIO_M3x3
: return D3DSIO_M3x3
;
498 case BWRITERSIO_M3x2
: return D3DSIO_M3x2
;
499 case BWRITERSIO_CALL
: return D3DSIO_CALL
;
500 case BWRITERSIO_CALLNZ
: return D3DSIO_CALLNZ
;
501 case BWRITERSIO_LOOP
: return D3DSIO_LOOP
;
502 case BWRITERSIO_RET
: return D3DSIO_RET
;
503 case BWRITERSIO_ENDLOOP
: return D3DSIO_ENDLOOP
;
504 case BWRITERSIO_LABEL
: return D3DSIO_LABEL
;
505 case BWRITERSIO_DCL
: return D3DSIO_DCL
;
506 case BWRITERSIO_POW
: return D3DSIO_POW
;
507 case BWRITERSIO_CRS
: return D3DSIO_CRS
;
508 case BWRITERSIO_SGN
: return D3DSIO_SGN
;
509 case BWRITERSIO_ABS
: return D3DSIO_ABS
;
510 case BWRITERSIO_NRM
: return D3DSIO_NRM
;
511 case BWRITERSIO_SINCOS
: return D3DSIO_SINCOS
;
512 case BWRITERSIO_REP
: return D3DSIO_REP
;
513 case BWRITERSIO_ENDREP
: return D3DSIO_ENDREP
;
514 case BWRITERSIO_IF
: return D3DSIO_IF
;
515 case BWRITERSIO_IFC
: return D3DSIO_IFC
;
516 case BWRITERSIO_ELSE
: return D3DSIO_ELSE
;
517 case BWRITERSIO_ENDIF
: return D3DSIO_ENDIF
;
518 case BWRITERSIO_BREAK
: return D3DSIO_BREAK
;
519 case BWRITERSIO_BREAKC
: return D3DSIO_BREAKC
;
520 case BWRITERSIO_MOVA
: return D3DSIO_MOVA
;
521 case BWRITERSIO_DEFB
: return D3DSIO_DEFB
;
522 case BWRITERSIO_DEFI
: return D3DSIO_DEFI
;
524 case BWRITERSIO_TEXCOORD
: return D3DSIO_TEXCOORD
;
525 case BWRITERSIO_TEXKILL
: return D3DSIO_TEXKILL
;
526 case BWRITERSIO_TEX
: return D3DSIO_TEX
;
527 case BWRITERSIO_TEXBEM
: return D3DSIO_TEXBEM
;
528 case BWRITERSIO_TEXBEML
: return D3DSIO_TEXBEML
;
529 case BWRITERSIO_TEXREG2AR
: return D3DSIO_TEXREG2AR
;
530 case BWRITERSIO_TEXREG2GB
: return D3DSIO_TEXREG2GB
;
531 case BWRITERSIO_TEXM3x2PAD
: return D3DSIO_TEXM3x2PAD
;
532 case BWRITERSIO_TEXM3x2TEX
: return D3DSIO_TEXM3x2TEX
;
533 case BWRITERSIO_TEXM3x3PAD
: return D3DSIO_TEXM3x3PAD
;
534 case BWRITERSIO_TEXM3x3TEX
: return D3DSIO_TEXM3x3TEX
;
535 case BWRITERSIO_TEXM3x3SPEC
: return D3DSIO_TEXM3x3SPEC
;
536 case BWRITERSIO_TEXM3x3VSPEC
:return D3DSIO_TEXM3x3VSPEC
;
537 case BWRITERSIO_EXPP
: return D3DSIO_EXPP
;
538 case BWRITERSIO_LOGP
: return D3DSIO_LOGP
;
539 case BWRITERSIO_CND
: return D3DSIO_CND
;
540 case BWRITERSIO_DEF
: return D3DSIO_DEF
;
541 case BWRITERSIO_TEXREG2RGB
: return D3DSIO_TEXREG2RGB
;
542 case BWRITERSIO_TEXDP3TEX
: return D3DSIO_TEXDP3TEX
;
543 case BWRITERSIO_TEXM3x2DEPTH
:return D3DSIO_TEXM3x2DEPTH
;
544 case BWRITERSIO_TEXDP3
: return D3DSIO_TEXDP3
;
545 case BWRITERSIO_TEXM3x3
: return D3DSIO_TEXM3x3
;
546 case BWRITERSIO_TEXDEPTH
: return D3DSIO_TEXDEPTH
;
547 case BWRITERSIO_CMP
: return D3DSIO_CMP
;
548 case BWRITERSIO_BEM
: return D3DSIO_BEM
;
549 case BWRITERSIO_DP2ADD
: return D3DSIO_DP2ADD
;
550 case BWRITERSIO_DSX
: return D3DSIO_DSX
;
551 case BWRITERSIO_DSY
: return D3DSIO_DSY
;
552 case BWRITERSIO_TEXLDD
: return D3DSIO_TEXLDD
;
553 case BWRITERSIO_SETP
: return D3DSIO_SETP
;
554 case BWRITERSIO_TEXLDL
: return D3DSIO_TEXLDL
;
555 case BWRITERSIO_BREAKP
: return D3DSIO_BREAKP
;
557 case BWRITERSIO_PHASE
: return D3DSIO_PHASE
;
558 case BWRITERSIO_COMMENT
: return D3DSIO_COMMENT
;
559 case BWRITERSIO_END
: return D3DSIO_END
;
561 case BWRITERSIO_TEXLDP
: return D3DSIO_TEX
| D3DSI_TEXLD_PROJECT
;
562 case BWRITERSIO_TEXLDB
: return D3DSIO_TEX
| D3DSI_TEXLD_BIAS
;
565 FIXME("Unhandled BWRITERSIO token %#x.\n", bwriter_opcode
);
570 static DWORD
d3dsp_register( D3DSHADER_PARAM_REGISTER_TYPE type
, DWORD num
)
572 return ((type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
) |
573 ((type
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
) |
574 (num
& D3DSP_REGNUM_MASK
); /* No shift */
577 /******************************************************
578 * Implementation of the writer functions starts here *
579 ******************************************************/
580 static void write_declarations(struct bc_writer
*This
,
581 struct bytecode_buffer
*buffer
, BOOL len
,
582 const struct declaration
*decls
, unsigned int num
, DWORD type
) {
584 DWORD instr_dcl
= D3DSIO_DCL
;
586 struct shader_reg reg
;
588 ZeroMemory(®
, sizeof(reg
));
591 instr_dcl
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
594 for(i
= 0; i
< num
; i
++) {
595 if(decls
[i
].builtin
) continue;
597 /* Write the DCL instruction */
598 put_dword(buffer
, instr_dcl
);
600 /* Write the usage and index */
601 token
= (1u << 31); /* Bit 31 of non-instruction opcodes is 1 */
602 token
|= (decls
[i
].usage
<< D3DSP_DCL_USAGE_SHIFT
) & D3DSP_DCL_USAGE_MASK
;
603 token
|= (decls
[i
].usage_idx
<< D3DSP_DCL_USAGEINDEX_SHIFT
) & D3DSP_DCL_USAGEINDEX_MASK
;
604 put_dword(buffer
, token
);
606 /* Write the dest register */
608 reg
.regnum
= decls
[i
].regnum
;
609 reg
.u
.writemask
= decls
[i
].writemask
;
610 This
->funcs
->dstreg(This
, ®
, buffer
, 0, decls
[i
].mod
);
614 static void write_const(struct constant
**consts
, int num
, DWORD opcode
, DWORD reg_type
, struct bytecode_buffer
*buffer
, BOOL len
) {
616 DWORD instr_def
= opcode
;
617 const DWORD reg
= (1u << 31) | d3dsp_register( reg_type
, 0 ) | D3DSP_WRITEMASK_ALL
;
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 write_declarations(This
, buffer
, FALSE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
748 write_constF(shader
, buffer
, FALSE
);
751 static HRESULT
find_ps_builtin_semantics(struct bc_writer
*This
,
752 const struct bwriter_shader
*shader
,
755 DWORD usage
, usage_idx
, writemask
, regnum
;
757 This
->v_regnum
[0] = -1; This
->v_regnum
[1] = -1;
758 for(i
= 0; i
< 8; i
++) This
->t_regnum
[i
] = -1;
760 for(i
= 0; i
< shader
->num_inputs
; i
++) {
761 if(!shader
->inputs
[i
].builtin
) continue;
763 usage
= shader
->inputs
[i
].usage
;
764 usage_idx
= shader
->inputs
[i
].usage_idx
;
765 writemask
= shader
->inputs
[i
].writemask
;
766 regnum
= shader
->inputs
[i
].regnum
;
769 case BWRITERDECLUSAGE_COLOR
:
771 WARN("dcl_color%u not supported in sm 1 shaders\n", usage_idx
);
774 if(writemask
!= BWRITERSP_WRITEMASK_ALL
) {
775 WARN("Only WRITEMASK_ALL is supported on color in sm 1\n");
778 TRACE("v%u is v%u\n", regnum
, usage_idx
);
779 This
->v_regnum
[usage_idx
] = regnum
;
782 case BWRITERDECLUSAGE_TEXCOORD
:
783 if(usage_idx
> texcoords
) {
784 WARN("dcl_texcoord%u not supported in this shader version\n", usage_idx
);
787 if(writemask
!= (BWRITERSP_WRITEMASK_0
) &&
788 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
) &&
789 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
| BWRITERSP_WRITEMASK_2
) &&
790 writemask
!= (BWRITERSP_WRITEMASK_ALL
)) {
791 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
793 writemask
= BWRITERSP_WRITEMASK_ALL
;
795 TRACE("v%u is t%u\n", regnum
, usage_idx
);
796 This
->t_regnum
[usage_idx
] = regnum
;
800 WARN("Varying type %u is not supported in shader model 1.x\n", usage
);
808 static void ps_1_x_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
811 /* First check the constants and varyings, and complain if unsupported things are used */
812 if(shader
->num_ci
|| shader
->num_cb
) {
813 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
814 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
815 This
->state
= E_INVALIDARG
;
819 hr
= find_ps_builtin_semantics(This
, shader
, 4);
825 write_constF(shader
, buffer
, FALSE
);
828 static void ps_1_4_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
831 /* First check the constants and varyings, and complain if unsupported things are used */
832 if(shader
->num_ci
|| shader
->num_cb
) {
833 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
834 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
835 This
->state
= E_INVALIDARG
;
838 hr
= find_ps_builtin_semantics(This
, shader
, 6);
844 write_constF(shader
, buffer
, FALSE
);
847 static void end(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
848 put_dword(buffer
, D3DSIO_END
);
851 static DWORD
map_vs_output(struct bc_writer
*This
, DWORD regnum
, DWORD mask
, DWORD
*has_components
) {
854 *has_components
= TRUE
;
855 if(regnum
== This
->oPos_regnum
) {
856 return d3dsp_register( D3DSPR_RASTOUT
, D3DSRO_POSITION
);
858 if(regnum
== This
->oFog_regnum
&& mask
== This
->oFog_mask
) {
859 *has_components
= FALSE
;
860 return d3dsp_register( D3DSPR_RASTOUT
, D3DSRO_FOG
) | D3DSP_WRITEMASK_ALL
;
862 if(regnum
== This
->oPts_regnum
&& mask
== This
->oPts_mask
) {
863 *has_components
= FALSE
;
864 return d3dsp_register( D3DSPR_RASTOUT
, D3DSRO_POINT_SIZE
) | D3DSP_WRITEMASK_ALL
;
866 for(i
= 0; i
< 2; i
++) {
867 if(regnum
== This
->oD_regnum
[i
]) {
868 return d3dsp_register( D3DSPR_ATTROUT
, i
);
871 for(i
= 0; i
< 8; i
++) {
872 if(regnum
== This
->oT_regnum
[i
]) {
873 return d3dsp_register( D3DSPR_TEXCRDOUT
, i
);
877 /* The varying must be undeclared - if an unsupported varying was declared,
878 * the vs_find_builtin_varyings function would have caught it and this code
880 WARN("Undeclared varying %u\n", regnum
);
881 This
->state
= E_INVALIDARG
;
885 static void vs_12_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
886 struct bytecode_buffer
*buffer
,
887 DWORD shift
, DWORD mod
) {
888 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
892 WARN("Relative addressing not supported for destination registers\n");
893 This
->state
= E_INVALIDARG
;
898 case BWRITERSPR_OUTPUT
:
899 token
|= map_vs_output(This
, reg
->regnum
, reg
->u
.writemask
, &has_wmask
);
902 case BWRITERSPR_RASTOUT
:
903 case BWRITERSPR_ATTROUT
:
904 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
905 * but are unexpected. If we hit this path it might be due to an error.
907 FIXME("Unexpected register type %u\n", reg
->type
);
909 case BWRITERSPR_INPUT
:
910 case BWRITERSPR_TEMP
:
911 case BWRITERSPR_CONST
:
912 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
916 case BWRITERSPR_ADDR
:
917 if(reg
->regnum
!= 0) {
918 WARN("Only a0 exists\n");
919 This
->state
= E_INVALIDARG
;
922 token
|= d3dsp_register( D3DSPR_ADDR
, 0 );
926 case BWRITERSPR_PREDICATE
:
927 if(This
->version
!= BWRITERVS_VERSION(2, 1)){
928 WARN("Predicate register is allowed only in vs_2_x\n");
929 This
->state
= E_INVALIDARG
;
932 if(reg
->regnum
!= 0) {
933 WARN("Only predicate register p0 exists\n");
934 This
->state
= E_INVALIDARG
;
937 token
|= d3dsp_register( D3DSPR_PREDICATE
, 0 );
942 WARN("Invalid register type for 1.x-2.x vertex shader\n");
943 This
->state
= E_INVALIDARG
;
947 /* strictly speaking there are no modifiers in vs_2_0 and vs_1_x, but they can be written
948 * into the bytecode and since the compiler doesn't do such checks write them
949 * (the checks are done by the undocumented shader validator)
951 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
952 token
|= d3d9_dstmod(mod
);
955 token
|= d3d9_writemask(reg
->u
.writemask
);
957 put_dword(buffer
, token
);
960 static void vs_1_x_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
961 struct bytecode_buffer
*buffer
) {
962 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
967 case BWRITERSPR_OUTPUT
:
968 /* Map the swizzle to a writemask, the format expected
971 switch(reg
->u
.swizzle
) {
972 case BWRITERVS_SWIZZLE_X
:
973 component
= BWRITERSP_WRITEMASK_0
;
975 case BWRITERVS_SWIZZLE_Y
:
976 component
= BWRITERSP_WRITEMASK_1
;
978 case BWRITERVS_SWIZZLE_Z
:
979 component
= BWRITERSP_WRITEMASK_2
;
981 case BWRITERVS_SWIZZLE_W
:
982 component
= BWRITERSP_WRITEMASK_3
;
987 token
|= map_vs_output(This
, reg
->regnum
, component
, &has_swizzle
);
990 case BWRITERSPR_RASTOUT
:
991 case BWRITERSPR_ATTROUT
:
992 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
993 * but are unexpected. If we hit this path it might be due to an error.
995 FIXME("Unexpected register type %u\n", reg
->type
);
997 case BWRITERSPR_INPUT
:
998 case BWRITERSPR_TEMP
:
999 case BWRITERSPR_CONST
:
1000 case BWRITERSPR_ADDR
:
1001 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1003 if(reg
->rel_reg
->type
!= BWRITERSPR_ADDR
||
1004 reg
->rel_reg
->regnum
!= 0 ||
1005 reg
->rel_reg
->u
.swizzle
!= BWRITERVS_SWIZZLE_X
) {
1006 WARN("Relative addressing in vs_1_x is only allowed with a0.x\n");
1007 This
->state
= E_INVALIDARG
;
1010 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1015 WARN("Invalid register type for 1.x vshader\n");
1016 This
->state
= E_INVALIDARG
;
1020 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1022 token
|= d3d9_srcmod(reg
->srcmod
);
1023 put_dword(buffer
, token
);
1026 static void write_srcregs(struct bc_writer
*This
, const struct instruction
*instr
,
1027 struct bytecode_buffer
*buffer
){
1029 if(instr
->has_predicate
){
1030 This
->funcs
->srcreg(This
, &instr
->predicate
, buffer
);
1032 for(i
= 0; i
< instr
->num_srcs
; i
++){
1033 This
->funcs
->srcreg(This
, &instr
->src
[i
], buffer
);
1037 static DWORD
map_ps13_temp(struct bc_writer
*This
, const struct shader_reg
*reg
) {
1038 if(reg
->regnum
== T0_REG
) {
1039 return d3dsp_register( D3DSPR_TEXTURE
, 0 );
1040 } else if(reg
->regnum
== T1_REG
) {
1041 return d3dsp_register( D3DSPR_TEXTURE
, 1 );
1042 } else if(reg
->regnum
== T2_REG
) {
1043 return d3dsp_register( D3DSPR_TEXTURE
, 2 );
1044 } else if(reg
->regnum
== T3_REG
) {
1045 return d3dsp_register( D3DSPR_TEXTURE
, 3 );
1047 return d3dsp_register( D3DSPR_TEMP
, reg
->regnum
);
1051 static DWORD
map_ps_input(struct bc_writer
*This
,
1052 const struct shader_reg
*reg
) {
1054 /* Map color interpolators */
1055 for(i
= 0; i
< 2; i
++) {
1056 if(reg
->regnum
== This
->v_regnum
[i
]) {
1057 return d3dsp_register( D3DSPR_INPUT
, i
);
1060 for(i
= 0; i
< 8; i
++) {
1061 if(reg
->regnum
== This
->t_regnum
[i
]) {
1062 return d3dsp_register( D3DSPR_TEXTURE
, i
);
1066 WARN("Invalid ps 1/2 varying\n");
1067 This
->state
= E_INVALIDARG
;
1071 static void ps_1_0123_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1072 struct bytecode_buffer
*buffer
) {
1073 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1075 WARN("Relative addressing not supported in <= ps_3_0\n");
1076 This
->state
= E_INVALIDARG
;
1081 case BWRITERSPR_INPUT
:
1082 token
|= map_ps_input(This
, reg
);
1085 /* Take care about the texture temporaries. There's a problem: They aren't
1086 * declared anywhere, so we can only hardcode the values that are used
1087 * to map ps_1_3 shaders to the common shader structure
1089 case BWRITERSPR_TEMP
:
1090 token
|= map_ps13_temp(This
, reg
);
1093 case BWRITERSPR_CONST
: /* Can be mapped 1:1 */
1094 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1098 WARN("Invalid register type for <= ps_1_3 shader\n");
1099 This
->state
= E_INVALIDARG
;
1103 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1105 if(reg
->srcmod
== BWRITERSPSM_DZ
|| reg
->srcmod
== BWRITERSPSM_DW
||
1106 reg
->srcmod
== BWRITERSPSM_ABS
|| reg
->srcmod
== BWRITERSPSM_ABSNEG
||
1107 reg
->srcmod
== BWRITERSPSM_NOT
) {
1108 WARN("Invalid source modifier %u for <= ps_1_3\n", reg
->srcmod
);
1109 This
->state
= E_INVALIDARG
;
1112 token
|= d3d9_srcmod(reg
->srcmod
);
1113 put_dword(buffer
, token
);
1116 static void ps_1_0123_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1117 struct bytecode_buffer
*buffer
,
1118 DWORD shift
, DWORD mod
) {
1119 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1122 WARN("Relative addressing not supported for destination registers\n");
1123 This
->state
= E_INVALIDARG
;
1128 case BWRITERSPR_TEMP
:
1129 token
|= map_ps13_temp(This
, reg
);
1132 /* texkill uses the input register as a destination parameter */
1133 case BWRITERSPR_INPUT
:
1134 token
|= map_ps_input(This
, reg
);
1138 WARN("Invalid dest register type for 1.x pshader\n");
1139 This
->state
= E_INVALIDARG
;
1143 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1144 token
|= d3d9_dstmod(mod
);
1146 token
|= d3d9_writemask(reg
->u
.writemask
);
1147 put_dword(buffer
, token
);
1150 /* The length of an instruction consists of the destination register (if any),
1151 * the number of source registers, the number of address registers used for
1152 * indirect addressing, and optionally the predicate register
1154 static DWORD
instrlen(const struct instruction
*instr
, unsigned int srcs
, unsigned int dsts
) {
1156 DWORD ret
= srcs
+ dsts
+ (instr
->has_predicate
? 1 : 0);
1159 if(instr
->dst
.rel_reg
) ret
++;
1161 for(i
= 0; i
< srcs
; i
++) {
1162 if(instr
->src
[i
].rel_reg
) ret
++;
1167 static void sm_1_x_opcode(struct bc_writer
*This
,
1168 const struct instruction
*instr
,
1169 DWORD token
, struct bytecode_buffer
*buffer
) {
1170 /* In sm_1_x instruction length isn't encoded */
1172 token
|= D3DSI_COISSUE
;
1174 put_dword(buffer
, token
);
1177 static void instr_handler(struct bc_writer
*This
,
1178 const struct instruction
*instr
,
1179 struct bytecode_buffer
*buffer
) {
1180 DWORD token
= d3d9_opcode(instr
->opcode
);
1182 This
->funcs
->opcode(This
, instr
, token
, buffer
);
1183 if(instr
->has_dst
) This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1184 write_srcregs(This
, instr
, buffer
);
1187 static const struct instr_handler_table vs_1_x_handlers
[] = {
1188 {BWRITERSIO_ADD
, instr_handler
},
1189 {BWRITERSIO_NOP
, instr_handler
},
1190 {BWRITERSIO_MOV
, instr_handler
},
1191 {BWRITERSIO_SUB
, instr_handler
},
1192 {BWRITERSIO_MAD
, instr_handler
},
1193 {BWRITERSIO_MUL
, instr_handler
},
1194 {BWRITERSIO_RCP
, instr_handler
},
1195 {BWRITERSIO_RSQ
, instr_handler
},
1196 {BWRITERSIO_DP3
, instr_handler
},
1197 {BWRITERSIO_DP4
, instr_handler
},
1198 {BWRITERSIO_MIN
, instr_handler
},
1199 {BWRITERSIO_MAX
, instr_handler
},
1200 {BWRITERSIO_SLT
, instr_handler
},
1201 {BWRITERSIO_SGE
, instr_handler
},
1202 {BWRITERSIO_EXP
, instr_handler
},
1203 {BWRITERSIO_LOG
, instr_handler
},
1204 {BWRITERSIO_EXPP
, instr_handler
},
1205 {BWRITERSIO_LOGP
, instr_handler
},
1206 {BWRITERSIO_DST
, instr_handler
},
1207 {BWRITERSIO_FRC
, instr_handler
},
1208 {BWRITERSIO_M4x4
, instr_handler
},
1209 {BWRITERSIO_M4x3
, instr_handler
},
1210 {BWRITERSIO_M3x4
, instr_handler
},
1211 {BWRITERSIO_M3x3
, instr_handler
},
1212 {BWRITERSIO_M3x2
, instr_handler
},
1213 {BWRITERSIO_LIT
, instr_handler
},
1215 {BWRITERSIO_END
, NULL
}, /* Sentinel value, it signals
1216 the end of the list */
1219 static const struct bytecode_backend vs_1_x_backend
= {
1228 static void instr_ps_1_0123_texld(struct bc_writer
*This
,
1229 const struct instruction
*instr
,
1230 struct bytecode_buffer
*buffer
) {
1232 struct shader_reg reg
;
1235 if(instr
->src
[1].type
!= BWRITERSPR_SAMPLER
||
1236 instr
->src
[1].regnum
> 3) {
1237 WARN("Unsupported sampler type %u regnum %u\n",
1238 instr
->src
[1].type
, instr
->src
[1].regnum
);
1239 This
->state
= E_INVALIDARG
;
1241 } else if(instr
->dst
.type
!= BWRITERSPR_TEMP
) {
1242 WARN("Can only sample into a temp register\n");
1243 This
->state
= E_INVALIDARG
;
1247 idx
= instr
->src
[1].regnum
;
1248 if((idx
== 0 && instr
->dst
.regnum
!= T0_REG
) ||
1249 (idx
== 1 && instr
->dst
.regnum
!= T1_REG
) ||
1250 (idx
== 2 && instr
->dst
.regnum
!= T2_REG
) ||
1251 (idx
== 3 && instr
->dst
.regnum
!= T3_REG
)) {
1252 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_x\n",
1253 idx
, instr
->dst
.regnum
);
1254 This
->state
= E_INVALIDARG
;
1257 if(instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1258 /* A simple non-dependent read tex instruction */
1259 if(instr
->src
[0].regnum
!= This
->t_regnum
[idx
]) {
1260 WARN("Cannot sample from s%u with texture address data from interpolator %u\n",
1261 idx
, instr
->src
[0].regnum
);
1262 This
->state
= E_INVALIDARG
;
1265 This
->funcs
->opcode(This
, instr
, D3DSIO_TEX
& D3DSI_OPCODE_MASK
, buffer
);
1267 /* map the temp dstreg to the ps_1_3 texture temporary register */
1268 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1269 } else if(instr
->src
[0].type
== BWRITERSPR_TEMP
) {
1271 swizzlemask
= (3 << BWRITERVS_SWIZZLE_SHIFT
) |
1272 (3 << (BWRITERVS_SWIZZLE_SHIFT
+ 2)) |
1273 (3 << (BWRITERVS_SWIZZLE_SHIFT
+ 4));
1274 if((instr
->src
[0].u
.swizzle
& swizzlemask
) == (BWRITERVS_X_X
| BWRITERVS_Y_Y
| BWRITERVS_Z_Z
)) {
1275 TRACE("writing texreg2rgb\n");
1276 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2RGB
& D3DSI_OPCODE_MASK
, buffer
);
1277 } else if(instr
->src
[0].u
.swizzle
== (BWRITERVS_X_W
| BWRITERVS_Y_X
| BWRITERVS_Z_X
| BWRITERVS_W_X
)) {
1278 TRACE("writing texreg2ar\n");
1279 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2AR
& D3DSI_OPCODE_MASK
, buffer
);
1280 } else if(instr
->src
[0].u
.swizzle
== (BWRITERVS_X_Y
| BWRITERVS_Y_Z
| BWRITERVS_Z_Z
| BWRITERVS_W_Z
)) {
1281 TRACE("writing texreg2gb\n");
1282 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2GB
& D3DSI_OPCODE_MASK
, buffer
);
1284 WARN("Unsupported src addr swizzle in dependent texld: 0x%08x\n", instr
->src
[0].u
.swizzle
);
1285 This
->state
= E_INVALIDARG
;
1289 /* Dst and src reg can be mapped normally. Both registers are temporary registers in the
1290 * source shader and have to be mapped to the temporary form of the texture registers. However,
1291 * the src reg doesn't have a swizzle
1293 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1294 reg
= instr
->src
[0];
1295 reg
.u
.swizzle
= BWRITERVS_NOSWIZZLE
;
1296 This
->funcs
->srcreg(This
, ®
, buffer
);
1298 WARN("Invalid address data source register\n");
1299 This
->state
= E_INVALIDARG
;
1304 static void instr_ps_1_0123_mov(struct bc_writer
*This
,
1305 const struct instruction
*instr
,
1306 struct bytecode_buffer
*buffer
) {
1307 DWORD token
= D3DSIO_MOV
& D3DSI_OPCODE_MASK
;
1309 if(instr
->dst
.type
== BWRITERSPR_TEMP
&& instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1310 if((instr
->dst
.regnum
== T0_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[0]) ||
1311 (instr
->dst
.regnum
== T1_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[1]) ||
1312 (instr
->dst
.regnum
== T2_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[2]) ||
1313 (instr
->dst
.regnum
== T3_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[3])) {
1314 if(instr
->dstmod
& BWRITERSPDM_SATURATE
) {
1315 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXCOORD
& D3DSI_OPCODE_MASK
, buffer
);
1316 /* Remove the SATURATE flag, it's implicit to the instruction */
1317 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
& (~BWRITERSPDM_SATURATE
));
1320 WARN("A varying -> temp copy is only supported with the SATURATE modifier in <=ps_1_3\n");
1321 This
->state
= E_INVALIDARG
;
1324 } else if(instr
->src
[0].regnum
== This
->v_regnum
[0] ||
1325 instr
->src
[0].regnum
== This
->v_regnum
[1]) {
1326 /* Handled by the normal mov below. Just drop out of the if condition */
1328 WARN("Unsupported varying -> temp mov in <= ps_1_3\n");
1329 This
->state
= E_INVALIDARG
;
1334 This
->funcs
->opcode(This
, instr
, token
, buffer
);
1335 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1336 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1339 static const struct instr_handler_table ps_1_0123_handlers
[] = {
1340 {BWRITERSIO_ADD
, instr_handler
},
1341 {BWRITERSIO_NOP
, instr_handler
},
1342 {BWRITERSIO_MOV
, instr_ps_1_0123_mov
},
1343 {BWRITERSIO_SUB
, instr_handler
},
1344 {BWRITERSIO_MAD
, instr_handler
},
1345 {BWRITERSIO_MUL
, instr_handler
},
1346 {BWRITERSIO_DP3
, instr_handler
},
1347 {BWRITERSIO_DP4
, instr_handler
},
1348 {BWRITERSIO_LRP
, instr_handler
},
1350 /* pshader instructions */
1351 {BWRITERSIO_CND
, instr_handler
},
1352 {BWRITERSIO_CMP
, instr_handler
},
1353 {BWRITERSIO_TEXKILL
, instr_handler
},
1354 {BWRITERSIO_TEX
, instr_ps_1_0123_texld
},
1355 {BWRITERSIO_TEXBEM
, instr_handler
},
1356 {BWRITERSIO_TEXBEML
, instr_handler
},
1357 {BWRITERSIO_TEXM3x2PAD
, instr_handler
},
1358 {BWRITERSIO_TEXM3x3PAD
, instr_handler
},
1359 {BWRITERSIO_TEXM3x3SPEC
, instr_handler
},
1360 {BWRITERSIO_TEXM3x3VSPEC
, instr_handler
},
1361 {BWRITERSIO_TEXM3x3TEX
, instr_handler
},
1362 {BWRITERSIO_TEXM3x3
, instr_handler
},
1363 {BWRITERSIO_TEXM3x2DEPTH
, instr_handler
},
1364 {BWRITERSIO_TEXM3x2TEX
, instr_handler
},
1365 {BWRITERSIO_TEXDP3
, instr_handler
},
1366 {BWRITERSIO_TEXDP3TEX
, instr_handler
},
1367 {BWRITERSIO_END
, NULL
},
1370 static const struct bytecode_backend ps_1_0123_backend
= {
1379 static void ps_1_4_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1380 struct bytecode_buffer
*buffer
) {
1381 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1383 WARN("Relative addressing not supported in <= ps_3_0\n");
1384 This
->state
= E_INVALIDARG
;
1389 case BWRITERSPR_INPUT
:
1390 token
|= map_ps_input(This
, reg
);
1393 /* Can be mapped 1:1 */
1394 case BWRITERSPR_TEMP
:
1395 case BWRITERSPR_CONST
:
1396 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1400 WARN("Invalid register type for ps_1_4 shader\n");
1401 This
->state
= E_INVALIDARG
;
1405 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1407 if(reg
->srcmod
== BWRITERSPSM_ABS
|| reg
->srcmod
== BWRITERSPSM_ABSNEG
||
1408 reg
->srcmod
== BWRITERSPSM_NOT
) {
1409 WARN("Invalid source modifier %u for ps_1_4\n", reg
->srcmod
);
1410 This
->state
= E_INVALIDARG
;
1413 token
|= d3d9_srcmod(reg
->srcmod
);
1414 put_dword(buffer
, token
);
1417 static void ps_1_4_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1418 struct bytecode_buffer
*buffer
,
1419 DWORD shift
, DWORD mod
) {
1420 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1423 WARN("Relative addressing not supported for destination registers\n");
1424 This
->state
= E_INVALIDARG
;
1429 case BWRITERSPR_TEMP
: /* 1:1 mapping */
1430 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1434 case BWRITERSPR_INPUT
:
1435 token
|= map_ps_input(This
, reg
);
1439 WARN("Invalid dest register type for 1.x pshader\n");
1440 This
->state
= E_INVALIDARG
;
1444 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1445 token
|= d3d9_dstmod(mod
);
1447 token
|= d3d9_writemask(reg
->u
.writemask
);
1448 put_dword(buffer
, token
);
1451 static void instr_ps_1_4_mov(struct bc_writer
*This
,
1452 const struct instruction
*instr
,
1453 struct bytecode_buffer
*buffer
) {
1454 DWORD token
= D3DSIO_MOV
& D3DSI_OPCODE_MASK
;
1456 if(instr
->dst
.type
== BWRITERSPR_TEMP
&& instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1457 if(instr
->src
[0].regnum
== This
->t_regnum
[0] ||
1458 instr
->src
[0].regnum
== This
->t_regnum
[1] ||
1459 instr
->src
[0].regnum
== This
->t_regnum
[2] ||
1460 instr
->src
[0].regnum
== This
->t_regnum
[3] ||
1461 instr
->src
[0].regnum
== This
->t_regnum
[4] ||
1462 instr
->src
[0].regnum
== This
->t_regnum
[5]) {
1463 /* Similar to a regular mov, but a different opcode */
1464 token
= D3DSIO_TEXCOORD
& D3DSI_OPCODE_MASK
;
1465 } else if(instr
->src
[0].regnum
== This
->v_regnum
[0] ||
1466 instr
->src
[0].regnum
== This
->v_regnum
[1]) {
1467 /* Handled by the normal mov below. Just drop out of the if condition */
1469 WARN("Unsupported varying -> temp mov in ps_1_4\n");
1470 This
->state
= E_INVALIDARG
;
1475 This
->funcs
->opcode(This
, instr
, token
, buffer
);
1476 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1477 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1480 static void instr_ps_1_4_texld(struct bc_writer
*This
,
1481 const struct instruction
*instr
,
1482 struct bytecode_buffer
*buffer
) {
1483 if(instr
->src
[1].type
!= BWRITERSPR_SAMPLER
||
1484 instr
->src
[1].regnum
> 5) {
1485 WARN("Unsupported sampler type %u regnum %u\n",
1486 instr
->src
[1].type
, instr
->src
[1].regnum
);
1487 This
->state
= E_INVALIDARG
;
1489 } else if(instr
->dst
.type
!= BWRITERSPR_TEMP
) {
1490 WARN("Can only sample into a temp register\n");
1491 This
->state
= E_INVALIDARG
;
1495 if(instr
->src
[1].regnum
!= instr
->dst
.regnum
) {
1496 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_4\n",
1497 instr
->src
[1].regnum
, instr
->dst
.regnum
);
1498 This
->state
= E_INVALIDARG
;
1502 This
->funcs
->opcode(This
, instr
, D3DSIO_TEX
& D3DSI_OPCODE_MASK
, buffer
);
1503 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1504 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1507 static const struct instr_handler_table ps_1_4_handlers
[] = {
1508 {BWRITERSIO_ADD
, instr_handler
},
1509 {BWRITERSIO_NOP
, instr_handler
},
1510 {BWRITERSIO_MOV
, instr_ps_1_4_mov
},
1511 {BWRITERSIO_SUB
, instr_handler
},
1512 {BWRITERSIO_MAD
, instr_handler
},
1513 {BWRITERSIO_MUL
, instr_handler
},
1514 {BWRITERSIO_DP3
, instr_handler
},
1515 {BWRITERSIO_DP4
, instr_handler
},
1516 {BWRITERSIO_LRP
, instr_handler
},
1518 /* pshader instructions */
1519 {BWRITERSIO_CND
, instr_handler
},
1520 {BWRITERSIO_CMP
, instr_handler
},
1521 {BWRITERSIO_TEXKILL
, instr_handler
},
1522 {BWRITERSIO_TEX
, instr_ps_1_4_texld
},
1523 {BWRITERSIO_TEXDEPTH
, instr_handler
},
1524 {BWRITERSIO_BEM
, instr_handler
},
1526 {BWRITERSIO_PHASE
, instr_handler
},
1527 {BWRITERSIO_END
, NULL
},
1530 static const struct bytecode_backend ps_1_4_backend
= {
1539 static void write_constB(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
1540 write_const(shader
->constB
, shader
->num_cb
, D3DSIO_DEFB
, D3DSPR_CONSTBOOL
, buffer
, len
);
1543 static void write_constI(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
1544 write_const(shader
->constI
, shader
->num_ci
, D3DSIO_DEFI
, D3DSPR_CONSTINT
, buffer
, len
);
1547 static void vs_2_header(struct bc_writer
*This
,
1548 const struct bwriter_shader
*shader
,
1549 struct bytecode_buffer
*buffer
) {
1552 hr
= vs_find_builtin_varyings(This
, shader
);
1558 write_declarations(This
, buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
1559 write_constF(shader
, buffer
, TRUE
);
1560 write_constB(shader
, buffer
, TRUE
);
1561 write_constI(shader
, buffer
, TRUE
);
1564 static void vs_2_srcreg(struct bc_writer
*This
,
1565 const struct shader_reg
*reg
,
1566 struct bytecode_buffer
*buffer
) {
1567 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1573 case BWRITERSPR_OUTPUT
:
1574 /* Map the swizzle to a writemask, the format expected
1577 switch(reg
->u
.swizzle
) {
1578 case BWRITERVS_SWIZZLE_X
:
1579 component
= BWRITERSP_WRITEMASK_0
;
1581 case BWRITERVS_SWIZZLE_Y
:
1582 component
= BWRITERSP_WRITEMASK_1
;
1584 case BWRITERVS_SWIZZLE_Z
:
1585 component
= BWRITERSP_WRITEMASK_2
;
1587 case BWRITERVS_SWIZZLE_W
:
1588 component
= BWRITERSP_WRITEMASK_3
;
1593 token
|= map_vs_output(This
, reg
->regnum
, component
, &has_swizzle
);
1596 case BWRITERSPR_RASTOUT
:
1597 case BWRITERSPR_ATTROUT
:
1598 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1599 * but are unexpected. If we hit this path it might be due to an error.
1601 FIXME("Unexpected register type %u\n", reg
->type
);
1603 case BWRITERSPR_INPUT
:
1604 case BWRITERSPR_TEMP
:
1605 case BWRITERSPR_CONST
:
1606 case BWRITERSPR_ADDR
:
1607 case BWRITERSPR_CONSTINT
:
1608 case BWRITERSPR_CONSTBOOL
:
1609 case BWRITERSPR_LABEL
:
1610 d3d9reg
= d3d9_register(reg
->type
);
1611 token
|= d3dsp_register( d3d9reg
, reg
->regnum
);
1614 case BWRITERSPR_LOOP
:
1615 if(reg
->regnum
!= 0) {
1616 WARN("Only regnum 0 is supported for the loop index register in vs_2_0\n");
1617 This
->state
= E_INVALIDARG
;
1620 token
|= d3dsp_register( D3DSPR_LOOP
, 0 );
1623 case BWRITERSPR_PREDICATE
:
1624 if(This
->version
!= BWRITERVS_VERSION(2, 1)){
1625 WARN("Predicate register is allowed only in vs_2_x\n");
1626 This
->state
= E_INVALIDARG
;
1629 if(reg
->regnum
> 0) {
1630 WARN("Only predicate register 0 is supported\n");
1631 This
->state
= E_INVALIDARG
;
1634 token
|= d3dsp_register( D3DSPR_PREDICATE
, 0 );
1638 WARN("Invalid register type for 2.0 vshader\n");
1639 This
->state
= E_INVALIDARG
;
1643 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1645 token
|= d3d9_srcmod(reg
->srcmod
);
1648 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1650 put_dword(buffer
, token
);
1652 /* vs_2_0 and newer write the register containing the index explicitly in the
1655 if(token
& D3DVS_ADDRMODE_RELATIVE
)
1656 vs_2_srcreg(This
, reg
->rel_reg
, buffer
);
1659 static void sm_2_opcode(struct bc_writer
*This
,
1660 const struct instruction
*instr
,
1661 DWORD token
, struct bytecode_buffer
*buffer
) {
1662 /* From sm 2 onwards instruction length is encoded in the opcode field */
1663 int dsts
= instr
->has_dst
? 1 : 0;
1664 token
|= instrlen(instr
, instr
->num_srcs
, dsts
) << D3DSI_INSTLENGTH_SHIFT
;
1666 token
|= (d3d9_comparetype(instr
->comptype
) << 16) & (0xf << 16);
1667 if(instr
->has_predicate
)
1668 token
|= D3DSHADER_INSTRUCTION_PREDICATED
;
1669 put_dword(buffer
,token
);
1672 static const struct instr_handler_table vs_2_0_handlers
[] = {
1673 {BWRITERSIO_ADD
, instr_handler
},
1674 {BWRITERSIO_NOP
, instr_handler
},
1675 {BWRITERSIO_MOV
, instr_handler
},
1676 {BWRITERSIO_SUB
, instr_handler
},
1677 {BWRITERSIO_MAD
, instr_handler
},
1678 {BWRITERSIO_MUL
, instr_handler
},
1679 {BWRITERSIO_RCP
, instr_handler
},
1680 {BWRITERSIO_RSQ
, instr_handler
},
1681 {BWRITERSIO_DP3
, instr_handler
},
1682 {BWRITERSIO_DP4
, instr_handler
},
1683 {BWRITERSIO_MIN
, instr_handler
},
1684 {BWRITERSIO_MAX
, instr_handler
},
1685 {BWRITERSIO_SLT
, instr_handler
},
1686 {BWRITERSIO_SGE
, instr_handler
},
1687 {BWRITERSIO_ABS
, instr_handler
},
1688 {BWRITERSIO_EXP
, instr_handler
},
1689 {BWRITERSIO_LOG
, instr_handler
},
1690 {BWRITERSIO_EXPP
, instr_handler
},
1691 {BWRITERSIO_LOGP
, instr_handler
},
1692 {BWRITERSIO_DST
, instr_handler
},
1693 {BWRITERSIO_LRP
, instr_handler
},
1694 {BWRITERSIO_FRC
, instr_handler
},
1695 {BWRITERSIO_CRS
, instr_handler
},
1696 {BWRITERSIO_SGN
, instr_handler
},
1697 {BWRITERSIO_NRM
, instr_handler
},
1698 {BWRITERSIO_SINCOS
, instr_handler
},
1699 {BWRITERSIO_M4x4
, instr_handler
},
1700 {BWRITERSIO_M4x3
, instr_handler
},
1701 {BWRITERSIO_M3x4
, instr_handler
},
1702 {BWRITERSIO_M3x3
, instr_handler
},
1703 {BWRITERSIO_M3x2
, instr_handler
},
1704 {BWRITERSIO_LIT
, instr_handler
},
1705 {BWRITERSIO_POW
, instr_handler
},
1706 {BWRITERSIO_MOVA
, instr_handler
},
1708 {BWRITERSIO_CALL
, instr_handler
},
1709 {BWRITERSIO_CALLNZ
, instr_handler
},
1710 {BWRITERSIO_REP
, instr_handler
},
1711 {BWRITERSIO_ENDREP
, instr_handler
},
1712 {BWRITERSIO_IF
, instr_handler
},
1713 {BWRITERSIO_LABEL
, instr_handler
},
1714 {BWRITERSIO_ELSE
, instr_handler
},
1715 {BWRITERSIO_ENDIF
, instr_handler
},
1716 {BWRITERSIO_LOOP
, instr_handler
},
1717 {BWRITERSIO_RET
, instr_handler
},
1718 {BWRITERSIO_ENDLOOP
, instr_handler
},
1720 {BWRITERSIO_END
, NULL
},
1723 static const struct bytecode_backend vs_2_0_backend
= {
1732 static const struct instr_handler_table vs_2_x_handlers
[] = {
1733 {BWRITERSIO_ADD
, instr_handler
},
1734 {BWRITERSIO_NOP
, instr_handler
},
1735 {BWRITERSIO_MOV
, instr_handler
},
1736 {BWRITERSIO_SUB
, instr_handler
},
1737 {BWRITERSIO_MAD
, instr_handler
},
1738 {BWRITERSIO_MUL
, instr_handler
},
1739 {BWRITERSIO_RCP
, instr_handler
},
1740 {BWRITERSIO_RSQ
, instr_handler
},
1741 {BWRITERSIO_DP3
, instr_handler
},
1742 {BWRITERSIO_DP4
, instr_handler
},
1743 {BWRITERSIO_MIN
, instr_handler
},
1744 {BWRITERSIO_MAX
, instr_handler
},
1745 {BWRITERSIO_SLT
, instr_handler
},
1746 {BWRITERSIO_SGE
, instr_handler
},
1747 {BWRITERSIO_ABS
, instr_handler
},
1748 {BWRITERSIO_EXP
, instr_handler
},
1749 {BWRITERSIO_LOG
, instr_handler
},
1750 {BWRITERSIO_EXPP
, instr_handler
},
1751 {BWRITERSIO_LOGP
, instr_handler
},
1752 {BWRITERSIO_DST
, instr_handler
},
1753 {BWRITERSIO_LRP
, instr_handler
},
1754 {BWRITERSIO_FRC
, instr_handler
},
1755 {BWRITERSIO_CRS
, instr_handler
},
1756 {BWRITERSIO_SGN
, instr_handler
},
1757 {BWRITERSIO_NRM
, instr_handler
},
1758 {BWRITERSIO_SINCOS
, instr_handler
},
1759 {BWRITERSIO_M4x4
, instr_handler
},
1760 {BWRITERSIO_M4x3
, instr_handler
},
1761 {BWRITERSIO_M3x4
, instr_handler
},
1762 {BWRITERSIO_M3x3
, instr_handler
},
1763 {BWRITERSIO_M3x2
, instr_handler
},
1764 {BWRITERSIO_LIT
, instr_handler
},
1765 {BWRITERSIO_POW
, instr_handler
},
1766 {BWRITERSIO_MOVA
, instr_handler
},
1768 {BWRITERSIO_CALL
, instr_handler
},
1769 {BWRITERSIO_CALLNZ
, instr_handler
},
1770 {BWRITERSIO_REP
, instr_handler
},
1771 {BWRITERSIO_ENDREP
, instr_handler
},
1772 {BWRITERSIO_IF
, instr_handler
},
1773 {BWRITERSIO_LABEL
, instr_handler
},
1774 {BWRITERSIO_IFC
, instr_handler
},
1775 {BWRITERSIO_ELSE
, instr_handler
},
1776 {BWRITERSIO_ENDIF
, instr_handler
},
1777 {BWRITERSIO_BREAK
, instr_handler
},
1778 {BWRITERSIO_BREAKC
, instr_handler
},
1779 {BWRITERSIO_LOOP
, instr_handler
},
1780 {BWRITERSIO_RET
, instr_handler
},
1781 {BWRITERSIO_ENDLOOP
, instr_handler
},
1783 {BWRITERSIO_SETP
, instr_handler
},
1784 {BWRITERSIO_BREAKP
, instr_handler
},
1786 {BWRITERSIO_END
, NULL
},
1789 static const struct bytecode_backend vs_2_x_backend
= {
1798 static void write_samplers(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1800 DWORD instr_dcl
= D3DSIO_DCL
| (2 << D3DSI_INSTLENGTH_SHIFT
);
1802 const DWORD reg
= (1u << 31) | d3dsp_register( D3DSPR_SAMPLER
, 0 ) | D3DSP_WRITEMASK_ALL
;
1804 for(i
= 0; i
< shader
->num_samplers
; i
++) {
1805 /* Write the DCL instruction */
1806 put_dword(buffer
, instr_dcl
);
1808 /* Already shifted */
1809 token
|= (d3d9_sampler(shader
->samplers
[i
].type
)) & D3DSP_TEXTURETYPE_MASK
;
1810 put_dword(buffer
, token
);
1811 token
= reg
| (shader
->samplers
[i
].regnum
& D3DSP_REGNUM_MASK
);
1812 token
|= d3d9_dstmod(shader
->samplers
[i
].mod
);
1813 put_dword(buffer
, token
);
1817 static void ps_2_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1818 HRESULT hr
= find_ps_builtin_semantics(This
, shader
, 8);
1824 write_declarations(This
, buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
1825 write_samplers(shader
, buffer
);
1826 write_constF(shader
, buffer
, TRUE
);
1827 write_constB(shader
, buffer
, TRUE
);
1828 write_constI(shader
, buffer
, TRUE
);
1831 static void ps_2_srcreg(struct bc_writer
*This
,
1832 const struct shader_reg
*reg
,
1833 struct bytecode_buffer
*buffer
) {
1834 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1837 WARN("Relative addressing not supported in <= ps_3_0\n");
1838 This
->state
= E_INVALIDARG
;
1843 case BWRITERSPR_INPUT
:
1844 token
|= map_ps_input(This
, reg
);
1847 /* Can be mapped 1:1 */
1848 case BWRITERSPR_TEMP
:
1849 case BWRITERSPR_CONST
:
1850 case BWRITERSPR_COLOROUT
:
1851 case BWRITERSPR_CONSTBOOL
:
1852 case BWRITERSPR_CONSTINT
:
1853 case BWRITERSPR_SAMPLER
:
1854 case BWRITERSPR_LABEL
:
1855 case BWRITERSPR_DEPTHOUT
:
1856 d3d9reg
= d3d9_register(reg
->type
);
1857 token
|= d3dsp_register( d3d9reg
, reg
->regnum
);
1860 case BWRITERSPR_PREDICATE
:
1861 if(This
->version
!= BWRITERPS_VERSION(2, 1)){
1862 WARN("Predicate register not supported in ps_2_0\n");
1863 This
->state
= E_INVALIDARG
;
1866 WARN("Predicate register with regnum %u not supported\n",
1868 This
->state
= E_INVALIDARG
;
1870 token
|= d3dsp_register( D3DSPR_PREDICATE
, 0 );
1874 WARN("Invalid register type for ps_2_0 shader\n");
1875 This
->state
= E_INVALIDARG
;
1879 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1881 token
|= d3d9_srcmod(reg
->srcmod
);
1882 put_dword(buffer
, token
);
1885 static void ps_2_0_dstreg(struct bc_writer
*This
,
1886 const struct shader_reg
*reg
,
1887 struct bytecode_buffer
*buffer
,
1888 DWORD shift
, DWORD mod
) {
1889 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1893 WARN("Relative addressing not supported for destination registers\n");
1894 This
->state
= E_INVALIDARG
;
1899 case BWRITERSPR_TEMP
: /* 1:1 mapping */
1900 case BWRITERSPR_COLOROUT
:
1901 case BWRITERSPR_DEPTHOUT
:
1902 d3d9reg
= d3d9_register(reg
->type
);
1903 token
|= d3dsp_register( d3d9reg
, reg
->regnum
);
1906 case BWRITERSPR_PREDICATE
:
1907 if(This
->version
!= BWRITERPS_VERSION(2, 1)){
1908 WARN("Predicate register not supported in ps_2_0\n");
1909 This
->state
= E_INVALIDARG
;
1911 token
|= d3dsp_register( D3DSPR_PREDICATE
, reg
->regnum
);
1914 /* texkill uses the input register as a destination parameter */
1915 case BWRITERSPR_INPUT
:
1916 token
|= map_ps_input(This
, reg
);
1920 WARN("Invalid dest register type for 2.x pshader\n");
1921 This
->state
= E_INVALIDARG
;
1925 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1926 token
|= d3d9_dstmod(mod
);
1928 token
|= d3d9_writemask(reg
->u
.writemask
);
1929 put_dword(buffer
, token
);
1932 static const struct instr_handler_table ps_2_0_handlers
[] = {
1933 {BWRITERSIO_ADD
, instr_handler
},
1934 {BWRITERSIO_NOP
, instr_handler
},
1935 {BWRITERSIO_MOV
, instr_handler
},
1936 {BWRITERSIO_SUB
, instr_handler
},
1937 {BWRITERSIO_MAD
, instr_handler
},
1938 {BWRITERSIO_MUL
, instr_handler
},
1939 {BWRITERSIO_RCP
, instr_handler
},
1940 {BWRITERSIO_RSQ
, instr_handler
},
1941 {BWRITERSIO_DP3
, instr_handler
},
1942 {BWRITERSIO_DP4
, instr_handler
},
1943 {BWRITERSIO_MIN
, instr_handler
},
1944 {BWRITERSIO_MAX
, instr_handler
},
1945 {BWRITERSIO_ABS
, instr_handler
},
1946 {BWRITERSIO_EXP
, instr_handler
},
1947 {BWRITERSIO_LOG
, instr_handler
},
1948 {BWRITERSIO_EXPP
, instr_handler
},
1949 {BWRITERSIO_LOGP
, instr_handler
},
1950 {BWRITERSIO_LRP
, instr_handler
},
1951 {BWRITERSIO_FRC
, instr_handler
},
1952 {BWRITERSIO_CRS
, instr_handler
},
1953 {BWRITERSIO_NRM
, instr_handler
},
1954 {BWRITERSIO_SINCOS
, instr_handler
},
1955 {BWRITERSIO_M4x4
, instr_handler
},
1956 {BWRITERSIO_M4x3
, instr_handler
},
1957 {BWRITERSIO_M3x4
, instr_handler
},
1958 {BWRITERSIO_M3x3
, instr_handler
},
1959 {BWRITERSIO_M3x2
, instr_handler
},
1960 {BWRITERSIO_POW
, instr_handler
},
1961 {BWRITERSIO_DP2ADD
, instr_handler
},
1962 {BWRITERSIO_CMP
, instr_handler
},
1964 {BWRITERSIO_TEX
, instr_handler
},
1965 {BWRITERSIO_TEXLDP
, instr_handler
},
1966 {BWRITERSIO_TEXLDB
, instr_handler
},
1967 {BWRITERSIO_TEXKILL
, instr_handler
},
1969 {BWRITERSIO_END
, NULL
},
1972 static const struct bytecode_backend ps_2_0_backend
= {
1981 static const struct instr_handler_table ps_2_x_handlers
[] = {
1982 {BWRITERSIO_ADD
, instr_handler
},
1983 {BWRITERSIO_NOP
, instr_handler
},
1984 {BWRITERSIO_MOV
, instr_handler
},
1985 {BWRITERSIO_SUB
, instr_handler
},
1986 {BWRITERSIO_MAD
, instr_handler
},
1987 {BWRITERSIO_MUL
, instr_handler
},
1988 {BWRITERSIO_RCP
, instr_handler
},
1989 {BWRITERSIO_RSQ
, instr_handler
},
1990 {BWRITERSIO_DP3
, instr_handler
},
1991 {BWRITERSIO_DP4
, instr_handler
},
1992 {BWRITERSIO_MIN
, instr_handler
},
1993 {BWRITERSIO_MAX
, instr_handler
},
1994 {BWRITERSIO_ABS
, instr_handler
},
1995 {BWRITERSIO_EXP
, instr_handler
},
1996 {BWRITERSIO_LOG
, instr_handler
},
1997 {BWRITERSIO_EXPP
, instr_handler
},
1998 {BWRITERSIO_LOGP
, instr_handler
},
1999 {BWRITERSIO_LRP
, instr_handler
},
2000 {BWRITERSIO_FRC
, instr_handler
},
2001 {BWRITERSIO_CRS
, instr_handler
},
2002 {BWRITERSIO_NRM
, instr_handler
},
2003 {BWRITERSIO_SINCOS
, instr_handler
},
2004 {BWRITERSIO_M4x4
, instr_handler
},
2005 {BWRITERSIO_M4x3
, instr_handler
},
2006 {BWRITERSIO_M3x4
, instr_handler
},
2007 {BWRITERSIO_M3x3
, instr_handler
},
2008 {BWRITERSIO_M3x2
, instr_handler
},
2009 {BWRITERSIO_POW
, instr_handler
},
2010 {BWRITERSIO_DP2ADD
, instr_handler
},
2011 {BWRITERSIO_CMP
, instr_handler
},
2013 {BWRITERSIO_CALL
, instr_handler
},
2014 {BWRITERSIO_CALLNZ
, instr_handler
},
2015 {BWRITERSIO_REP
, instr_handler
},
2016 {BWRITERSIO_ENDREP
, instr_handler
},
2017 {BWRITERSIO_IF
, instr_handler
},
2018 {BWRITERSIO_LABEL
, instr_handler
},
2019 {BWRITERSIO_IFC
, instr_handler
},
2020 {BWRITERSIO_ELSE
, instr_handler
},
2021 {BWRITERSIO_ENDIF
, instr_handler
},
2022 {BWRITERSIO_BREAK
, instr_handler
},
2023 {BWRITERSIO_BREAKC
, instr_handler
},
2024 {BWRITERSIO_RET
, instr_handler
},
2026 {BWRITERSIO_TEX
, instr_handler
},
2027 {BWRITERSIO_TEXLDP
, instr_handler
},
2028 {BWRITERSIO_TEXLDB
, instr_handler
},
2029 {BWRITERSIO_TEXKILL
, instr_handler
},
2030 {BWRITERSIO_DSX
, instr_handler
},
2031 {BWRITERSIO_DSY
, instr_handler
},
2033 {BWRITERSIO_SETP
, instr_handler
},
2034 {BWRITERSIO_BREAKP
, instr_handler
},
2036 {BWRITERSIO_TEXLDD
, instr_handler
},
2038 {BWRITERSIO_END
, NULL
},
2041 static const struct bytecode_backend ps_2_x_backend
= {
2050 static void sm_3_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
2051 write_declarations(This
, buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
2052 write_declarations(This
, buffer
, TRUE
, shader
->outputs
, shader
->num_outputs
, BWRITERSPR_OUTPUT
);
2053 write_constF(shader
, buffer
, TRUE
);
2054 write_constB(shader
, buffer
, TRUE
);
2055 write_constI(shader
, buffer
, TRUE
);
2056 write_samplers(shader
, buffer
);
2059 static void sm_3_srcreg(struct bc_writer
*This
,
2060 const struct shader_reg
*reg
,
2061 struct bytecode_buffer
*buffer
) {
2062 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
2065 d3d9reg
= d3d9_register(reg
->type
);
2066 token
|= d3dsp_register( d3d9reg
, reg
->regnum
);
2067 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
;
2068 token
|= d3d9_srcmod(reg
->srcmod
);
2071 if(reg
->type
== BWRITERSPR_CONST
&& This
->version
== BWRITERPS_VERSION(3, 0)) {
2072 WARN("c%u[...] is unsupported in ps_3_0\n", reg
->regnum
);
2073 This
->state
= E_INVALIDARG
;
2076 if(((reg
->rel_reg
->type
== BWRITERSPR_ADDR
&& This
->version
== BWRITERVS_VERSION(3, 0)) ||
2077 reg
->rel_reg
->type
== BWRITERSPR_LOOP
) &&
2078 reg
->rel_reg
->regnum
== 0) {
2079 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
2081 WARN("Unsupported relative addressing register\n");
2082 This
->state
= E_INVALIDARG
;
2087 put_dword(buffer
, token
);
2089 /* vs_2_0 and newer write the register containing the index explicitly in the
2092 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
2093 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
2097 static void sm_3_dstreg(struct bc_writer
*This
,
2098 const struct shader_reg
*reg
,
2099 struct bytecode_buffer
*buffer
,
2100 DWORD shift
, DWORD mod
) {
2101 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
2105 if(This
->version
== BWRITERVS_VERSION(3, 0) &&
2106 reg
->type
== BWRITERSPR_OUTPUT
) {
2107 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
2109 WARN("Relative addressing not supported for this shader type or register type\n");
2110 This
->state
= E_INVALIDARG
;
2115 d3d9reg
= d3d9_register(reg
->type
);
2116 token
|= d3dsp_register( d3d9reg
, reg
->regnum
);
2117 token
|= d3d9_dstmod(mod
);
2118 token
|= d3d9_writemask(reg
->u
.writemask
);
2119 put_dword(buffer
, token
);
2121 /* vs_2_0 and newer write the register containing the index explicitly in the
2124 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
2125 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
2129 static const struct instr_handler_table vs_3_handlers
[] = {
2130 {BWRITERSIO_ADD
, instr_handler
},
2131 {BWRITERSIO_NOP
, instr_handler
},
2132 {BWRITERSIO_MOV
, instr_handler
},
2133 {BWRITERSIO_SUB
, instr_handler
},
2134 {BWRITERSIO_MAD
, instr_handler
},
2135 {BWRITERSIO_MUL
, instr_handler
},
2136 {BWRITERSIO_RCP
, instr_handler
},
2137 {BWRITERSIO_RSQ
, instr_handler
},
2138 {BWRITERSIO_DP3
, instr_handler
},
2139 {BWRITERSIO_DP4
, instr_handler
},
2140 {BWRITERSIO_MIN
, instr_handler
},
2141 {BWRITERSIO_MAX
, instr_handler
},
2142 {BWRITERSIO_SLT
, instr_handler
},
2143 {BWRITERSIO_SGE
, instr_handler
},
2144 {BWRITERSIO_ABS
, instr_handler
},
2145 {BWRITERSIO_EXP
, instr_handler
},
2146 {BWRITERSIO_LOG
, instr_handler
},
2147 {BWRITERSIO_EXPP
, instr_handler
},
2148 {BWRITERSIO_LOGP
, instr_handler
},
2149 {BWRITERSIO_DST
, instr_handler
},
2150 {BWRITERSIO_LRP
, instr_handler
},
2151 {BWRITERSIO_FRC
, instr_handler
},
2152 {BWRITERSIO_CRS
, instr_handler
},
2153 {BWRITERSIO_SGN
, instr_handler
},
2154 {BWRITERSIO_NRM
, instr_handler
},
2155 {BWRITERSIO_SINCOS
, instr_handler
},
2156 {BWRITERSIO_M4x4
, instr_handler
},
2157 {BWRITERSIO_M4x3
, instr_handler
},
2158 {BWRITERSIO_M3x4
, instr_handler
},
2159 {BWRITERSIO_M3x3
, instr_handler
},
2160 {BWRITERSIO_M3x2
, instr_handler
},
2161 {BWRITERSIO_LIT
, instr_handler
},
2162 {BWRITERSIO_POW
, instr_handler
},
2163 {BWRITERSIO_MOVA
, instr_handler
},
2165 {BWRITERSIO_CALL
, instr_handler
},
2166 {BWRITERSIO_CALLNZ
, instr_handler
},
2167 {BWRITERSIO_REP
, instr_handler
},
2168 {BWRITERSIO_ENDREP
, instr_handler
},
2169 {BWRITERSIO_IF
, instr_handler
},
2170 {BWRITERSIO_LABEL
, instr_handler
},
2171 {BWRITERSIO_IFC
, instr_handler
},
2172 {BWRITERSIO_ELSE
, instr_handler
},
2173 {BWRITERSIO_ENDIF
, instr_handler
},
2174 {BWRITERSIO_BREAK
, instr_handler
},
2175 {BWRITERSIO_BREAKC
, instr_handler
},
2176 {BWRITERSIO_LOOP
, instr_handler
},
2177 {BWRITERSIO_RET
, instr_handler
},
2178 {BWRITERSIO_ENDLOOP
, instr_handler
},
2180 {BWRITERSIO_SETP
, instr_handler
},
2181 {BWRITERSIO_BREAKP
, instr_handler
},
2182 {BWRITERSIO_TEXLDL
, instr_handler
},
2184 {BWRITERSIO_END
, NULL
},
2187 static const struct bytecode_backend vs_3_backend
= {
2196 static const struct instr_handler_table ps_3_handlers
[] = {
2197 {BWRITERSIO_ADD
, instr_handler
},
2198 {BWRITERSIO_NOP
, instr_handler
},
2199 {BWRITERSIO_MOV
, instr_handler
},
2200 {BWRITERSIO_SUB
, instr_handler
},
2201 {BWRITERSIO_MAD
, instr_handler
},
2202 {BWRITERSIO_MUL
, instr_handler
},
2203 {BWRITERSIO_RCP
, instr_handler
},
2204 {BWRITERSIO_RSQ
, instr_handler
},
2205 {BWRITERSIO_DP3
, instr_handler
},
2206 {BWRITERSIO_DP4
, instr_handler
},
2207 {BWRITERSIO_MIN
, instr_handler
},
2208 {BWRITERSIO_MAX
, instr_handler
},
2209 {BWRITERSIO_ABS
, instr_handler
},
2210 {BWRITERSIO_EXP
, instr_handler
},
2211 {BWRITERSIO_LOG
, instr_handler
},
2212 {BWRITERSIO_EXPP
, instr_handler
},
2213 {BWRITERSIO_LOGP
, instr_handler
},
2214 {BWRITERSIO_LRP
, instr_handler
},
2215 {BWRITERSIO_FRC
, instr_handler
},
2216 {BWRITERSIO_CRS
, instr_handler
},
2217 {BWRITERSIO_NRM
, instr_handler
},
2218 {BWRITERSIO_SINCOS
, instr_handler
},
2219 {BWRITERSIO_M4x4
, instr_handler
},
2220 {BWRITERSIO_M4x3
, instr_handler
},
2221 {BWRITERSIO_M3x4
, instr_handler
},
2222 {BWRITERSIO_M3x3
, instr_handler
},
2223 {BWRITERSIO_M3x2
, instr_handler
},
2224 {BWRITERSIO_POW
, instr_handler
},
2225 {BWRITERSIO_DP2ADD
, instr_handler
},
2226 {BWRITERSIO_CMP
, instr_handler
},
2228 {BWRITERSIO_CALL
, instr_handler
},
2229 {BWRITERSIO_CALLNZ
, instr_handler
},
2230 {BWRITERSIO_REP
, instr_handler
},
2231 {BWRITERSIO_ENDREP
, instr_handler
},
2232 {BWRITERSIO_IF
, instr_handler
},
2233 {BWRITERSIO_LABEL
, instr_handler
},
2234 {BWRITERSIO_IFC
, instr_handler
},
2235 {BWRITERSIO_ELSE
, instr_handler
},
2236 {BWRITERSIO_ENDIF
, instr_handler
},
2237 {BWRITERSIO_BREAK
, instr_handler
},
2238 {BWRITERSIO_BREAKC
, instr_handler
},
2239 {BWRITERSIO_LOOP
, instr_handler
},
2240 {BWRITERSIO_RET
, instr_handler
},
2241 {BWRITERSIO_ENDLOOP
, instr_handler
},
2243 {BWRITERSIO_SETP
, instr_handler
},
2244 {BWRITERSIO_BREAKP
, instr_handler
},
2245 {BWRITERSIO_TEXLDL
, instr_handler
},
2247 {BWRITERSIO_TEX
, instr_handler
},
2248 {BWRITERSIO_TEXLDP
, instr_handler
},
2249 {BWRITERSIO_TEXLDB
, instr_handler
},
2250 {BWRITERSIO_TEXKILL
, instr_handler
},
2251 {BWRITERSIO_DSX
, instr_handler
},
2252 {BWRITERSIO_DSY
, instr_handler
},
2253 {BWRITERSIO_TEXLDD
, instr_handler
},
2255 {BWRITERSIO_END
, NULL
},
2258 static const struct bytecode_backend ps_3_backend
= {
2267 static void init_vs10_dx9_writer(struct bc_writer
*writer
) {
2268 TRACE("Creating DirectX9 vertex shader 1.0 writer\n");
2269 writer
->funcs
= &vs_1_x_backend
;
2272 static void init_vs11_dx9_writer(struct bc_writer
*writer
) {
2273 TRACE("Creating DirectX9 vertex shader 1.1 writer\n");
2274 writer
->funcs
= &vs_1_x_backend
;
2277 static void init_vs20_dx9_writer(struct bc_writer
*writer
) {
2278 TRACE("Creating DirectX9 vertex shader 2.0 writer\n");
2279 writer
->funcs
= &vs_2_0_backend
;
2282 static void init_vs2x_dx9_writer(struct bc_writer
*writer
) {
2283 TRACE("Creating DirectX9 vertex shader 2.x writer\n");
2284 writer
->funcs
= &vs_2_x_backend
;
2287 static void init_vs30_dx9_writer(struct bc_writer
*writer
) {
2288 TRACE("Creating DirectX9 vertex shader 3.0 writer\n");
2289 writer
->funcs
= &vs_3_backend
;
2292 static void init_ps10_dx9_writer(struct bc_writer
*writer
) {
2293 TRACE("Creating DirectX9 pixel shader 1.0 writer\n");
2294 writer
->funcs
= &ps_1_0123_backend
;
2297 static void init_ps11_dx9_writer(struct bc_writer
*writer
) {
2298 TRACE("Creating DirectX9 pixel shader 1.1 writer\n");
2299 writer
->funcs
= &ps_1_0123_backend
;
2302 static void init_ps12_dx9_writer(struct bc_writer
*writer
) {
2303 TRACE("Creating DirectX9 pixel shader 1.2 writer\n");
2304 writer
->funcs
= &ps_1_0123_backend
;
2307 static void init_ps13_dx9_writer(struct bc_writer
*writer
) {
2308 TRACE("Creating DirectX9 pixel shader 1.3 writer\n");
2309 writer
->funcs
= &ps_1_0123_backend
;
2312 static void init_ps14_dx9_writer(struct bc_writer
*writer
) {
2313 TRACE("Creating DirectX9 pixel shader 1.4 writer\n");
2314 writer
->funcs
= &ps_1_4_backend
;
2317 static void init_ps20_dx9_writer(struct bc_writer
*writer
) {
2318 TRACE("Creating DirectX9 pixel shader 2.0 writer\n");
2319 writer
->funcs
= &ps_2_0_backend
;
2322 static void init_ps2x_dx9_writer(struct bc_writer
*writer
) {
2323 TRACE("Creating DirectX9 pixel shader 2.x writer\n");
2324 writer
->funcs
= &ps_2_x_backend
;
2327 static void init_ps30_dx9_writer(struct bc_writer
*writer
) {
2328 TRACE("Creating DirectX9 pixel shader 3.0 writer\n");
2329 writer
->funcs
= &ps_3_backend
;
2332 static struct bc_writer
*create_writer(DWORD version
, DWORD dxversion
) {
2333 struct bc_writer
*ret
= d3dcompiler_alloc(sizeof(*ret
));
2336 WARN("Failed to allocate a bytecode writer instance\n");
2341 case BWRITERVS_VERSION(1, 0):
2342 if(dxversion
!= 9) {
2343 WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion
);
2346 init_vs10_dx9_writer(ret
);
2348 case BWRITERVS_VERSION(1, 1):
2349 if(dxversion
!= 9) {
2350 WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion
);
2353 init_vs11_dx9_writer(ret
);
2355 case BWRITERVS_VERSION(2, 0):
2356 if(dxversion
!= 9) {
2357 WARN("Unsupported dxversion for vertex shader 2.0 requested: %u\n", dxversion
);
2360 init_vs20_dx9_writer(ret
);
2362 case BWRITERVS_VERSION(2, 1):
2363 if(dxversion
!= 9) {
2364 WARN("Unsupported dxversion for vertex shader 2.x requested: %u\n", dxversion
);
2367 init_vs2x_dx9_writer(ret
);
2369 case BWRITERVS_VERSION(3, 0):
2370 if(dxversion
!= 9) {
2371 WARN("Unsupported dxversion for vertex shader 3.0 requested: %u\n", dxversion
);
2374 init_vs30_dx9_writer(ret
);
2377 case BWRITERPS_VERSION(1, 0):
2378 if(dxversion
!= 9) {
2379 WARN("Unsupported dxversion for pixel shader 1.0 requested: %u\n", dxversion
);
2382 init_ps10_dx9_writer(ret
);
2384 case BWRITERPS_VERSION(1, 1):
2385 if(dxversion
!= 9) {
2386 WARN("Unsupported dxversion for pixel shader 1.1 requested: %u\n", dxversion
);
2389 init_ps11_dx9_writer(ret
);
2391 case BWRITERPS_VERSION(1, 2):
2392 if(dxversion
!= 9) {
2393 WARN("Unsupported dxversion for pixel shader 1.2 requested: %u\n", dxversion
);
2396 init_ps12_dx9_writer(ret
);
2398 case BWRITERPS_VERSION(1, 3):
2399 if(dxversion
!= 9) {
2400 WARN("Unsupported dxversion for pixel shader 1.3 requested: %u\n", dxversion
);
2403 init_ps13_dx9_writer(ret
);
2405 case BWRITERPS_VERSION(1, 4):
2406 if(dxversion
!= 9) {
2407 WARN("Unsupported dxversion for pixel shader 1.4 requested: %u\n", dxversion
);
2410 init_ps14_dx9_writer(ret
);
2413 case BWRITERPS_VERSION(2, 0):
2414 if(dxversion
!= 9) {
2415 WARN("Unsupported dxversion for pixel shader 2.0 requested: %u\n", dxversion
);
2418 init_ps20_dx9_writer(ret
);
2421 case BWRITERPS_VERSION(2, 1):
2422 if(dxversion
!= 9) {
2423 WARN("Unsupported dxversion for pixel shader 2.x requested: %u\n", dxversion
);
2426 init_ps2x_dx9_writer(ret
);
2429 case BWRITERPS_VERSION(3, 0):
2430 if(dxversion
!= 9) {
2431 WARN("Unsupported dxversion for pixel shader 3.0 requested: %u\n", dxversion
);
2434 init_ps30_dx9_writer(ret
);
2438 WARN("Unexpected shader version requested: %08x\n", version
);
2441 ret
->version
= version
;
2445 d3dcompiler_free(ret
);
2449 static HRESULT
call_instr_handler(struct bc_writer
*writer
,
2450 const struct instruction
*instr
,
2451 struct bytecode_buffer
*buffer
) {
2454 while(writer
->funcs
->instructions
[i
].opcode
!= BWRITERSIO_END
) {
2455 if(instr
->opcode
== writer
->funcs
->instructions
[i
].opcode
) {
2456 if(!writer
->funcs
->instructions
[i
].func
) {
2457 WARN("Opcode %u not supported by this profile\n", instr
->opcode
);
2458 return E_INVALIDARG
;
2460 writer
->funcs
->instructions
[i
].func(writer
, instr
, buffer
);
2466 FIXME("Unhandled instruction %u - %s\n", instr
->opcode
,
2467 debug_print_opcode(instr
->opcode
));
2468 return E_INVALIDARG
;
2471 HRESULT
SlWriteBytecode(const struct bwriter_shader
*shader
, int dxversion
, DWORD
**result
, DWORD
*size
)
2473 struct bc_writer
*writer
;
2474 struct bytecode_buffer
*buffer
= NULL
;
2479 ERR("NULL shader structure, aborting\n");
2482 writer
= create_writer(shader
->version
, dxversion
);
2486 WARN("Could not create a bytecode writer instance. Either unsupported version\n");
2487 WARN("or out of memory\n");
2492 buffer
= allocate_buffer();
2494 WARN("Failed to allocate a buffer for the shader bytecode\n");
2499 /* Write shader type and version */
2500 put_dword(buffer
, shader
->version
);
2502 writer
->funcs
->header(writer
, shader
, buffer
);
2503 if(FAILED(writer
->state
)) {
2508 for(i
= 0; i
< shader
->num_instrs
; i
++) {
2509 hr
= call_instr_handler(writer
, shader
->instr
[i
], buffer
);
2515 if(FAILED(writer
->state
)) {
2520 writer
->funcs
->end(writer
, shader
, buffer
);
2522 if(FAILED(buffer
->state
)) {
2527 *size
= buffer
->size
* sizeof(DWORD
);
2528 *result
= buffer
->data
;
2529 buffer
->data
= NULL
;
2534 d3dcompiler_free(buffer
->data
);
2535 d3dcompiler_free(buffer
);
2537 d3dcompiler_free(writer
);
2541 void SlDeleteShader(struct bwriter_shader
*shader
) {
2544 TRACE("Deleting shader %p\n", shader
);
2546 for(i
= 0; i
< shader
->num_cf
; i
++) {
2547 d3dcompiler_free(shader
->constF
[i
]);
2549 d3dcompiler_free(shader
->constF
);
2550 for(i
= 0; i
< shader
->num_ci
; i
++) {
2551 d3dcompiler_free(shader
->constI
[i
]);
2553 d3dcompiler_free(shader
->constI
);
2554 for(i
= 0; i
< shader
->num_cb
; i
++) {
2555 d3dcompiler_free(shader
->constB
[i
]);
2557 d3dcompiler_free(shader
->constB
);
2559 d3dcompiler_free(shader
->inputs
);
2560 d3dcompiler_free(shader
->outputs
);
2561 d3dcompiler_free(shader
->samplers
);
2563 for(i
= 0; i
< shader
->num_instrs
; i
++) {
2564 for(j
= 0; j
< shader
->instr
[i
]->num_srcs
; j
++) {
2565 d3dcompiler_free(shader
->instr
[i
]->src
[j
].rel_reg
);
2567 d3dcompiler_free(shader
->instr
[i
]->src
);
2568 d3dcompiler_free(shader
->instr
[i
]->dst
.rel_reg
);
2569 d3dcompiler_free(shader
->instr
[i
]);
2571 d3dcompiler_free(shader
->instr
);
2573 d3dcompiler_free(shader
);