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 "wine/debug.h"
25 #include "d3d9types.h"
26 #include "d3dcompiler_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(bytecodewriter
);
30 static BOOL
array_reserve(void **elements
, unsigned int *capacity
, unsigned int count
, unsigned int size
)
32 unsigned int max_capacity
, new_capacity
;
35 if (count
<= *capacity
)
38 max_capacity
= ~0u / size
;
39 if (count
> max_capacity
)
42 new_capacity
= max(8, *capacity
);
43 while (new_capacity
< count
&& new_capacity
<= max_capacity
/ 2)
45 if (new_capacity
< count
)
48 if (!(new_elements
= d3dcompiler_realloc(*elements
, new_capacity
* size
)))
50 ERR("Failed to allocate memory.\n");
54 *elements
= new_elements
;
55 *capacity
= new_capacity
;
59 /****************************************************************
60 * General assembler shader construction helper routines follow *
61 ****************************************************************/
62 /* struct instruction *alloc_instr
64 * Allocates a new instruction structure with srcs registers
67 * srcs: Number of source registers to allocate
70 * A pointer to the allocated instruction structure
71 * NULL in case of an allocation failure
73 struct instruction
*alloc_instr(unsigned int srcs
) {
74 struct instruction
*ret
= d3dcompiler_alloc(sizeof(*ret
));
76 ERR("Failed to allocate memory for an instruction structure\n");
81 ret
->src
= d3dcompiler_alloc(srcs
* sizeof(*ret
->src
));
83 ERR("Failed to allocate memory for instruction registers\n");
84 d3dcompiler_free(ret
);
92 /* void add_instruction
94 * Adds a new instruction to the shader's instructions array and grows the instruction array
97 * The function does NOT copy the instruction structure. Make sure not to release the
98 * instruction or any of its substructures like registers.
101 * shader: Shader to add the instruction to
102 * instr: Instruction to add to the shader
104 BOOL
add_instruction(struct bwriter_shader
*shader
, struct instruction
*instr
) {
105 if(!shader
) return FALSE
;
107 if (!array_reserve((void **)&shader
->instr
, &shader
->instr_alloc_size
,
108 shader
->num_instrs
+ 1, sizeof(*shader
->instr
)))
111 shader
->instr
[shader
->num_instrs
] = instr
;
112 shader
->num_instrs
++;
116 BOOL
add_constF(struct bwriter_shader
*shader
, DWORD reg
, float x
, float y
, float z
, float w
) {
117 struct constant
*newconst
;
120 struct constant
**newarray
;
121 newarray
= d3dcompiler_realloc(shader
->constF
,
122 sizeof(*shader
->constF
) * (shader
->num_cf
+ 1));
124 ERR("Failed to grow the constants array\n");
127 shader
->constF
= newarray
;
129 shader
->constF
= d3dcompiler_alloc(sizeof(*shader
->constF
));
130 if(!shader
->constF
) {
131 ERR("Failed to allocate the constants array\n");
136 newconst
= d3dcompiler_alloc(sizeof(*newconst
));
138 ERR("Failed to allocate a new constant\n");
141 newconst
->regnum
= reg
;
142 newconst
->value
[0].f
= x
;
143 newconst
->value
[1].f
= y
;
144 newconst
->value
[2].f
= z
;
145 newconst
->value
[3].f
= w
;
146 shader
->constF
[shader
->num_cf
] = newconst
;
152 BOOL
add_constI(struct bwriter_shader
*shader
, DWORD reg
, INT x
, INT y
, INT z
, INT w
) {
153 struct constant
*newconst
;
156 struct constant
**newarray
;
157 newarray
= d3dcompiler_realloc(shader
->constI
,
158 sizeof(*shader
->constI
) * (shader
->num_ci
+ 1));
160 ERR("Failed to grow the constants array\n");
163 shader
->constI
= newarray
;
165 shader
->constI
= d3dcompiler_alloc(sizeof(*shader
->constI
));
166 if(!shader
->constI
) {
167 ERR("Failed to allocate the constants array\n");
172 newconst
= d3dcompiler_alloc(sizeof(*newconst
));
174 ERR("Failed to allocate a new constant\n");
177 newconst
->regnum
= reg
;
178 newconst
->value
[0].i
= x
;
179 newconst
->value
[1].i
= y
;
180 newconst
->value
[2].i
= z
;
181 newconst
->value
[3].i
= w
;
182 shader
->constI
[shader
->num_ci
] = newconst
;
188 BOOL
add_constB(struct bwriter_shader
*shader
, DWORD reg
, BOOL x
) {
189 struct constant
*newconst
;
192 struct constant
**newarray
;
193 newarray
= d3dcompiler_realloc(shader
->constB
,
194 sizeof(*shader
->constB
) * (shader
->num_cb
+ 1));
196 ERR("Failed to grow the constants array\n");
199 shader
->constB
= newarray
;
201 shader
->constB
= d3dcompiler_alloc(sizeof(*shader
->constB
));
202 if(!shader
->constB
) {
203 ERR("Failed to allocate the constants array\n");
208 newconst
= d3dcompiler_alloc(sizeof(*newconst
));
210 ERR("Failed to allocate a new constant\n");
213 newconst
->regnum
= reg
;
214 newconst
->value
[0].b
= x
;
215 shader
->constB
[shader
->num_cb
] = newconst
;
221 BOOL
record_declaration(struct bwriter_shader
*shader
, DWORD usage
,
222 DWORD usage_idx
, DWORD mod
, BOOL output
,
223 DWORD regnum
, DWORD writemask
, BOOL builtin
) {
225 struct declaration
**decl
;
228 if(!shader
) return FALSE
;
231 num
= &shader
->num_outputs
;
232 decl
= &shader
->outputs
;
234 num
= &shader
->num_inputs
;
235 decl
= &shader
->inputs
;
239 *decl
= d3dcompiler_alloc(sizeof(**decl
));
241 ERR("Error allocating declarations array\n");
245 struct declaration
*newdecl
;
246 for(i
= 0; i
< *num
; i
++) {
247 if((*decl
)[i
].regnum
== regnum
&& ((*decl
)[i
].writemask
& writemask
)) {
248 WARN("Declaration of register %u already exists, writemask match 0x%x\n",
249 regnum
, (*decl
)[i
].writemask
& writemask
);
253 newdecl
= d3dcompiler_realloc(*decl
,
254 sizeof(**decl
) * ((*num
) + 1));
256 ERR("Error reallocating declarations array\n");
261 (*decl
)[*num
].usage
= usage
;
262 (*decl
)[*num
].usage_idx
= usage_idx
;
263 (*decl
)[*num
].regnum
= regnum
;
264 (*decl
)[*num
].mod
= mod
;
265 (*decl
)[*num
].writemask
= writemask
;
266 (*decl
)[*num
].builtin
= builtin
;
272 BOOL
record_sampler(struct bwriter_shader
*shader
, DWORD samptype
, DWORD mod
, DWORD regnum
) {
275 if(!shader
) return FALSE
;
277 if(shader
->num_samplers
== 0) {
278 shader
->samplers
= d3dcompiler_alloc(sizeof(*shader
->samplers
));
279 if(!shader
->samplers
) {
280 ERR("Error allocating samplers array\n");
284 struct samplerdecl
*newarray
;
286 for(i
= 0; i
< shader
->num_samplers
; i
++) {
287 if(shader
->samplers
[i
].regnum
== regnum
) {
288 WARN("Sampler %u already declared\n", regnum
);
289 /* This is not an error as far as the assembler is concerned.
290 * Direct3D might refuse to load the compiled shader though
295 newarray
= d3dcompiler_realloc(shader
->samplers
,
296 sizeof(*shader
->samplers
) * (shader
->num_samplers
+ 1));
298 ERR("Error reallocating samplers array\n");
301 shader
->samplers
= newarray
;
304 shader
->samplers
[shader
->num_samplers
].type
= samptype
;
305 shader
->samplers
[shader
->num_samplers
].mod
= mod
;
306 shader
->samplers
[shader
->num_samplers
].regnum
= regnum
;
307 shader
->num_samplers
++;
311 struct bytecode_buffer
314 unsigned int size
, alloc_size
;
320 typedef void (*instr_writer
)(struct bc_writer
*writer
, const struct instruction
*instr
,
321 struct bytecode_buffer
*buffer
);
323 struct bytecode_backend
325 void (*header
)(struct bc_writer
*writer
, const struct bwriter_shader
*shader
,
326 struct bytecode_buffer
*buffer
);
327 void (*end
)(struct bc_writer
*writer
, const struct bwriter_shader
*shader
,
328 struct bytecode_buffer
*buffer
);
329 void (*srcreg
)(struct bc_writer
*writer
, const struct shader_reg
*reg
,
330 struct bytecode_buffer
*buffer
);
331 void (*dstreg
)(struct bc_writer
*writer
, const struct shader_reg
*reg
,
332 struct bytecode_buffer
*buffer
, DWORD shift
, DWORD mod
);
333 void (*opcode
)(struct bc_writer
*writer
, const struct instruction
*instr
,
334 DWORD token
, struct bytecode_buffer
*buffer
);
336 const struct instr_handler_table
345 const struct bytecode_backend
*funcs
;
346 const struct bwriter_shader
*shader
;
350 /* Vertex shader varying mapping. */
351 DWORD oPos_regnum
, oD_regnum
[2], oT_regnum
[8], oFog_regnum
, oFog_mask
, oPts_regnum
, oPts_mask
;
353 /* Pixel shader varying mapping. */
354 DWORD t_regnum
[8], v_regnum
[2];
358 /* shader bytecode buffer manipulation functions.
359 * allocate_buffer creates a new buffer structure, put_dword adds a new
360 * DWORD to the buffer. In the rare case of a memory allocation failure
361 * when trying to grow the buffer a flag is set in the buffer to mark it
362 * invalid. This avoids return value checking and passing in many places
364 static struct bytecode_buffer
*allocate_buffer(void) {
365 struct bytecode_buffer
*ret
;
367 ret
= d3dcompiler_alloc(sizeof(*ret
));
368 if(!ret
) return NULL
;
373 static void put_dword(struct bytecode_buffer
*buffer
, DWORD value
) {
374 if(FAILED(buffer
->state
)) return;
376 if (!array_reserve((void **)&buffer
->data
, &buffer
->alloc_size
, buffer
->size
+ 1, sizeof(*buffer
->data
)))
378 buffer
->state
= E_OUTOFMEMORY
;
382 buffer
->data
[buffer
->size
++] = value
;
385 /* bwriter -> d3d9 conversion functions. */
387 static DWORD
sm1_version(const struct bwriter_shader
*shader
)
389 switch (shader
->type
)
392 return D3DVS_VERSION(shader
->major_version
, shader
->minor_version
);
394 return D3DPS_VERSION(shader
->major_version
, shader
->minor_version
);
396 ERR("Invalid shader type %#x.\n", shader
->type
);
401 static DWORD
d3d9_swizzle(DWORD bwriter_swizzle
)
405 if ((bwriter_swizzle
& BWRITERVS_X_X
) == BWRITERVS_X_X
) ret
|= D3DVS_X_X
;
406 if ((bwriter_swizzle
& BWRITERVS_X_Y
) == BWRITERVS_X_Y
) ret
|= D3DVS_X_Y
;
407 if ((bwriter_swizzle
& BWRITERVS_X_Z
) == BWRITERVS_X_Z
) ret
|= D3DVS_X_Z
;
408 if ((bwriter_swizzle
& BWRITERVS_X_W
) == BWRITERVS_X_W
) ret
|= D3DVS_X_W
;
410 if ((bwriter_swizzle
& BWRITERVS_Y_X
) == BWRITERVS_Y_X
) ret
|= D3DVS_Y_X
;
411 if ((bwriter_swizzle
& BWRITERVS_Y_Y
) == BWRITERVS_Y_Y
) ret
|= D3DVS_Y_Y
;
412 if ((bwriter_swizzle
& BWRITERVS_Y_Z
) == BWRITERVS_Y_Z
) ret
|= D3DVS_Y_Z
;
413 if ((bwriter_swizzle
& BWRITERVS_Y_W
) == BWRITERVS_Y_W
) ret
|= D3DVS_Y_W
;
415 if ((bwriter_swizzle
& BWRITERVS_Z_X
) == BWRITERVS_Z_X
) ret
|= D3DVS_Z_X
;
416 if ((bwriter_swizzle
& BWRITERVS_Z_Y
) == BWRITERVS_Z_Y
) ret
|= D3DVS_Z_Y
;
417 if ((bwriter_swizzle
& BWRITERVS_Z_Z
) == BWRITERVS_Z_Z
) ret
|= D3DVS_Z_Z
;
418 if ((bwriter_swizzle
& BWRITERVS_Z_W
) == BWRITERVS_Z_W
) ret
|= D3DVS_Z_W
;
420 if ((bwriter_swizzle
& BWRITERVS_W_X
) == BWRITERVS_W_X
) ret
|= D3DVS_W_X
;
421 if ((bwriter_swizzle
& BWRITERVS_W_Y
) == BWRITERVS_W_Y
) ret
|= D3DVS_W_Y
;
422 if ((bwriter_swizzle
& BWRITERVS_W_Z
) == BWRITERVS_W_Z
) ret
|= D3DVS_W_Z
;
423 if ((bwriter_swizzle
& BWRITERVS_W_W
) == BWRITERVS_W_W
) ret
|= D3DVS_W_W
;
428 static DWORD
d3d9_writemask(DWORD bwriter_writemask
)
432 if (bwriter_writemask
& BWRITERSP_WRITEMASK_0
) ret
|= D3DSP_WRITEMASK_0
;
433 if (bwriter_writemask
& BWRITERSP_WRITEMASK_1
) ret
|= D3DSP_WRITEMASK_1
;
434 if (bwriter_writemask
& BWRITERSP_WRITEMASK_2
) ret
|= D3DSP_WRITEMASK_2
;
435 if (bwriter_writemask
& BWRITERSP_WRITEMASK_3
) ret
|= D3DSP_WRITEMASK_3
;
440 static DWORD
d3d9_srcmod(DWORD bwriter_srcmod
)
442 switch (bwriter_srcmod
)
444 case BWRITERSPSM_NONE
: return D3DSPSM_NONE
;
445 case BWRITERSPSM_NEG
: return D3DSPSM_NEG
;
446 case BWRITERSPSM_BIAS
: return D3DSPSM_BIAS
;
447 case BWRITERSPSM_BIASNEG
: return D3DSPSM_BIASNEG
;
448 case BWRITERSPSM_SIGN
: return D3DSPSM_SIGN
;
449 case BWRITERSPSM_SIGNNEG
: return D3DSPSM_SIGNNEG
;
450 case BWRITERSPSM_COMP
: return D3DSPSM_COMP
;
451 case BWRITERSPSM_X2
: return D3DSPSM_X2
;
452 case BWRITERSPSM_X2NEG
: return D3DSPSM_X2NEG
;
453 case BWRITERSPSM_DZ
: return D3DSPSM_DZ
;
454 case BWRITERSPSM_DW
: return D3DSPSM_DW
;
455 case BWRITERSPSM_ABS
: return D3DSPSM_ABS
;
456 case BWRITERSPSM_ABSNEG
: return D3DSPSM_ABSNEG
;
457 case BWRITERSPSM_NOT
: return D3DSPSM_NOT
;
459 FIXME("Unhandled BWRITERSPSM token %#x.\n", bwriter_srcmod
);
464 static DWORD
d3d9_dstmod(DWORD bwriter_mod
)
468 if (bwriter_mod
& BWRITERSPDM_SATURATE
) ret
|= D3DSPDM_SATURATE
;
469 if (bwriter_mod
& BWRITERSPDM_PARTIALPRECISION
) ret
|= D3DSPDM_PARTIALPRECISION
;
470 if (bwriter_mod
& BWRITERSPDM_MSAMPCENTROID
) ret
|= D3DSPDM_MSAMPCENTROID
;
475 static DWORD
d3d9_comparetype(DWORD asmshader_comparetype
)
477 switch (asmshader_comparetype
)
479 case BWRITER_COMPARISON_GT
: return D3DSPC_GT
;
480 case BWRITER_COMPARISON_EQ
: return D3DSPC_EQ
;
481 case BWRITER_COMPARISON_GE
: return D3DSPC_GE
;
482 case BWRITER_COMPARISON_LT
: return D3DSPC_LT
;
483 case BWRITER_COMPARISON_NE
: return D3DSPC_NE
;
484 case BWRITER_COMPARISON_LE
: return D3DSPC_LE
;
486 FIXME("Unexpected BWRITER_COMPARISON type %#x.\n", asmshader_comparetype
);
491 static DWORD
d3d9_sampler(DWORD bwriter_sampler
)
493 if (bwriter_sampler
== BWRITERSTT_UNKNOWN
) return D3DSTT_UNKNOWN
;
494 if (bwriter_sampler
== BWRITERSTT_1D
) return D3DSTT_1D
;
495 if (bwriter_sampler
== BWRITERSTT_2D
) return D3DSTT_2D
;
496 if (bwriter_sampler
== BWRITERSTT_CUBE
) return D3DSTT_CUBE
;
497 if (bwriter_sampler
== BWRITERSTT_VOLUME
) return D3DSTT_VOLUME
;
498 FIXME("Unexpected BWRITERSAMPLER_TEXTURE_TYPE type %#x.\n", bwriter_sampler
);
503 static DWORD
d3d9_register(DWORD bwriter_register
)
505 if (bwriter_register
== BWRITERSPR_TEMP
) return D3DSPR_TEMP
;
506 if (bwriter_register
== BWRITERSPR_INPUT
) return D3DSPR_INPUT
;
507 if (bwriter_register
== BWRITERSPR_CONST
) return D3DSPR_CONST
;
508 if (bwriter_register
== BWRITERSPR_ADDR
) return D3DSPR_ADDR
;
509 if (bwriter_register
== BWRITERSPR_TEXTURE
) return D3DSPR_TEXTURE
;
510 if (bwriter_register
== BWRITERSPR_RASTOUT
) return D3DSPR_RASTOUT
;
511 if (bwriter_register
== BWRITERSPR_ATTROUT
) return D3DSPR_ATTROUT
;
512 if (bwriter_register
== BWRITERSPR_TEXCRDOUT
) return D3DSPR_TEXCRDOUT
;
513 if (bwriter_register
== BWRITERSPR_OUTPUT
) return D3DSPR_OUTPUT
;
514 if (bwriter_register
== BWRITERSPR_CONSTINT
) return D3DSPR_CONSTINT
;
515 if (bwriter_register
== BWRITERSPR_COLOROUT
) return D3DSPR_COLOROUT
;
516 if (bwriter_register
== BWRITERSPR_DEPTHOUT
) return D3DSPR_DEPTHOUT
;
517 if (bwriter_register
== BWRITERSPR_SAMPLER
) return D3DSPR_SAMPLER
;
518 if (bwriter_register
== BWRITERSPR_CONSTBOOL
) return D3DSPR_CONSTBOOL
;
519 if (bwriter_register
== BWRITERSPR_LOOP
) return D3DSPR_LOOP
;
520 if (bwriter_register
== BWRITERSPR_MISCTYPE
) return D3DSPR_MISCTYPE
;
521 if (bwriter_register
== BWRITERSPR_LABEL
) return D3DSPR_LABEL
;
522 if (bwriter_register
== BWRITERSPR_PREDICATE
) return D3DSPR_PREDICATE
;
524 FIXME("Unexpected BWRITERSPR %#x.\n", bwriter_register
);
528 static DWORD
d3d9_opcode(DWORD bwriter_opcode
)
530 switch (bwriter_opcode
)
532 case BWRITERSIO_NOP
: return D3DSIO_NOP
;
533 case BWRITERSIO_MOV
: return D3DSIO_MOV
;
534 case BWRITERSIO_ADD
: return D3DSIO_ADD
;
535 case BWRITERSIO_SUB
: return D3DSIO_SUB
;
536 case BWRITERSIO_MAD
: return D3DSIO_MAD
;
537 case BWRITERSIO_MUL
: return D3DSIO_MUL
;
538 case BWRITERSIO_RCP
: return D3DSIO_RCP
;
539 case BWRITERSIO_RSQ
: return D3DSIO_RSQ
;
540 case BWRITERSIO_DP3
: return D3DSIO_DP3
;
541 case BWRITERSIO_DP4
: return D3DSIO_DP4
;
542 case BWRITERSIO_MIN
: return D3DSIO_MIN
;
543 case BWRITERSIO_MAX
: return D3DSIO_MAX
;
544 case BWRITERSIO_SLT
: return D3DSIO_SLT
;
545 case BWRITERSIO_SGE
: return D3DSIO_SGE
;
546 case BWRITERSIO_EXP
: return D3DSIO_EXP
;
547 case BWRITERSIO_LOG
: return D3DSIO_LOG
;
548 case BWRITERSIO_LIT
: return D3DSIO_LIT
;
549 case BWRITERSIO_DST
: return D3DSIO_DST
;
550 case BWRITERSIO_LRP
: return D3DSIO_LRP
;
551 case BWRITERSIO_FRC
: return D3DSIO_FRC
;
552 case BWRITERSIO_M4x4
: return D3DSIO_M4x4
;
553 case BWRITERSIO_M4x3
: return D3DSIO_M4x3
;
554 case BWRITERSIO_M3x4
: return D3DSIO_M3x4
;
555 case BWRITERSIO_M3x3
: return D3DSIO_M3x3
;
556 case BWRITERSIO_M3x2
: return D3DSIO_M3x2
;
557 case BWRITERSIO_CALL
: return D3DSIO_CALL
;
558 case BWRITERSIO_CALLNZ
: return D3DSIO_CALLNZ
;
559 case BWRITERSIO_LOOP
: return D3DSIO_LOOP
;
560 case BWRITERSIO_RET
: return D3DSIO_RET
;
561 case BWRITERSIO_ENDLOOP
: return D3DSIO_ENDLOOP
;
562 case BWRITERSIO_LABEL
: return D3DSIO_LABEL
;
563 case BWRITERSIO_DCL
: return D3DSIO_DCL
;
564 case BWRITERSIO_POW
: return D3DSIO_POW
;
565 case BWRITERSIO_CRS
: return D3DSIO_CRS
;
566 case BWRITERSIO_SGN
: return D3DSIO_SGN
;
567 case BWRITERSIO_ABS
: return D3DSIO_ABS
;
568 case BWRITERSIO_NRM
: return D3DSIO_NRM
;
569 case BWRITERSIO_SINCOS
: return D3DSIO_SINCOS
;
570 case BWRITERSIO_REP
: return D3DSIO_REP
;
571 case BWRITERSIO_ENDREP
: return D3DSIO_ENDREP
;
572 case BWRITERSIO_IF
: return D3DSIO_IF
;
573 case BWRITERSIO_IFC
: return D3DSIO_IFC
;
574 case BWRITERSIO_ELSE
: return D3DSIO_ELSE
;
575 case BWRITERSIO_ENDIF
: return D3DSIO_ENDIF
;
576 case BWRITERSIO_BREAK
: return D3DSIO_BREAK
;
577 case BWRITERSIO_BREAKC
: return D3DSIO_BREAKC
;
578 case BWRITERSIO_MOVA
: return D3DSIO_MOVA
;
579 case BWRITERSIO_DEFB
: return D3DSIO_DEFB
;
580 case BWRITERSIO_DEFI
: return D3DSIO_DEFI
;
582 case BWRITERSIO_TEXCOORD
: return D3DSIO_TEXCOORD
;
583 case BWRITERSIO_TEXKILL
: return D3DSIO_TEXKILL
;
584 case BWRITERSIO_TEX
: return D3DSIO_TEX
;
585 case BWRITERSIO_TEXBEM
: return D3DSIO_TEXBEM
;
586 case BWRITERSIO_TEXBEML
: return D3DSIO_TEXBEML
;
587 case BWRITERSIO_TEXREG2AR
: return D3DSIO_TEXREG2AR
;
588 case BWRITERSIO_TEXREG2GB
: return D3DSIO_TEXREG2GB
;
589 case BWRITERSIO_TEXM3x2PAD
: return D3DSIO_TEXM3x2PAD
;
590 case BWRITERSIO_TEXM3x2TEX
: return D3DSIO_TEXM3x2TEX
;
591 case BWRITERSIO_TEXM3x3PAD
: return D3DSIO_TEXM3x3PAD
;
592 case BWRITERSIO_TEXM3x3TEX
: return D3DSIO_TEXM3x3TEX
;
593 case BWRITERSIO_TEXM3x3SPEC
: return D3DSIO_TEXM3x3SPEC
;
594 case BWRITERSIO_TEXM3x3VSPEC
:return D3DSIO_TEXM3x3VSPEC
;
595 case BWRITERSIO_EXPP
: return D3DSIO_EXPP
;
596 case BWRITERSIO_LOGP
: return D3DSIO_LOGP
;
597 case BWRITERSIO_CND
: return D3DSIO_CND
;
598 case BWRITERSIO_DEF
: return D3DSIO_DEF
;
599 case BWRITERSIO_TEXREG2RGB
: return D3DSIO_TEXREG2RGB
;
600 case BWRITERSIO_TEXDP3TEX
: return D3DSIO_TEXDP3TEX
;
601 case BWRITERSIO_TEXM3x2DEPTH
:return D3DSIO_TEXM3x2DEPTH
;
602 case BWRITERSIO_TEXDP3
: return D3DSIO_TEXDP3
;
603 case BWRITERSIO_TEXM3x3
: return D3DSIO_TEXM3x3
;
604 case BWRITERSIO_TEXDEPTH
: return D3DSIO_TEXDEPTH
;
605 case BWRITERSIO_CMP
: return D3DSIO_CMP
;
606 case BWRITERSIO_BEM
: return D3DSIO_BEM
;
607 case BWRITERSIO_DP2ADD
: return D3DSIO_DP2ADD
;
608 case BWRITERSIO_DSX
: return D3DSIO_DSX
;
609 case BWRITERSIO_DSY
: return D3DSIO_DSY
;
610 case BWRITERSIO_TEXLDD
: return D3DSIO_TEXLDD
;
611 case BWRITERSIO_SETP
: return D3DSIO_SETP
;
612 case BWRITERSIO_TEXLDL
: return D3DSIO_TEXLDL
;
613 case BWRITERSIO_BREAKP
: return D3DSIO_BREAKP
;
615 case BWRITERSIO_PHASE
: return D3DSIO_PHASE
;
616 case BWRITERSIO_COMMENT
: return D3DSIO_COMMENT
;
617 case BWRITERSIO_END
: return D3DSIO_END
;
619 case BWRITERSIO_TEXLDP
: return D3DSIO_TEX
| D3DSI_TEXLD_PROJECT
;
620 case BWRITERSIO_TEXLDB
: return D3DSIO_TEX
| D3DSI_TEXLD_BIAS
;
623 FIXME("Unhandled BWRITERSIO token %#x.\n", bwriter_opcode
);
628 static DWORD
d3dsp_register( D3DSHADER_PARAM_REGISTER_TYPE type
, DWORD num
)
630 return ((type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
) |
631 ((type
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
) |
632 (num
& D3DSP_REGNUM_MASK
); /* No shift */
635 /******************************************************
636 * Implementation of the writer functions starts here *
637 ******************************************************/
638 static void write_declarations(struct bc_writer
*This
, struct bytecode_buffer
*buffer
,
639 const struct declaration
*decls
, unsigned int num
, DWORD type
)
642 DWORD instr_dcl
= D3DSIO_DCL
;
644 struct shader_reg reg
;
646 ZeroMemory(®
, sizeof(reg
));
648 if (This
->shader
->major_version
> 1)
649 instr_dcl
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
651 for(i
= 0; i
< num
; i
++) {
652 if(decls
[i
].builtin
) continue;
654 /* Write the DCL instruction */
655 put_dword(buffer
, instr_dcl
);
657 /* Write the usage and index */
658 token
= (1u << 31); /* Bit 31 of non-instruction opcodes is 1 */
659 token
|= (decls
[i
].usage
<< D3DSP_DCL_USAGE_SHIFT
) & D3DSP_DCL_USAGE_MASK
;
660 token
|= (decls
[i
].usage_idx
<< D3DSP_DCL_USAGEINDEX_SHIFT
) & D3DSP_DCL_USAGEINDEX_MASK
;
661 put_dword(buffer
, token
);
663 /* Write the dest register */
665 reg
.regnum
= decls
[i
].regnum
;
666 reg
.u
.writemask
= decls
[i
].writemask
;
667 This
->funcs
->dstreg(This
, ®
, buffer
, 0, decls
[i
].mod
);
671 static void write_const(struct constant
**consts
, int num
, DWORD opcode
, DWORD reg_type
, struct bytecode_buffer
*buffer
, BOOL len
) {
673 DWORD instr_def
= opcode
;
674 const DWORD reg
= (1u << 31) | d3dsp_register( reg_type
, 0 ) | D3DSP_WRITEMASK_ALL
;
677 if(opcode
== D3DSIO_DEFB
)
678 instr_def
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
680 instr_def
|= 5 << D3DSI_INSTLENGTH_SHIFT
;
683 for(i
= 0; i
< num
; i
++) {
684 /* Write the DEF instruction */
685 put_dword(buffer
, instr_def
);
687 put_dword(buffer
, reg
| (consts
[i
]->regnum
& D3DSP_REGNUM_MASK
));
688 put_dword(buffer
, consts
[i
]->value
[0].d
);
689 if(opcode
!= D3DSIO_DEFB
) {
690 put_dword(buffer
, consts
[i
]->value
[1].d
);
691 put_dword(buffer
, consts
[i
]->value
[2].d
);
692 put_dword(buffer
, consts
[i
]->value
[3].d
);
697 static void write_constF(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
698 write_const(shader
->constF
, shader
->num_cf
, D3DSIO_DEF
, D3DSPR_CONST
, buffer
, len
);
701 /* This function looks for VS 1/2 registers mapping to VS 3 output registers */
702 static HRESULT
vs_find_builtin_varyings(struct bc_writer
*This
, const struct bwriter_shader
*shader
) {
704 DWORD usage
, usage_idx
, writemask
, regnum
;
706 for(i
= 0; i
< shader
->num_outputs
; i
++) {
707 if(!shader
->outputs
[i
].builtin
) continue;
709 usage
= shader
->outputs
[i
].usage
;
710 usage_idx
= shader
->outputs
[i
].usage_idx
;
711 writemask
= shader
->outputs
[i
].writemask
;
712 regnum
= shader
->outputs
[i
].regnum
;
715 case BWRITERDECLUSAGE_POSITION
:
716 case BWRITERDECLUSAGE_POSITIONT
:
718 WARN("dcl_position%u not supported in sm 1/2 shaders\n", usage_idx
);
721 TRACE("o%u is oPos\n", regnum
);
722 This
->oPos_regnum
= regnum
;
725 case BWRITERDECLUSAGE_COLOR
:
727 WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx
);
730 if(writemask
!= BWRITERSP_WRITEMASK_ALL
) {
731 WARN("Only WRITEMASK_ALL is supported on color in sm 1/2\n");
734 TRACE("o%u is oD%u\n", regnum
, usage_idx
);
735 This
->oD_regnum
[usage_idx
] = regnum
;
738 case BWRITERDECLUSAGE_TEXCOORD
:
740 WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx
);
743 if(writemask
!= (BWRITERSP_WRITEMASK_0
) &&
744 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
) &&
745 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
| BWRITERSP_WRITEMASK_2
) &&
746 writemask
!= (BWRITERSP_WRITEMASK_ALL
)) {
747 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
750 TRACE("o%u is oT%u\n", regnum
, usage_idx
);
751 This
->oT_regnum
[usage_idx
] = regnum
;
754 case BWRITERDECLUSAGE_PSIZE
:
756 WARN("dcl_psize%u not supported in sm 1/2 shaders\n", usage_idx
);
759 TRACE("o%u writemask 0x%08x is oPts\n", regnum
, writemask
);
760 This
->oPts_regnum
= regnum
;
761 This
->oPts_mask
= writemask
;
764 case BWRITERDECLUSAGE_FOG
:
766 WARN("dcl_fog%u not supported in sm 1 shaders\n", usage_idx
);
769 if(writemask
!= BWRITERSP_WRITEMASK_0
&& writemask
!= BWRITERSP_WRITEMASK_1
&&
770 writemask
!= BWRITERSP_WRITEMASK_2
&& writemask
!= BWRITERSP_WRITEMASK_3
) {
771 WARN("Unsupported fog writemask\n");
774 TRACE("o%u writemask 0x%08x is oFog\n", regnum
, writemask
);
775 This
->oFog_regnum
= regnum
;
776 This
->oFog_mask
= writemask
;
780 WARN("Varying type %u is not supported in shader model 1.x\n", usage
);
788 static void vs_1_x_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
791 if(shader
->num_ci
|| shader
->num_cb
) {
792 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
793 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
794 This
->state
= E_INVALIDARG
;
798 hr
= vs_find_builtin_varyings(This
, shader
);
804 write_declarations(This
, buffer
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
805 write_constF(shader
, buffer
, FALSE
);
808 static HRESULT
find_ps_builtin_semantics(struct bc_writer
*This
,
809 const struct bwriter_shader
*shader
,
812 DWORD usage
, usage_idx
, writemask
, regnum
;
814 This
->v_regnum
[0] = -1; This
->v_regnum
[1] = -1;
815 for(i
= 0; i
< 8; i
++) This
->t_regnum
[i
] = -1;
817 for(i
= 0; i
< shader
->num_inputs
; i
++) {
818 if(!shader
->inputs
[i
].builtin
) continue;
820 usage
= shader
->inputs
[i
].usage
;
821 usage_idx
= shader
->inputs
[i
].usage_idx
;
822 writemask
= shader
->inputs
[i
].writemask
;
823 regnum
= shader
->inputs
[i
].regnum
;
826 case BWRITERDECLUSAGE_COLOR
:
828 WARN("dcl_color%u not supported in sm 1 shaders\n", usage_idx
);
831 if(writemask
!= BWRITERSP_WRITEMASK_ALL
) {
832 WARN("Only WRITEMASK_ALL is supported on color in sm 1\n");
835 TRACE("v%u is v%u\n", regnum
, usage_idx
);
836 This
->v_regnum
[usage_idx
] = regnum
;
839 case BWRITERDECLUSAGE_TEXCOORD
:
840 if(usage_idx
> texcoords
) {
841 WARN("dcl_texcoord%u not supported in this shader version\n", usage_idx
);
844 if(writemask
!= (BWRITERSP_WRITEMASK_0
) &&
845 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
) &&
846 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
| BWRITERSP_WRITEMASK_2
) &&
847 writemask
!= (BWRITERSP_WRITEMASK_ALL
)) {
848 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
850 writemask
= BWRITERSP_WRITEMASK_ALL
;
852 TRACE("v%u is t%u\n", regnum
, usage_idx
);
853 This
->t_regnum
[usage_idx
] = regnum
;
857 WARN("Varying type %u is not supported in shader model 1.x\n", usage
);
865 static void ps_1_x_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
868 /* First check the constants and varyings, and complain if unsupported things are used */
869 if(shader
->num_ci
|| shader
->num_cb
) {
870 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
871 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
872 This
->state
= E_INVALIDARG
;
876 hr
= find_ps_builtin_semantics(This
, shader
, 4);
882 write_constF(shader
, buffer
, FALSE
);
885 static void ps_1_4_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
888 /* First check the constants and varyings, and complain if unsupported things are used */
889 if(shader
->num_ci
|| shader
->num_cb
) {
890 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
891 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
892 This
->state
= E_INVALIDARG
;
895 hr
= find_ps_builtin_semantics(This
, shader
, 6);
901 write_constF(shader
, buffer
, FALSE
);
904 static void end(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
905 put_dword(buffer
, D3DSIO_END
);
908 static DWORD
map_vs_output(struct bc_writer
*This
, DWORD regnum
, DWORD mask
, DWORD
*has_components
) {
911 *has_components
= TRUE
;
912 if(regnum
== This
->oPos_regnum
) {
913 return d3dsp_register( D3DSPR_RASTOUT
, D3DSRO_POSITION
);
915 if(regnum
== This
->oFog_regnum
&& mask
== This
->oFog_mask
) {
916 *has_components
= FALSE
;
917 return d3dsp_register( D3DSPR_RASTOUT
, D3DSRO_FOG
) | D3DSP_WRITEMASK_ALL
;
919 if(regnum
== This
->oPts_regnum
&& mask
== This
->oPts_mask
) {
920 *has_components
= FALSE
;
921 return d3dsp_register( D3DSPR_RASTOUT
, D3DSRO_POINT_SIZE
) | D3DSP_WRITEMASK_ALL
;
923 for(i
= 0; i
< 2; i
++) {
924 if(regnum
== This
->oD_regnum
[i
]) {
925 return d3dsp_register( D3DSPR_ATTROUT
, i
);
928 for(i
= 0; i
< 8; i
++) {
929 if(regnum
== This
->oT_regnum
[i
]) {
930 return d3dsp_register( D3DSPR_TEXCRDOUT
, i
);
934 /* The varying must be undeclared - if an unsupported varying was declared,
935 * the vs_find_builtin_varyings function would have caught it and this code
937 WARN("Undeclared varying %u\n", regnum
);
938 This
->state
= E_INVALIDARG
;
942 static void vs_12_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
943 struct bytecode_buffer
*buffer
,
944 DWORD shift
, DWORD mod
) {
945 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
949 WARN("Relative addressing not supported for destination registers\n");
950 This
->state
= E_INVALIDARG
;
955 case BWRITERSPR_OUTPUT
:
956 token
|= map_vs_output(This
, reg
->regnum
, reg
->u
.writemask
, &has_wmask
);
959 case BWRITERSPR_RASTOUT
:
960 case BWRITERSPR_ATTROUT
:
961 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
962 * but are unexpected. If we hit this path it might be due to an error.
964 FIXME("Unexpected register type %u\n", reg
->type
);
966 case BWRITERSPR_INPUT
:
967 case BWRITERSPR_TEMP
:
968 case BWRITERSPR_CONST
:
969 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
973 case BWRITERSPR_ADDR
:
974 if(reg
->regnum
!= 0) {
975 WARN("Only a0 exists\n");
976 This
->state
= E_INVALIDARG
;
979 token
|= d3dsp_register( D3DSPR_ADDR
, 0 );
983 case BWRITERSPR_PREDICATE
:
984 if (This
->shader
->major_version
!= 2 || This
->shader
->minor_version
!= 1)
986 WARN("Predicate register is allowed only in vs_2_x\n");
987 This
->state
= E_INVALIDARG
;
990 if(reg
->regnum
!= 0) {
991 WARN("Only predicate register p0 exists\n");
992 This
->state
= E_INVALIDARG
;
995 token
|= d3dsp_register( D3DSPR_PREDICATE
, 0 );
1000 WARN("Invalid register type for 1.x-2.x vertex shader\n");
1001 This
->state
= E_INVALIDARG
;
1005 /* strictly speaking there are no modifiers in vs_2_0 and vs_1_x, but they can be written
1006 * into the bytecode and since the compiler doesn't do such checks write them
1007 * (the checks are done by the undocumented shader validator)
1009 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1010 token
|= d3d9_dstmod(mod
);
1013 token
|= d3d9_writemask(reg
->u
.writemask
);
1015 put_dword(buffer
, token
);
1018 static void vs_1_x_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1019 struct bytecode_buffer
*buffer
) {
1020 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1025 case BWRITERSPR_OUTPUT
:
1026 /* Map the swizzle to a writemask, the format expected
1029 switch(reg
->u
.swizzle
) {
1030 case BWRITERVS_SWIZZLE_X
:
1031 component
= BWRITERSP_WRITEMASK_0
;
1033 case BWRITERVS_SWIZZLE_Y
:
1034 component
= BWRITERSP_WRITEMASK_1
;
1036 case BWRITERVS_SWIZZLE_Z
:
1037 component
= BWRITERSP_WRITEMASK_2
;
1039 case BWRITERVS_SWIZZLE_W
:
1040 component
= BWRITERSP_WRITEMASK_3
;
1045 token
|= map_vs_output(This
, reg
->regnum
, component
, &has_swizzle
);
1048 case BWRITERSPR_RASTOUT
:
1049 case BWRITERSPR_ATTROUT
:
1050 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1051 * but are unexpected. If we hit this path it might be due to an error.
1053 FIXME("Unexpected register type %u\n", reg
->type
);
1055 case BWRITERSPR_INPUT
:
1056 case BWRITERSPR_TEMP
:
1057 case BWRITERSPR_CONST
:
1058 case BWRITERSPR_ADDR
:
1059 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1061 if(reg
->rel_reg
->type
!= BWRITERSPR_ADDR
||
1062 reg
->rel_reg
->regnum
!= 0 ||
1063 reg
->rel_reg
->u
.swizzle
!= BWRITERVS_SWIZZLE_X
) {
1064 WARN("Relative addressing in vs_1_x is only allowed with a0.x\n");
1065 This
->state
= E_INVALIDARG
;
1068 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1073 WARN("Invalid register type for 1.x vshader\n");
1074 This
->state
= E_INVALIDARG
;
1078 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1080 token
|= d3d9_srcmod(reg
->srcmod
);
1081 put_dword(buffer
, token
);
1084 static void write_srcregs(struct bc_writer
*This
, const struct instruction
*instr
,
1085 struct bytecode_buffer
*buffer
){
1087 if(instr
->has_predicate
){
1088 This
->funcs
->srcreg(This
, &instr
->predicate
, buffer
);
1090 for(i
= 0; i
< instr
->num_srcs
; i
++){
1091 This
->funcs
->srcreg(This
, &instr
->src
[i
], buffer
);
1095 static DWORD
map_ps13_temp(struct bc_writer
*This
, const struct shader_reg
*reg
) {
1096 if(reg
->regnum
== T0_REG
) {
1097 return d3dsp_register( D3DSPR_TEXTURE
, 0 );
1098 } else if(reg
->regnum
== T1_REG
) {
1099 return d3dsp_register( D3DSPR_TEXTURE
, 1 );
1100 } else if(reg
->regnum
== T2_REG
) {
1101 return d3dsp_register( D3DSPR_TEXTURE
, 2 );
1102 } else if(reg
->regnum
== T3_REG
) {
1103 return d3dsp_register( D3DSPR_TEXTURE
, 3 );
1105 return d3dsp_register( D3DSPR_TEMP
, reg
->regnum
);
1109 static DWORD
map_ps_input(struct bc_writer
*This
,
1110 const struct shader_reg
*reg
) {
1112 /* Map color interpolators */
1113 for(i
= 0; i
< 2; i
++) {
1114 if(reg
->regnum
== This
->v_regnum
[i
]) {
1115 return d3dsp_register( D3DSPR_INPUT
, i
);
1118 for(i
= 0; i
< 8; i
++) {
1119 if(reg
->regnum
== This
->t_regnum
[i
]) {
1120 return d3dsp_register( D3DSPR_TEXTURE
, i
);
1124 WARN("Invalid ps 1/2 varying\n");
1125 This
->state
= E_INVALIDARG
;
1129 static void ps_1_0123_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1130 struct bytecode_buffer
*buffer
) {
1131 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1133 WARN("Relative addressing not supported in <= ps_3_0\n");
1134 This
->state
= E_INVALIDARG
;
1139 case BWRITERSPR_INPUT
:
1140 token
|= map_ps_input(This
, reg
);
1143 /* Take care about the texture temporaries. There's a problem: They aren't
1144 * declared anywhere, so we can only hardcode the values that are used
1145 * to map ps_1_3 shaders to the common shader structure
1147 case BWRITERSPR_TEMP
:
1148 token
|= map_ps13_temp(This
, reg
);
1151 case BWRITERSPR_CONST
: /* Can be mapped 1:1 */
1152 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1156 WARN("Invalid register type for <= ps_1_3 shader\n");
1157 This
->state
= E_INVALIDARG
;
1161 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1163 if(reg
->srcmod
== BWRITERSPSM_DZ
|| reg
->srcmod
== BWRITERSPSM_DW
||
1164 reg
->srcmod
== BWRITERSPSM_ABS
|| reg
->srcmod
== BWRITERSPSM_ABSNEG
||
1165 reg
->srcmod
== BWRITERSPSM_NOT
) {
1166 WARN("Invalid source modifier %u for <= ps_1_3\n", reg
->srcmod
);
1167 This
->state
= E_INVALIDARG
;
1170 token
|= d3d9_srcmod(reg
->srcmod
);
1171 put_dword(buffer
, token
);
1174 static void ps_1_0123_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1175 struct bytecode_buffer
*buffer
,
1176 DWORD shift
, DWORD mod
) {
1177 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1180 WARN("Relative addressing not supported for destination registers\n");
1181 This
->state
= E_INVALIDARG
;
1186 case BWRITERSPR_TEMP
:
1187 token
|= map_ps13_temp(This
, reg
);
1190 /* texkill uses the input register as a destination parameter */
1191 case BWRITERSPR_INPUT
:
1192 token
|= map_ps_input(This
, reg
);
1196 WARN("Invalid dest register type for 1.x pshader\n");
1197 This
->state
= E_INVALIDARG
;
1201 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1202 token
|= d3d9_dstmod(mod
);
1204 token
|= d3d9_writemask(reg
->u
.writemask
);
1205 put_dword(buffer
, token
);
1208 /* The length of an instruction consists of the destination register (if any),
1209 * the number of source registers, the number of address registers used for
1210 * indirect addressing, and optionally the predicate register
1212 static DWORD
instrlen(const struct instruction
*instr
, unsigned int srcs
, unsigned int dsts
) {
1214 DWORD ret
= srcs
+ dsts
+ (instr
->has_predicate
? 1 : 0);
1217 if(instr
->dst
.rel_reg
) ret
++;
1219 for(i
= 0; i
< srcs
; i
++) {
1220 if(instr
->src
[i
].rel_reg
) ret
++;
1225 static void sm_1_x_opcode(struct bc_writer
*This
,
1226 const struct instruction
*instr
,
1227 DWORD token
, struct bytecode_buffer
*buffer
) {
1228 /* In sm_1_x instruction length isn't encoded */
1230 token
|= D3DSI_COISSUE
;
1232 put_dword(buffer
, token
);
1235 static void instr_handler(struct bc_writer
*This
,
1236 const struct instruction
*instr
,
1237 struct bytecode_buffer
*buffer
) {
1238 DWORD token
= d3d9_opcode(instr
->opcode
);
1240 This
->funcs
->opcode(This
, instr
, token
, buffer
);
1241 if(instr
->has_dst
) This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1242 write_srcregs(This
, instr
, buffer
);
1245 static const struct instr_handler_table vs_1_x_handlers
[] = {
1246 {BWRITERSIO_ADD
, instr_handler
},
1247 {BWRITERSIO_NOP
, instr_handler
},
1248 {BWRITERSIO_MOV
, instr_handler
},
1249 {BWRITERSIO_SUB
, instr_handler
},
1250 {BWRITERSIO_MAD
, instr_handler
},
1251 {BWRITERSIO_MUL
, instr_handler
},
1252 {BWRITERSIO_RCP
, instr_handler
},
1253 {BWRITERSIO_RSQ
, instr_handler
},
1254 {BWRITERSIO_DP3
, instr_handler
},
1255 {BWRITERSIO_DP4
, instr_handler
},
1256 {BWRITERSIO_MIN
, instr_handler
},
1257 {BWRITERSIO_MAX
, instr_handler
},
1258 {BWRITERSIO_SLT
, instr_handler
},
1259 {BWRITERSIO_SGE
, instr_handler
},
1260 {BWRITERSIO_EXP
, instr_handler
},
1261 {BWRITERSIO_LOG
, instr_handler
},
1262 {BWRITERSIO_EXPP
, instr_handler
},
1263 {BWRITERSIO_LOGP
, instr_handler
},
1264 {BWRITERSIO_DST
, instr_handler
},
1265 {BWRITERSIO_FRC
, instr_handler
},
1266 {BWRITERSIO_M4x4
, instr_handler
},
1267 {BWRITERSIO_M4x3
, instr_handler
},
1268 {BWRITERSIO_M3x4
, instr_handler
},
1269 {BWRITERSIO_M3x3
, instr_handler
},
1270 {BWRITERSIO_M3x2
, instr_handler
},
1271 {BWRITERSIO_LIT
, instr_handler
},
1273 {BWRITERSIO_END
, NULL
}, /* Sentinel value, it signals
1274 the end of the list */
1277 static const struct bytecode_backend vs_1_x_backend
= {
1286 static void instr_ps_1_0123_texld(struct bc_writer
*This
,
1287 const struct instruction
*instr
,
1288 struct bytecode_buffer
*buffer
) {
1290 struct shader_reg reg
;
1293 if(instr
->src
[1].type
!= BWRITERSPR_SAMPLER
||
1294 instr
->src
[1].regnum
> 3) {
1295 WARN("Unsupported sampler type %u regnum %u\n",
1296 instr
->src
[1].type
, instr
->src
[1].regnum
);
1297 This
->state
= E_INVALIDARG
;
1299 } else if(instr
->dst
.type
!= BWRITERSPR_TEMP
) {
1300 WARN("Can only sample into a temp register\n");
1301 This
->state
= E_INVALIDARG
;
1305 idx
= instr
->src
[1].regnum
;
1306 if((idx
== 0 && instr
->dst
.regnum
!= T0_REG
) ||
1307 (idx
== 1 && instr
->dst
.regnum
!= T1_REG
) ||
1308 (idx
== 2 && instr
->dst
.regnum
!= T2_REG
) ||
1309 (idx
== 3 && instr
->dst
.regnum
!= T3_REG
)) {
1310 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_x\n",
1311 idx
, instr
->dst
.regnum
);
1312 This
->state
= E_INVALIDARG
;
1315 if(instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1316 /* A simple non-dependent read tex instruction */
1317 if(instr
->src
[0].regnum
!= This
->t_regnum
[idx
]) {
1318 WARN("Cannot sample from s%u with texture address data from interpolator %u\n",
1319 idx
, instr
->src
[0].regnum
);
1320 This
->state
= E_INVALIDARG
;
1323 This
->funcs
->opcode(This
, instr
, D3DSIO_TEX
& D3DSI_OPCODE_MASK
, buffer
);
1325 /* map the temp dstreg to the ps_1_3 texture temporary register */
1326 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1327 } else if(instr
->src
[0].type
== BWRITERSPR_TEMP
) {
1329 swizzlemask
= 3 | (3 << 2) | (3 << 4);
1330 if((instr
->src
[0].u
.swizzle
& swizzlemask
) == (BWRITERVS_X_X
| BWRITERVS_Y_Y
| BWRITERVS_Z_Z
)) {
1331 TRACE("writing texreg2rgb\n");
1332 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2RGB
& D3DSI_OPCODE_MASK
, buffer
);
1333 } else if(instr
->src
[0].u
.swizzle
== (BWRITERVS_X_W
| BWRITERVS_Y_X
| BWRITERVS_Z_X
| BWRITERVS_W_X
)) {
1334 TRACE("writing texreg2ar\n");
1335 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2AR
& D3DSI_OPCODE_MASK
, buffer
);
1336 } else if(instr
->src
[0].u
.swizzle
== (BWRITERVS_X_Y
| BWRITERVS_Y_Z
| BWRITERVS_Z_Z
| BWRITERVS_W_Z
)) {
1337 TRACE("writing texreg2gb\n");
1338 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2GB
& D3DSI_OPCODE_MASK
, buffer
);
1340 WARN("Unsupported src addr swizzle in dependent texld: 0x%08x\n", instr
->src
[0].u
.swizzle
);
1341 This
->state
= E_INVALIDARG
;
1345 /* Dst and src reg can be mapped normally. Both registers are temporary registers in the
1346 * source shader and have to be mapped to the temporary form of the texture registers. However,
1347 * the src reg doesn't have a swizzle
1349 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1350 reg
= instr
->src
[0];
1351 reg
.u
.swizzle
= BWRITERVS_NOSWIZZLE
;
1352 This
->funcs
->srcreg(This
, ®
, buffer
);
1354 WARN("Invalid address data source register\n");
1355 This
->state
= E_INVALIDARG
;
1360 static void instr_ps_1_0123_mov(struct bc_writer
*This
,
1361 const struct instruction
*instr
,
1362 struct bytecode_buffer
*buffer
) {
1363 DWORD token
= D3DSIO_MOV
& D3DSI_OPCODE_MASK
;
1365 if(instr
->dst
.type
== BWRITERSPR_TEMP
&& instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1366 if((instr
->dst
.regnum
== T0_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[0]) ||
1367 (instr
->dst
.regnum
== T1_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[1]) ||
1368 (instr
->dst
.regnum
== T2_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[2]) ||
1369 (instr
->dst
.regnum
== T3_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[3])) {
1370 if(instr
->dstmod
& BWRITERSPDM_SATURATE
) {
1371 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXCOORD
& D3DSI_OPCODE_MASK
, buffer
);
1372 /* Remove the SATURATE flag, it's implicit to the instruction */
1373 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
& (~BWRITERSPDM_SATURATE
));
1376 WARN("A varying -> temp copy is only supported with the SATURATE modifier in <=ps_1_3\n");
1377 This
->state
= E_INVALIDARG
;
1380 } else if(instr
->src
[0].regnum
== This
->v_regnum
[0] ||
1381 instr
->src
[0].regnum
== This
->v_regnum
[1]) {
1382 /* Handled by the normal mov below. Just drop out of the if condition */
1384 WARN("Unsupported varying -> temp mov in <= ps_1_3\n");
1385 This
->state
= E_INVALIDARG
;
1390 This
->funcs
->opcode(This
, instr
, token
, buffer
);
1391 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1392 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1395 static const struct instr_handler_table ps_1_0123_handlers
[] = {
1396 {BWRITERSIO_ADD
, instr_handler
},
1397 {BWRITERSIO_NOP
, instr_handler
},
1398 {BWRITERSIO_MOV
, instr_ps_1_0123_mov
},
1399 {BWRITERSIO_SUB
, instr_handler
},
1400 {BWRITERSIO_MAD
, instr_handler
},
1401 {BWRITERSIO_MUL
, instr_handler
},
1402 {BWRITERSIO_DP3
, instr_handler
},
1403 {BWRITERSIO_DP4
, instr_handler
},
1404 {BWRITERSIO_LRP
, instr_handler
},
1406 /* pshader instructions */
1407 {BWRITERSIO_CND
, instr_handler
},
1408 {BWRITERSIO_CMP
, instr_handler
},
1409 {BWRITERSIO_TEXKILL
, instr_handler
},
1410 {BWRITERSIO_TEX
, instr_ps_1_0123_texld
},
1411 {BWRITERSIO_TEXBEM
, instr_handler
},
1412 {BWRITERSIO_TEXBEML
, instr_handler
},
1413 {BWRITERSIO_TEXM3x2PAD
, instr_handler
},
1414 {BWRITERSIO_TEXM3x3PAD
, instr_handler
},
1415 {BWRITERSIO_TEXM3x3SPEC
, instr_handler
},
1416 {BWRITERSIO_TEXM3x3VSPEC
, instr_handler
},
1417 {BWRITERSIO_TEXM3x3TEX
, instr_handler
},
1418 {BWRITERSIO_TEXM3x3
, instr_handler
},
1419 {BWRITERSIO_TEXM3x2DEPTH
, instr_handler
},
1420 {BWRITERSIO_TEXM3x2TEX
, instr_handler
},
1421 {BWRITERSIO_TEXDP3
, instr_handler
},
1422 {BWRITERSIO_TEXDP3TEX
, instr_handler
},
1423 {BWRITERSIO_END
, NULL
},
1426 static const struct bytecode_backend ps_1_0123_backend
= {
1435 static void ps_1_4_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1436 struct bytecode_buffer
*buffer
) {
1437 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1439 WARN("Relative addressing not supported in <= ps_3_0\n");
1440 This
->state
= E_INVALIDARG
;
1445 case BWRITERSPR_INPUT
:
1446 token
|= map_ps_input(This
, reg
);
1449 /* Can be mapped 1:1 */
1450 case BWRITERSPR_TEMP
:
1451 case BWRITERSPR_CONST
:
1452 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1456 WARN("Invalid register type for ps_1_4 shader\n");
1457 This
->state
= E_INVALIDARG
;
1461 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1463 if(reg
->srcmod
== BWRITERSPSM_ABS
|| reg
->srcmod
== BWRITERSPSM_ABSNEG
||
1464 reg
->srcmod
== BWRITERSPSM_NOT
) {
1465 WARN("Invalid source modifier %u for ps_1_4\n", reg
->srcmod
);
1466 This
->state
= E_INVALIDARG
;
1469 token
|= d3d9_srcmod(reg
->srcmod
);
1470 put_dword(buffer
, token
);
1473 static void ps_1_4_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1474 struct bytecode_buffer
*buffer
,
1475 DWORD shift
, DWORD mod
) {
1476 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1479 WARN("Relative addressing not supported for destination registers\n");
1480 This
->state
= E_INVALIDARG
;
1485 case BWRITERSPR_TEMP
: /* 1:1 mapping */
1486 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1490 case BWRITERSPR_INPUT
:
1491 token
|= map_ps_input(This
, reg
);
1495 WARN("Invalid dest register type for 1.x pshader\n");
1496 This
->state
= E_INVALIDARG
;
1500 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1501 token
|= d3d9_dstmod(mod
);
1503 token
|= d3d9_writemask(reg
->u
.writemask
);
1504 put_dword(buffer
, token
);
1507 static void instr_ps_1_4_mov(struct bc_writer
*This
,
1508 const struct instruction
*instr
,
1509 struct bytecode_buffer
*buffer
) {
1510 DWORD token
= D3DSIO_MOV
& D3DSI_OPCODE_MASK
;
1512 if(instr
->dst
.type
== BWRITERSPR_TEMP
&& instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1513 if(instr
->src
[0].regnum
== This
->t_regnum
[0] ||
1514 instr
->src
[0].regnum
== This
->t_regnum
[1] ||
1515 instr
->src
[0].regnum
== This
->t_regnum
[2] ||
1516 instr
->src
[0].regnum
== This
->t_regnum
[3] ||
1517 instr
->src
[0].regnum
== This
->t_regnum
[4] ||
1518 instr
->src
[0].regnum
== This
->t_regnum
[5]) {
1519 /* Similar to a regular mov, but a different opcode */
1520 token
= D3DSIO_TEXCOORD
& D3DSI_OPCODE_MASK
;
1521 } else if(instr
->src
[0].regnum
== This
->v_regnum
[0] ||
1522 instr
->src
[0].regnum
== This
->v_regnum
[1]) {
1523 /* Handled by the normal mov below. Just drop out of the if condition */
1525 WARN("Unsupported varying -> temp mov in ps_1_4\n");
1526 This
->state
= E_INVALIDARG
;
1531 This
->funcs
->opcode(This
, instr
, token
, buffer
);
1532 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1533 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1536 static void instr_ps_1_4_texld(struct bc_writer
*This
,
1537 const struct instruction
*instr
,
1538 struct bytecode_buffer
*buffer
) {
1539 if(instr
->src
[1].type
!= BWRITERSPR_SAMPLER
||
1540 instr
->src
[1].regnum
> 5) {
1541 WARN("Unsupported sampler type %u regnum %u\n",
1542 instr
->src
[1].type
, instr
->src
[1].regnum
);
1543 This
->state
= E_INVALIDARG
;
1545 } else if(instr
->dst
.type
!= BWRITERSPR_TEMP
) {
1546 WARN("Can only sample into a temp register\n");
1547 This
->state
= E_INVALIDARG
;
1551 if(instr
->src
[1].regnum
!= instr
->dst
.regnum
) {
1552 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_4\n",
1553 instr
->src
[1].regnum
, instr
->dst
.regnum
);
1554 This
->state
= E_INVALIDARG
;
1558 This
->funcs
->opcode(This
, instr
, D3DSIO_TEX
& D3DSI_OPCODE_MASK
, buffer
);
1559 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1560 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1563 static const struct instr_handler_table ps_1_4_handlers
[] = {
1564 {BWRITERSIO_ADD
, instr_handler
},
1565 {BWRITERSIO_NOP
, instr_handler
},
1566 {BWRITERSIO_MOV
, instr_ps_1_4_mov
},
1567 {BWRITERSIO_SUB
, instr_handler
},
1568 {BWRITERSIO_MAD
, instr_handler
},
1569 {BWRITERSIO_MUL
, instr_handler
},
1570 {BWRITERSIO_DP3
, instr_handler
},
1571 {BWRITERSIO_DP4
, instr_handler
},
1572 {BWRITERSIO_LRP
, instr_handler
},
1574 /* pshader instructions */
1575 {BWRITERSIO_CND
, instr_handler
},
1576 {BWRITERSIO_CMP
, instr_handler
},
1577 {BWRITERSIO_TEXKILL
, instr_handler
},
1578 {BWRITERSIO_TEX
, instr_ps_1_4_texld
},
1579 {BWRITERSIO_TEXDEPTH
, instr_handler
},
1580 {BWRITERSIO_BEM
, instr_handler
},
1582 {BWRITERSIO_PHASE
, instr_handler
},
1583 {BWRITERSIO_END
, NULL
},
1586 static const struct bytecode_backend ps_1_4_backend
= {
1595 static void write_constB(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
1596 write_const(shader
->constB
, shader
->num_cb
, D3DSIO_DEFB
, D3DSPR_CONSTBOOL
, buffer
, len
);
1599 static void write_constI(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
1600 write_const(shader
->constI
, shader
->num_ci
, D3DSIO_DEFI
, D3DSPR_CONSTINT
, buffer
, len
);
1603 static void vs_2_header(struct bc_writer
*This
,
1604 const struct bwriter_shader
*shader
,
1605 struct bytecode_buffer
*buffer
) {
1608 hr
= vs_find_builtin_varyings(This
, shader
);
1614 write_declarations(This
, buffer
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
1615 write_constF(shader
, buffer
, TRUE
);
1616 write_constB(shader
, buffer
, TRUE
);
1617 write_constI(shader
, buffer
, TRUE
);
1620 static void vs_2_srcreg(struct bc_writer
*This
,
1621 const struct shader_reg
*reg
,
1622 struct bytecode_buffer
*buffer
) {
1623 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1629 case BWRITERSPR_OUTPUT
:
1630 /* Map the swizzle to a writemask, the format expected
1633 switch(reg
->u
.swizzle
) {
1634 case BWRITERVS_SWIZZLE_X
:
1635 component
= BWRITERSP_WRITEMASK_0
;
1637 case BWRITERVS_SWIZZLE_Y
:
1638 component
= BWRITERSP_WRITEMASK_1
;
1640 case BWRITERVS_SWIZZLE_Z
:
1641 component
= BWRITERSP_WRITEMASK_2
;
1643 case BWRITERVS_SWIZZLE_W
:
1644 component
= BWRITERSP_WRITEMASK_3
;
1649 token
|= map_vs_output(This
, reg
->regnum
, component
, &has_swizzle
);
1652 case BWRITERSPR_RASTOUT
:
1653 case BWRITERSPR_ATTROUT
:
1654 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1655 * but are unexpected. If we hit this path it might be due to an error.
1657 FIXME("Unexpected register type %u\n", reg
->type
);
1659 case BWRITERSPR_INPUT
:
1660 case BWRITERSPR_TEMP
:
1661 case BWRITERSPR_CONST
:
1662 case BWRITERSPR_ADDR
:
1663 case BWRITERSPR_CONSTINT
:
1664 case BWRITERSPR_CONSTBOOL
:
1665 case BWRITERSPR_LABEL
:
1666 d3d9reg
= d3d9_register(reg
->type
);
1667 token
|= d3dsp_register( d3d9reg
, reg
->regnum
);
1670 case BWRITERSPR_LOOP
:
1671 if(reg
->regnum
!= 0) {
1672 WARN("Only regnum 0 is supported for the loop index register in vs_2_0\n");
1673 This
->state
= E_INVALIDARG
;
1676 token
|= d3dsp_register( D3DSPR_LOOP
, 0 );
1679 case BWRITERSPR_PREDICATE
:
1680 if (This
->shader
->major_version
!= 2 || This
->shader
->minor_version
!= 1)
1682 WARN("Predicate register is allowed only in vs_2_x\n");
1683 This
->state
= E_INVALIDARG
;
1686 if(reg
->regnum
> 0) {
1687 WARN("Only predicate register 0 is supported\n");
1688 This
->state
= E_INVALIDARG
;
1691 token
|= d3dsp_register( D3DSPR_PREDICATE
, 0 );
1695 WARN("Invalid register type for 2.0 vshader\n");
1696 This
->state
= E_INVALIDARG
;
1700 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1702 token
|= d3d9_srcmod(reg
->srcmod
);
1705 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1707 put_dword(buffer
, token
);
1709 /* vs_2_0 and newer write the register containing the index explicitly in the
1712 if(token
& D3DVS_ADDRMODE_RELATIVE
)
1713 vs_2_srcreg(This
, reg
->rel_reg
, buffer
);
1716 static void sm_2_opcode(struct bc_writer
*This
,
1717 const struct instruction
*instr
,
1718 DWORD token
, struct bytecode_buffer
*buffer
) {
1719 /* From sm 2 onwards instruction length is encoded in the opcode field */
1720 int dsts
= instr
->has_dst
? 1 : 0;
1721 token
|= instrlen(instr
, instr
->num_srcs
, dsts
) << D3DSI_INSTLENGTH_SHIFT
;
1723 token
|= (d3d9_comparetype(instr
->comptype
) << 16) & (0xf << 16);
1724 if(instr
->has_predicate
)
1725 token
|= D3DSHADER_INSTRUCTION_PREDICATED
;
1726 put_dword(buffer
,token
);
1729 static const struct instr_handler_table vs_2_0_handlers
[] = {
1730 {BWRITERSIO_ADD
, instr_handler
},
1731 {BWRITERSIO_NOP
, instr_handler
},
1732 {BWRITERSIO_MOV
, instr_handler
},
1733 {BWRITERSIO_SUB
, instr_handler
},
1734 {BWRITERSIO_MAD
, instr_handler
},
1735 {BWRITERSIO_MUL
, instr_handler
},
1736 {BWRITERSIO_RCP
, instr_handler
},
1737 {BWRITERSIO_RSQ
, instr_handler
},
1738 {BWRITERSIO_DP3
, instr_handler
},
1739 {BWRITERSIO_DP4
, instr_handler
},
1740 {BWRITERSIO_MIN
, instr_handler
},
1741 {BWRITERSIO_MAX
, instr_handler
},
1742 {BWRITERSIO_SLT
, instr_handler
},
1743 {BWRITERSIO_SGE
, instr_handler
},
1744 {BWRITERSIO_ABS
, instr_handler
},
1745 {BWRITERSIO_EXP
, instr_handler
},
1746 {BWRITERSIO_LOG
, instr_handler
},
1747 {BWRITERSIO_EXPP
, instr_handler
},
1748 {BWRITERSIO_LOGP
, instr_handler
},
1749 {BWRITERSIO_DST
, instr_handler
},
1750 {BWRITERSIO_LRP
, instr_handler
},
1751 {BWRITERSIO_FRC
, instr_handler
},
1752 {BWRITERSIO_CRS
, instr_handler
},
1753 {BWRITERSIO_SGN
, instr_handler
},
1754 {BWRITERSIO_NRM
, instr_handler
},
1755 {BWRITERSIO_SINCOS
, instr_handler
},
1756 {BWRITERSIO_M4x4
, instr_handler
},
1757 {BWRITERSIO_M4x3
, instr_handler
},
1758 {BWRITERSIO_M3x4
, instr_handler
},
1759 {BWRITERSIO_M3x3
, instr_handler
},
1760 {BWRITERSIO_M3x2
, instr_handler
},
1761 {BWRITERSIO_LIT
, instr_handler
},
1762 {BWRITERSIO_POW
, instr_handler
},
1763 {BWRITERSIO_MOVA
, instr_handler
},
1765 {BWRITERSIO_CALL
, instr_handler
},
1766 {BWRITERSIO_CALLNZ
, instr_handler
},
1767 {BWRITERSIO_REP
, instr_handler
},
1768 {BWRITERSIO_ENDREP
, instr_handler
},
1769 {BWRITERSIO_IF
, instr_handler
},
1770 {BWRITERSIO_LABEL
, instr_handler
},
1771 {BWRITERSIO_ELSE
, instr_handler
},
1772 {BWRITERSIO_ENDIF
, instr_handler
},
1773 {BWRITERSIO_LOOP
, instr_handler
},
1774 {BWRITERSIO_RET
, instr_handler
},
1775 {BWRITERSIO_ENDLOOP
, instr_handler
},
1777 {BWRITERSIO_END
, NULL
},
1780 static const struct bytecode_backend vs_2_0_backend
= {
1789 static const struct instr_handler_table vs_2_x_handlers
[] = {
1790 {BWRITERSIO_ADD
, instr_handler
},
1791 {BWRITERSIO_NOP
, instr_handler
},
1792 {BWRITERSIO_MOV
, instr_handler
},
1793 {BWRITERSIO_SUB
, instr_handler
},
1794 {BWRITERSIO_MAD
, instr_handler
},
1795 {BWRITERSIO_MUL
, instr_handler
},
1796 {BWRITERSIO_RCP
, instr_handler
},
1797 {BWRITERSIO_RSQ
, instr_handler
},
1798 {BWRITERSIO_DP3
, instr_handler
},
1799 {BWRITERSIO_DP4
, instr_handler
},
1800 {BWRITERSIO_MIN
, instr_handler
},
1801 {BWRITERSIO_MAX
, instr_handler
},
1802 {BWRITERSIO_SLT
, instr_handler
},
1803 {BWRITERSIO_SGE
, instr_handler
},
1804 {BWRITERSIO_ABS
, instr_handler
},
1805 {BWRITERSIO_EXP
, instr_handler
},
1806 {BWRITERSIO_LOG
, instr_handler
},
1807 {BWRITERSIO_EXPP
, instr_handler
},
1808 {BWRITERSIO_LOGP
, instr_handler
},
1809 {BWRITERSIO_DST
, instr_handler
},
1810 {BWRITERSIO_LRP
, instr_handler
},
1811 {BWRITERSIO_FRC
, instr_handler
},
1812 {BWRITERSIO_CRS
, instr_handler
},
1813 {BWRITERSIO_SGN
, instr_handler
},
1814 {BWRITERSIO_NRM
, instr_handler
},
1815 {BWRITERSIO_SINCOS
, instr_handler
},
1816 {BWRITERSIO_M4x4
, instr_handler
},
1817 {BWRITERSIO_M4x3
, instr_handler
},
1818 {BWRITERSIO_M3x4
, instr_handler
},
1819 {BWRITERSIO_M3x3
, instr_handler
},
1820 {BWRITERSIO_M3x2
, instr_handler
},
1821 {BWRITERSIO_LIT
, instr_handler
},
1822 {BWRITERSIO_POW
, instr_handler
},
1823 {BWRITERSIO_MOVA
, instr_handler
},
1825 {BWRITERSIO_CALL
, instr_handler
},
1826 {BWRITERSIO_CALLNZ
, instr_handler
},
1827 {BWRITERSIO_REP
, instr_handler
},
1828 {BWRITERSIO_ENDREP
, instr_handler
},
1829 {BWRITERSIO_IF
, instr_handler
},
1830 {BWRITERSIO_LABEL
, instr_handler
},
1831 {BWRITERSIO_IFC
, instr_handler
},
1832 {BWRITERSIO_ELSE
, instr_handler
},
1833 {BWRITERSIO_ENDIF
, instr_handler
},
1834 {BWRITERSIO_BREAK
, instr_handler
},
1835 {BWRITERSIO_BREAKC
, instr_handler
},
1836 {BWRITERSIO_LOOP
, instr_handler
},
1837 {BWRITERSIO_RET
, instr_handler
},
1838 {BWRITERSIO_ENDLOOP
, instr_handler
},
1840 {BWRITERSIO_SETP
, instr_handler
},
1841 {BWRITERSIO_BREAKP
, instr_handler
},
1843 {BWRITERSIO_END
, NULL
},
1846 static const struct bytecode_backend vs_2_x_backend
= {
1855 static void write_samplers(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1857 DWORD instr_dcl
= D3DSIO_DCL
| (2 << D3DSI_INSTLENGTH_SHIFT
);
1859 const DWORD reg
= (1u << 31) | d3dsp_register( D3DSPR_SAMPLER
, 0 ) | D3DSP_WRITEMASK_ALL
;
1861 for(i
= 0; i
< shader
->num_samplers
; i
++) {
1862 /* Write the DCL instruction */
1863 put_dword(buffer
, instr_dcl
);
1865 /* Already shifted */
1866 token
|= (d3d9_sampler(shader
->samplers
[i
].type
)) & D3DSP_TEXTURETYPE_MASK
;
1867 put_dword(buffer
, token
);
1868 token
= reg
| (shader
->samplers
[i
].regnum
& D3DSP_REGNUM_MASK
);
1869 token
|= d3d9_dstmod(shader
->samplers
[i
].mod
);
1870 put_dword(buffer
, token
);
1874 static void ps_2_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1875 HRESULT hr
= find_ps_builtin_semantics(This
, shader
, 8);
1881 write_declarations(This
, buffer
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
1882 write_samplers(shader
, buffer
);
1883 write_constF(shader
, buffer
, TRUE
);
1884 write_constB(shader
, buffer
, TRUE
);
1885 write_constI(shader
, buffer
, TRUE
);
1888 static void ps_2_srcreg(struct bc_writer
*This
,
1889 const struct shader_reg
*reg
,
1890 struct bytecode_buffer
*buffer
) {
1891 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1894 WARN("Relative addressing not supported in <= ps_3_0\n");
1895 This
->state
= E_INVALIDARG
;
1900 case BWRITERSPR_INPUT
:
1901 token
|= map_ps_input(This
, reg
);
1904 /* Can be mapped 1:1 */
1905 case BWRITERSPR_TEMP
:
1906 case BWRITERSPR_CONST
:
1907 case BWRITERSPR_COLOROUT
:
1908 case BWRITERSPR_CONSTBOOL
:
1909 case BWRITERSPR_CONSTINT
:
1910 case BWRITERSPR_SAMPLER
:
1911 case BWRITERSPR_LABEL
:
1912 case BWRITERSPR_DEPTHOUT
:
1913 d3d9reg
= d3d9_register(reg
->type
);
1914 token
|= d3dsp_register( d3d9reg
, reg
->regnum
);
1917 case BWRITERSPR_PREDICATE
:
1918 if (This
->shader
->minor_version
== 0)
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
|= d3dsp_register( D3DSPR_PREDICATE
, 0 );
1932 WARN("Invalid register type for ps_2_0 shader\n");
1933 This
->state
= E_INVALIDARG
;
1937 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1939 token
|= d3d9_srcmod(reg
->srcmod
);
1940 put_dword(buffer
, token
);
1943 static void ps_2_0_dstreg(struct bc_writer
*This
,
1944 const struct shader_reg
*reg
,
1945 struct bytecode_buffer
*buffer
,
1946 DWORD shift
, DWORD mod
) {
1947 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
1951 WARN("Relative addressing not supported for destination registers\n");
1952 This
->state
= E_INVALIDARG
;
1957 case BWRITERSPR_TEMP
: /* 1:1 mapping */
1958 case BWRITERSPR_COLOROUT
:
1959 case BWRITERSPR_DEPTHOUT
:
1960 d3d9reg
= d3d9_register(reg
->type
);
1961 token
|= d3dsp_register( d3d9reg
, reg
->regnum
);
1964 case BWRITERSPR_PREDICATE
:
1965 if (This
->shader
->minor_version
== 0)
1967 WARN("Predicate register not supported in ps_2_0\n");
1968 This
->state
= E_INVALIDARG
;
1970 token
|= d3dsp_register( D3DSPR_PREDICATE
, reg
->regnum
);
1973 /* texkill uses the input register as a destination parameter */
1974 case BWRITERSPR_INPUT
:
1975 token
|= map_ps_input(This
, reg
);
1979 WARN("Invalid dest register type for 2.x pshader\n");
1980 This
->state
= E_INVALIDARG
;
1984 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1985 token
|= d3d9_dstmod(mod
);
1987 token
|= d3d9_writemask(reg
->u
.writemask
);
1988 put_dword(buffer
, token
);
1991 static const struct instr_handler_table ps_2_0_handlers
[] = {
1992 {BWRITERSIO_ADD
, instr_handler
},
1993 {BWRITERSIO_NOP
, instr_handler
},
1994 {BWRITERSIO_MOV
, instr_handler
},
1995 {BWRITERSIO_SUB
, instr_handler
},
1996 {BWRITERSIO_MAD
, instr_handler
},
1997 {BWRITERSIO_MUL
, instr_handler
},
1998 {BWRITERSIO_RCP
, instr_handler
},
1999 {BWRITERSIO_RSQ
, instr_handler
},
2000 {BWRITERSIO_DP3
, instr_handler
},
2001 {BWRITERSIO_DP4
, instr_handler
},
2002 {BWRITERSIO_MIN
, instr_handler
},
2003 {BWRITERSIO_MAX
, instr_handler
},
2004 {BWRITERSIO_ABS
, instr_handler
},
2005 {BWRITERSIO_EXP
, instr_handler
},
2006 {BWRITERSIO_LOG
, instr_handler
},
2007 {BWRITERSIO_EXPP
, instr_handler
},
2008 {BWRITERSIO_LOGP
, instr_handler
},
2009 {BWRITERSIO_LRP
, instr_handler
},
2010 {BWRITERSIO_FRC
, instr_handler
},
2011 {BWRITERSIO_CRS
, instr_handler
},
2012 {BWRITERSIO_NRM
, instr_handler
},
2013 {BWRITERSIO_SINCOS
, instr_handler
},
2014 {BWRITERSIO_M4x4
, instr_handler
},
2015 {BWRITERSIO_M4x3
, instr_handler
},
2016 {BWRITERSIO_M3x4
, instr_handler
},
2017 {BWRITERSIO_M3x3
, instr_handler
},
2018 {BWRITERSIO_M3x2
, instr_handler
},
2019 {BWRITERSIO_POW
, instr_handler
},
2020 {BWRITERSIO_DP2ADD
, instr_handler
},
2021 {BWRITERSIO_CMP
, instr_handler
},
2023 {BWRITERSIO_TEX
, instr_handler
},
2024 {BWRITERSIO_TEXLDP
, instr_handler
},
2025 {BWRITERSIO_TEXLDB
, instr_handler
},
2026 {BWRITERSIO_TEXKILL
, instr_handler
},
2028 {BWRITERSIO_END
, NULL
},
2031 static const struct bytecode_backend ps_2_0_backend
= {
2040 static const struct instr_handler_table ps_2_x_handlers
[] = {
2041 {BWRITERSIO_ADD
, instr_handler
},
2042 {BWRITERSIO_NOP
, instr_handler
},
2043 {BWRITERSIO_MOV
, instr_handler
},
2044 {BWRITERSIO_SUB
, instr_handler
},
2045 {BWRITERSIO_MAD
, instr_handler
},
2046 {BWRITERSIO_MUL
, instr_handler
},
2047 {BWRITERSIO_RCP
, instr_handler
},
2048 {BWRITERSIO_RSQ
, instr_handler
},
2049 {BWRITERSIO_DP3
, instr_handler
},
2050 {BWRITERSIO_DP4
, instr_handler
},
2051 {BWRITERSIO_MIN
, instr_handler
},
2052 {BWRITERSIO_MAX
, instr_handler
},
2053 {BWRITERSIO_ABS
, instr_handler
},
2054 {BWRITERSIO_EXP
, instr_handler
},
2055 {BWRITERSIO_LOG
, instr_handler
},
2056 {BWRITERSIO_EXPP
, instr_handler
},
2057 {BWRITERSIO_LOGP
, instr_handler
},
2058 {BWRITERSIO_LRP
, instr_handler
},
2059 {BWRITERSIO_FRC
, instr_handler
},
2060 {BWRITERSIO_CRS
, instr_handler
},
2061 {BWRITERSIO_NRM
, instr_handler
},
2062 {BWRITERSIO_SINCOS
, instr_handler
},
2063 {BWRITERSIO_M4x4
, instr_handler
},
2064 {BWRITERSIO_M4x3
, instr_handler
},
2065 {BWRITERSIO_M3x4
, instr_handler
},
2066 {BWRITERSIO_M3x3
, instr_handler
},
2067 {BWRITERSIO_M3x2
, instr_handler
},
2068 {BWRITERSIO_POW
, instr_handler
},
2069 {BWRITERSIO_DP2ADD
, instr_handler
},
2070 {BWRITERSIO_CMP
, instr_handler
},
2072 {BWRITERSIO_CALL
, instr_handler
},
2073 {BWRITERSIO_CALLNZ
, instr_handler
},
2074 {BWRITERSIO_REP
, instr_handler
},
2075 {BWRITERSIO_ENDREP
, instr_handler
},
2076 {BWRITERSIO_IF
, instr_handler
},
2077 {BWRITERSIO_LABEL
, instr_handler
},
2078 {BWRITERSIO_IFC
, instr_handler
},
2079 {BWRITERSIO_ELSE
, instr_handler
},
2080 {BWRITERSIO_ENDIF
, instr_handler
},
2081 {BWRITERSIO_BREAK
, instr_handler
},
2082 {BWRITERSIO_BREAKC
, instr_handler
},
2083 {BWRITERSIO_RET
, instr_handler
},
2085 {BWRITERSIO_TEX
, instr_handler
},
2086 {BWRITERSIO_TEXLDP
, instr_handler
},
2087 {BWRITERSIO_TEXLDB
, instr_handler
},
2088 {BWRITERSIO_TEXKILL
, instr_handler
},
2089 {BWRITERSIO_DSX
, instr_handler
},
2090 {BWRITERSIO_DSY
, instr_handler
},
2092 {BWRITERSIO_SETP
, instr_handler
},
2093 {BWRITERSIO_BREAKP
, instr_handler
},
2095 {BWRITERSIO_TEXLDD
, instr_handler
},
2097 {BWRITERSIO_END
, NULL
},
2100 static const struct bytecode_backend ps_2_x_backend
= {
2109 static void sm_3_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
2110 write_declarations(This
, buffer
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
2111 write_declarations(This
, buffer
, shader
->outputs
, shader
->num_outputs
, BWRITERSPR_OUTPUT
);
2112 write_constF(shader
, buffer
, TRUE
);
2113 write_constB(shader
, buffer
, TRUE
);
2114 write_constI(shader
, buffer
, TRUE
);
2115 write_samplers(shader
, buffer
);
2118 static void sm_3_srcreg(struct bc_writer
*This
,
2119 const struct shader_reg
*reg
,
2120 struct bytecode_buffer
*buffer
) {
2121 const struct bwriter_shader
*shader
= This
->shader
;
2122 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
2125 d3d9reg
= d3d9_register(reg
->type
);
2126 token
|= d3dsp_register( d3d9reg
, reg
->regnum
);
2127 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
;
2128 token
|= d3d9_srcmod(reg
->srcmod
);
2131 if (reg
->type
== BWRITERSPR_CONST
&& shader
->type
== ST_PIXEL
)
2133 WARN("c%u[...] is unsupported in ps_3_0\n", reg
->regnum
);
2134 This
->state
= E_INVALIDARG
;
2138 if (((reg
->rel_reg
->type
== BWRITERSPR_ADDR
&& shader
->type
== ST_VERTEX
)
2139 || reg
->rel_reg
->type
== BWRITERSPR_LOOP
) && reg
->rel_reg
->regnum
== 0)
2141 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
2143 WARN("Unsupported relative addressing register\n");
2144 This
->state
= E_INVALIDARG
;
2149 put_dword(buffer
, token
);
2151 /* vs_2_0 and newer write the register containing the index explicitly in the
2154 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
2155 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
2159 static void sm_3_dstreg(struct bc_writer
*This
,
2160 const struct shader_reg
*reg
,
2161 struct bytecode_buffer
*buffer
,
2162 DWORD shift
, DWORD mod
) {
2163 const struct bwriter_shader
*shader
= This
->shader
;
2164 DWORD token
= (1u << 31); /* Bit 31 of registers is 1 */
2168 if (shader
->type
== ST_VERTEX
&& reg
->type
== BWRITERSPR_OUTPUT
)
2170 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
2172 WARN("Relative addressing not supported for this shader type or register type\n");
2173 This
->state
= E_INVALIDARG
;
2178 d3d9reg
= d3d9_register(reg
->type
);
2179 token
|= d3dsp_register( d3d9reg
, reg
->regnum
);
2180 token
|= d3d9_dstmod(mod
);
2181 token
|= d3d9_writemask(reg
->u
.writemask
);
2182 put_dword(buffer
, token
);
2184 /* vs_2_0 and newer write the register containing the index explicitly in the
2187 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
2188 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
2192 static const struct instr_handler_table vs_3_handlers
[] = {
2193 {BWRITERSIO_ADD
, instr_handler
},
2194 {BWRITERSIO_NOP
, instr_handler
},
2195 {BWRITERSIO_MOV
, instr_handler
},
2196 {BWRITERSIO_SUB
, instr_handler
},
2197 {BWRITERSIO_MAD
, instr_handler
},
2198 {BWRITERSIO_MUL
, instr_handler
},
2199 {BWRITERSIO_RCP
, instr_handler
},
2200 {BWRITERSIO_RSQ
, instr_handler
},
2201 {BWRITERSIO_DP3
, instr_handler
},
2202 {BWRITERSIO_DP4
, instr_handler
},
2203 {BWRITERSIO_MIN
, instr_handler
},
2204 {BWRITERSIO_MAX
, instr_handler
},
2205 {BWRITERSIO_SLT
, instr_handler
},
2206 {BWRITERSIO_SGE
, instr_handler
},
2207 {BWRITERSIO_ABS
, instr_handler
},
2208 {BWRITERSIO_EXP
, instr_handler
},
2209 {BWRITERSIO_LOG
, instr_handler
},
2210 {BWRITERSIO_EXPP
, instr_handler
},
2211 {BWRITERSIO_LOGP
, instr_handler
},
2212 {BWRITERSIO_DST
, instr_handler
},
2213 {BWRITERSIO_LRP
, instr_handler
},
2214 {BWRITERSIO_FRC
, instr_handler
},
2215 {BWRITERSIO_CRS
, instr_handler
},
2216 {BWRITERSIO_SGN
, 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_LIT
, instr_handler
},
2225 {BWRITERSIO_POW
, instr_handler
},
2226 {BWRITERSIO_MOVA
, 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_END
, NULL
},
2250 static const struct bytecode_backend vs_3_backend
= {
2259 static const struct instr_handler_table ps_3_handlers
[] = {
2260 {BWRITERSIO_ADD
, instr_handler
},
2261 {BWRITERSIO_NOP
, instr_handler
},
2262 {BWRITERSIO_MOV
, instr_handler
},
2263 {BWRITERSIO_SUB
, instr_handler
},
2264 {BWRITERSIO_MAD
, instr_handler
},
2265 {BWRITERSIO_MUL
, instr_handler
},
2266 {BWRITERSIO_RCP
, instr_handler
},
2267 {BWRITERSIO_RSQ
, instr_handler
},
2268 {BWRITERSIO_DP3
, instr_handler
},
2269 {BWRITERSIO_DP4
, instr_handler
},
2270 {BWRITERSIO_MIN
, instr_handler
},
2271 {BWRITERSIO_MAX
, instr_handler
},
2272 {BWRITERSIO_ABS
, instr_handler
},
2273 {BWRITERSIO_EXP
, instr_handler
},
2274 {BWRITERSIO_LOG
, instr_handler
},
2275 {BWRITERSIO_EXPP
, instr_handler
},
2276 {BWRITERSIO_LOGP
, instr_handler
},
2277 {BWRITERSIO_LRP
, instr_handler
},
2278 {BWRITERSIO_FRC
, instr_handler
},
2279 {BWRITERSIO_CRS
, instr_handler
},
2280 {BWRITERSIO_NRM
, instr_handler
},
2281 {BWRITERSIO_SINCOS
, instr_handler
},
2282 {BWRITERSIO_M4x4
, instr_handler
},
2283 {BWRITERSIO_M4x3
, instr_handler
},
2284 {BWRITERSIO_M3x4
, instr_handler
},
2285 {BWRITERSIO_M3x3
, instr_handler
},
2286 {BWRITERSIO_M3x2
, instr_handler
},
2287 {BWRITERSIO_POW
, instr_handler
},
2288 {BWRITERSIO_DP2ADD
, instr_handler
},
2289 {BWRITERSIO_CMP
, instr_handler
},
2291 {BWRITERSIO_CALL
, instr_handler
},
2292 {BWRITERSIO_CALLNZ
, instr_handler
},
2293 {BWRITERSIO_REP
, instr_handler
},
2294 {BWRITERSIO_ENDREP
, instr_handler
},
2295 {BWRITERSIO_IF
, instr_handler
},
2296 {BWRITERSIO_LABEL
, instr_handler
},
2297 {BWRITERSIO_IFC
, instr_handler
},
2298 {BWRITERSIO_ELSE
, instr_handler
},
2299 {BWRITERSIO_ENDIF
, instr_handler
},
2300 {BWRITERSIO_BREAK
, instr_handler
},
2301 {BWRITERSIO_BREAKC
, instr_handler
},
2302 {BWRITERSIO_LOOP
, instr_handler
},
2303 {BWRITERSIO_RET
, instr_handler
},
2304 {BWRITERSIO_ENDLOOP
, instr_handler
},
2306 {BWRITERSIO_SETP
, instr_handler
},
2307 {BWRITERSIO_BREAKP
, instr_handler
},
2308 {BWRITERSIO_TEXLDL
, instr_handler
},
2310 {BWRITERSIO_TEX
, instr_handler
},
2311 {BWRITERSIO_TEXLDP
, instr_handler
},
2312 {BWRITERSIO_TEXLDB
, instr_handler
},
2313 {BWRITERSIO_TEXKILL
, instr_handler
},
2314 {BWRITERSIO_DSX
, instr_handler
},
2315 {BWRITERSIO_DSY
, instr_handler
},
2316 {BWRITERSIO_TEXLDD
, instr_handler
},
2318 {BWRITERSIO_END
, NULL
},
2321 static const struct bytecode_backend ps_3_backend
= {
2332 enum shader_type type
;
2333 unsigned char major
, minor
;
2334 const struct bytecode_backend
*backend
;
2338 {ST_VERTEX
, 1, 0, &vs_1_x_backend
},
2339 {ST_VERTEX
, 1, 1, &vs_1_x_backend
},
2340 {ST_VERTEX
, 2, 0, &vs_2_0_backend
},
2341 {ST_VERTEX
, 2, 1, &vs_2_x_backend
},
2342 {ST_VERTEX
, 3, 0, &vs_3_backend
},
2344 {ST_PIXEL
, 1, 0, &ps_1_0123_backend
},
2345 {ST_PIXEL
, 1, 1, &ps_1_0123_backend
},
2346 {ST_PIXEL
, 1, 2, &ps_1_0123_backend
},
2347 {ST_PIXEL
, 1, 3, &ps_1_0123_backend
},
2348 {ST_PIXEL
, 1, 4, &ps_1_4_backend
},
2349 {ST_PIXEL
, 2, 0, &ps_2_0_backend
},
2350 {ST_PIXEL
, 2, 1, &ps_2_x_backend
},
2351 {ST_PIXEL
, 3, 0, &ps_3_backend
},
2354 static HRESULT
call_instr_handler(struct bc_writer
*writer
,
2355 const struct instruction
*instr
,
2356 struct bytecode_buffer
*buffer
) {
2359 while(writer
->funcs
->instructions
[i
].opcode
!= BWRITERSIO_END
) {
2360 if(instr
->opcode
== writer
->funcs
->instructions
[i
].opcode
) {
2361 if(!writer
->funcs
->instructions
[i
].func
) {
2362 WARN("Opcode %u not supported by this profile\n", instr
->opcode
);
2363 return E_INVALIDARG
;
2365 writer
->funcs
->instructions
[i
].func(writer
, instr
, buffer
);
2371 FIXME("Unhandled instruction %u - %s\n", instr
->opcode
,
2372 debug_print_opcode(instr
->opcode
));
2373 return E_INVALIDARG
;
2376 HRESULT
shader_write_bytecode(const struct bwriter_shader
*shader
, DWORD
**result
, DWORD
*size
)
2378 struct bc_writer
*writer
;
2379 struct bytecode_buffer
*buffer
= NULL
;
2384 ERR("NULL shader structure, aborting\n");
2388 if (!(writer
= d3dcompiler_alloc(sizeof(*writer
))))
2389 return E_OUTOFMEMORY
;
2391 for (i
= 0; i
< ARRAY_SIZE(shader_backends
); ++i
)
2393 if (shader
->type
== shader_backends
[i
].type
2394 && shader
->major_version
== shader_backends
[i
].major
2395 && shader
->minor_version
== shader_backends
[i
].minor
)
2397 writer
->funcs
= shader_backends
[i
].backend
;
2404 FIXME("Unsupported shader type %#x, version %u.%u.\n",
2405 shader
->type
, shader
->major_version
, shader
->minor_version
);
2406 d3dcompiler_free(writer
);
2410 writer
->shader
= shader
;
2413 buffer
= allocate_buffer();
2415 WARN("Failed to allocate a buffer for the shader bytecode\n");
2420 /* Write shader type and version */
2421 put_dword(buffer
, sm1_version(shader
));
2423 writer
->funcs
->header(writer
, shader
, buffer
);
2424 if(FAILED(writer
->state
)) {
2429 for(i
= 0; i
< shader
->num_instrs
; i
++) {
2430 hr
= call_instr_handler(writer
, shader
->instr
[i
], buffer
);
2436 if(FAILED(writer
->state
)) {
2441 writer
->funcs
->end(writer
, shader
, buffer
);
2443 if(FAILED(buffer
->state
)) {
2448 *size
= buffer
->size
* sizeof(DWORD
);
2449 *result
= buffer
->data
;
2450 buffer
->data
= NULL
;
2455 d3dcompiler_free(buffer
->data
);
2456 d3dcompiler_free(buffer
);
2458 d3dcompiler_free(writer
);
2462 void SlDeleteShader(struct bwriter_shader
*shader
) {
2465 TRACE("Deleting shader %p\n", shader
);
2467 for(i
= 0; i
< shader
->num_cf
; i
++) {
2468 d3dcompiler_free(shader
->constF
[i
]);
2470 d3dcompiler_free(shader
->constF
);
2471 for(i
= 0; i
< shader
->num_ci
; i
++) {
2472 d3dcompiler_free(shader
->constI
[i
]);
2474 d3dcompiler_free(shader
->constI
);
2475 for(i
= 0; i
< shader
->num_cb
; i
++) {
2476 d3dcompiler_free(shader
->constB
[i
]);
2478 d3dcompiler_free(shader
->constB
);
2480 d3dcompiler_free(shader
->inputs
);
2481 d3dcompiler_free(shader
->outputs
);
2482 d3dcompiler_free(shader
->samplers
);
2484 for(i
= 0; i
< shader
->num_instrs
; i
++) {
2485 for(j
= 0; j
< shader
->instr
[i
]->num_srcs
; j
++) {
2486 d3dcompiler_free(shader
->instr
[i
]->src
[j
].rel_reg
);
2488 d3dcompiler_free(shader
->instr
[i
]->src
);
2489 d3dcompiler_free(shader
->instr
[i
]->dst
.rel_reg
);
2490 d3dcompiler_free(shader
->instr
[i
]);
2492 d3dcompiler_free(shader
->instr
);
2494 d3dcompiler_free(shader
);