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
, uint32_t reg
, float x
, float y
, float z
, float w
)
118 struct constant
*newconst
;
122 struct constant
**newarray
;
123 newarray
= d3dcompiler_realloc(shader
->constF
, sizeof(*shader
->constF
) * (shader
->num_cf
+ 1));
126 ERR("Failed to grow the constants array\n");
129 shader
->constF
= newarray
;
133 shader
->constF
= d3dcompiler_alloc(sizeof(*shader
->constF
));
136 ERR("Failed to allocate the constants array\n");
141 newconst
= d3dcompiler_alloc(sizeof(*newconst
));
144 ERR("Failed to allocate a new constant\n");
147 newconst
->regnum
= reg
;
148 newconst
->value
[0].f
= x
;
149 newconst
->value
[1].f
= y
;
150 newconst
->value
[2].f
= z
;
151 newconst
->value
[3].f
= w
;
152 shader
->constF
[shader
->num_cf
] = newconst
;
158 BOOL
add_constI(struct bwriter_shader
*shader
, uint32_t reg
, int x
, int y
, int z
, int w
)
160 struct constant
*newconst
;
164 struct constant
**newarray
;
165 newarray
= d3dcompiler_realloc(shader
->constI
, sizeof(*shader
->constI
) * (shader
->num_ci
+ 1));
168 ERR("Failed to grow the constants array\n");
171 shader
->constI
= newarray
;
175 shader
->constI
= d3dcompiler_alloc(sizeof(*shader
->constI
));
178 ERR("Failed to allocate the constants array\n");
183 newconst
= d3dcompiler_alloc(sizeof(*newconst
));
186 ERR("Failed to allocate a new constant\n");
189 newconst
->regnum
= reg
;
190 newconst
->value
[0].i
= x
;
191 newconst
->value
[1].i
= y
;
192 newconst
->value
[2].i
= z
;
193 newconst
->value
[3].i
= w
;
194 shader
->constI
[shader
->num_ci
] = newconst
;
200 BOOL
add_constB(struct bwriter_shader
*shader
, uint32_t reg
, BOOL x
)
202 struct constant
*newconst
;
206 struct constant
**newarray
;
207 newarray
= d3dcompiler_realloc(shader
->constB
, sizeof(*shader
->constB
) * (shader
->num_cb
+ 1));
210 ERR("Failed to grow the constants array\n");
213 shader
->constB
= newarray
;
217 shader
->constB
= d3dcompiler_alloc(sizeof(*shader
->constB
));
220 ERR("Failed to allocate the constants array\n");
225 newconst
= d3dcompiler_alloc(sizeof(*newconst
));
228 ERR("Failed to allocate a new constant\n");
231 newconst
->regnum
= reg
;
232 newconst
->value
[0].b
= x
;
233 shader
->constB
[shader
->num_cb
] = newconst
;
239 BOOL
record_declaration(struct bwriter_shader
*shader
, uint32_t usage
, uint32_t usage_idx
,
240 uint32_t mod
, BOOL output
, uint32_t regnum
, uint32_t writemask
, BOOL builtin
)
242 struct declaration
**decl
;
243 unsigned int i
, *num
;
250 num
= &shader
->num_outputs
;
251 decl
= &shader
->outputs
;
255 num
= &shader
->num_inputs
;
256 decl
= &shader
->inputs
;
261 *decl
= d3dcompiler_alloc(sizeof(**decl
));
264 ERR("Error allocating declarations array\n");
270 struct declaration
*newdecl
;
272 for (i
= 0; i
< *num
; i
++)
274 if ((*decl
)[i
].regnum
== regnum
&& ((*decl
)[i
].writemask
& writemask
))
275 WARN("Declaration of register %u already exists, writemask match 0x%x\n",
276 regnum
, (*decl
)[i
].writemask
& writemask
);
279 newdecl
= d3dcompiler_realloc(*decl
,
280 sizeof(**decl
) * ((*num
) + 1));
283 ERR("Error reallocating declarations array\n");
288 (*decl
)[*num
].usage
= usage
;
289 (*decl
)[*num
].usage_idx
= usage_idx
;
290 (*decl
)[*num
].regnum
= regnum
;
291 (*decl
)[*num
].mod
= mod
;
292 (*decl
)[*num
].writemask
= writemask
;
293 (*decl
)[*num
].builtin
= builtin
;
299 BOOL
record_sampler(struct bwriter_shader
*shader
, uint32_t samptype
, uint32_t mod
, uint32_t regnum
) {
305 if (shader
->num_samplers
== 0)
307 shader
->samplers
= d3dcompiler_alloc(sizeof(*shader
->samplers
));
308 if (!shader
->samplers
)
310 ERR("Error allocating samplers array\n");
316 struct samplerdecl
*newarray
;
318 for (i
= 0; i
< shader
->num_samplers
; i
++)
320 if (shader
->samplers
[i
].regnum
== regnum
)
322 WARN("Sampler %u already declared\n", regnum
);
323 /* This is not an error as far as the assembler is concerned.
324 * Direct3D might refuse to load the compiled shader though */
328 newarray
= d3dcompiler_realloc(shader
->samplers
, sizeof(*shader
->samplers
) * (shader
->num_samplers
+ 1));
331 ERR("Error reallocating samplers array\n");
334 shader
->samplers
= newarray
;
337 shader
->samplers
[shader
->num_samplers
].type
= samptype
;
338 shader
->samplers
[shader
->num_samplers
].mod
= mod
;
339 shader
->samplers
[shader
->num_samplers
].regnum
= regnum
;
340 shader
->num_samplers
++;
344 struct bytecode_buffer
347 unsigned int size
, alloc_size
;
353 typedef void (*instr_writer
)(struct bc_writer
*writer
, const struct instruction
*instr
,
354 struct bytecode_buffer
*buffer
);
356 struct bytecode_backend
358 void (*header
)(struct bc_writer
*writer
, const struct bwriter_shader
*shader
,
359 struct bytecode_buffer
*buffer
);
360 void (*end
)(struct bc_writer
*writer
, const struct bwriter_shader
*shader
,
361 struct bytecode_buffer
*buffer
);
362 void (*srcreg
)(struct bc_writer
*writer
, const struct shader_reg
*reg
,
363 struct bytecode_buffer
*buffer
);
364 void (*dstreg
)(struct bc_writer
*writer
, const struct shader_reg
*reg
,
365 struct bytecode_buffer
*buffer
, uint32_t shift
, uint32_t mod
);
366 void (*opcode
)(struct bc_writer
*writer
, const struct instruction
*instr
,
367 uint32_t token
, struct bytecode_buffer
*buffer
);
369 const struct instr_handler_table
378 const struct bytecode_backend
*funcs
;
379 const struct bwriter_shader
*shader
;
383 /* Vertex shader varying mapping. */
384 uint32_t oPos_regnum
, oD_regnum
[2], oT_regnum
[8], oFog_regnum
, oFog_mask
, oPts_regnum
, oPts_mask
;
386 /* Pixel shader varying mapping. */
387 uint32_t t_regnum
[8], v_regnum
[2];
391 /* shader bytecode buffer manipulation functions.
392 * allocate_buffer creates a new buffer structure, put_u32 adds a new
393 * uint32_t to the buffer. In the rare case of a memory allocation failure
394 * when trying to grow the buffer a flag is set in the buffer to mark it
395 * invalid. This avoids return value checking and passing in many places
397 static struct bytecode_buffer
*allocate_buffer(void) {
398 struct bytecode_buffer
*ret
;
400 ret
= d3dcompiler_alloc(sizeof(*ret
));
401 if(!ret
) return NULL
;
406 static void put_u32(struct bytecode_buffer
*buffer
, uint32_t value
)
408 if (FAILED(buffer
->state
))
411 if (!array_reserve((void **)&buffer
->data
, &buffer
->alloc_size
, buffer
->size
+ 1, sizeof(*buffer
->data
)))
413 buffer
->state
= E_OUTOFMEMORY
;
417 buffer
->data
[buffer
->size
++] = value
;
420 /* bwriter -> d3d9 conversion functions. */
422 static uint32_t sm1_version(const struct bwriter_shader
*shader
)
424 switch (shader
->type
)
427 return D3DVS_VERSION(shader
->major_version
, shader
->minor_version
);
429 return D3DPS_VERSION(shader
->major_version
, shader
->minor_version
);
431 ERR("Invalid shader type %#x.\n", shader
->type
);
436 static uint32_t d3d9_swizzle(uint32_t bwriter_swizzle
)
440 if ((bwriter_swizzle
& BWRITERVS_X_X
) == BWRITERVS_X_X
) ret
|= D3DVS_X_X
;
441 if ((bwriter_swizzle
& BWRITERVS_X_Y
) == BWRITERVS_X_Y
) ret
|= D3DVS_X_Y
;
442 if ((bwriter_swizzle
& BWRITERVS_X_Z
) == BWRITERVS_X_Z
) ret
|= D3DVS_X_Z
;
443 if ((bwriter_swizzle
& BWRITERVS_X_W
) == BWRITERVS_X_W
) ret
|= D3DVS_X_W
;
445 if ((bwriter_swizzle
& BWRITERVS_Y_X
) == BWRITERVS_Y_X
) ret
|= D3DVS_Y_X
;
446 if ((bwriter_swizzle
& BWRITERVS_Y_Y
) == BWRITERVS_Y_Y
) ret
|= D3DVS_Y_Y
;
447 if ((bwriter_swizzle
& BWRITERVS_Y_Z
) == BWRITERVS_Y_Z
) ret
|= D3DVS_Y_Z
;
448 if ((bwriter_swizzle
& BWRITERVS_Y_W
) == BWRITERVS_Y_W
) ret
|= D3DVS_Y_W
;
450 if ((bwriter_swizzle
& BWRITERVS_Z_X
) == BWRITERVS_Z_X
) ret
|= D3DVS_Z_X
;
451 if ((bwriter_swizzle
& BWRITERVS_Z_Y
) == BWRITERVS_Z_Y
) ret
|= D3DVS_Z_Y
;
452 if ((bwriter_swizzle
& BWRITERVS_Z_Z
) == BWRITERVS_Z_Z
) ret
|= D3DVS_Z_Z
;
453 if ((bwriter_swizzle
& BWRITERVS_Z_W
) == BWRITERVS_Z_W
) ret
|= D3DVS_Z_W
;
455 if ((bwriter_swizzle
& BWRITERVS_W_X
) == BWRITERVS_W_X
) ret
|= D3DVS_W_X
;
456 if ((bwriter_swizzle
& BWRITERVS_W_Y
) == BWRITERVS_W_Y
) ret
|= D3DVS_W_Y
;
457 if ((bwriter_swizzle
& BWRITERVS_W_Z
) == BWRITERVS_W_Z
) ret
|= D3DVS_W_Z
;
458 if ((bwriter_swizzle
& BWRITERVS_W_W
) == BWRITERVS_W_W
) ret
|= D3DVS_W_W
;
463 static uint32_t d3d9_writemask(uint32_t bwriter_writemask
)
467 if (bwriter_writemask
& BWRITERSP_WRITEMASK_0
) ret
|= D3DSP_WRITEMASK_0
;
468 if (bwriter_writemask
& BWRITERSP_WRITEMASK_1
) ret
|= D3DSP_WRITEMASK_1
;
469 if (bwriter_writemask
& BWRITERSP_WRITEMASK_2
) ret
|= D3DSP_WRITEMASK_2
;
470 if (bwriter_writemask
& BWRITERSP_WRITEMASK_3
) ret
|= D3DSP_WRITEMASK_3
;
475 static uint32_t d3d9_srcmod(uint32_t bwriter_srcmod
)
477 switch (bwriter_srcmod
)
479 case BWRITERSPSM_NONE
: return D3DSPSM_NONE
;
480 case BWRITERSPSM_NEG
: return D3DSPSM_NEG
;
481 case BWRITERSPSM_BIAS
: return D3DSPSM_BIAS
;
482 case BWRITERSPSM_BIASNEG
: return D3DSPSM_BIASNEG
;
483 case BWRITERSPSM_SIGN
: return D3DSPSM_SIGN
;
484 case BWRITERSPSM_SIGNNEG
: return D3DSPSM_SIGNNEG
;
485 case BWRITERSPSM_COMP
: return D3DSPSM_COMP
;
486 case BWRITERSPSM_X2
: return D3DSPSM_X2
;
487 case BWRITERSPSM_X2NEG
: return D3DSPSM_X2NEG
;
488 case BWRITERSPSM_DZ
: return D3DSPSM_DZ
;
489 case BWRITERSPSM_DW
: return D3DSPSM_DW
;
490 case BWRITERSPSM_ABS
: return D3DSPSM_ABS
;
491 case BWRITERSPSM_ABSNEG
: return D3DSPSM_ABSNEG
;
492 case BWRITERSPSM_NOT
: return D3DSPSM_NOT
;
494 FIXME("Unhandled BWRITERSPSM token %#x.\n", bwriter_srcmod
);
499 static uint32_t d3d9_dstmod(uint32_t bwriter_mod
)
503 if (bwriter_mod
& BWRITERSPDM_SATURATE
) ret
|= D3DSPDM_SATURATE
;
504 if (bwriter_mod
& BWRITERSPDM_PARTIALPRECISION
) ret
|= D3DSPDM_PARTIALPRECISION
;
505 if (bwriter_mod
& BWRITERSPDM_MSAMPCENTROID
) ret
|= D3DSPDM_MSAMPCENTROID
;
510 static uint32_t d3d9_comparetype(uint32_t asmshader_comparetype
)
512 switch (asmshader_comparetype
)
514 case BWRITER_COMPARISON_GT
: return D3DSPC_GT
;
515 case BWRITER_COMPARISON_EQ
: return D3DSPC_EQ
;
516 case BWRITER_COMPARISON_GE
: return D3DSPC_GE
;
517 case BWRITER_COMPARISON_LT
: return D3DSPC_LT
;
518 case BWRITER_COMPARISON_NE
: return D3DSPC_NE
;
519 case BWRITER_COMPARISON_LE
: return D3DSPC_LE
;
521 FIXME("Unexpected BWRITER_COMPARISON type %#x.\n", asmshader_comparetype
);
526 static uint32_t d3d9_sampler(uint32_t bwriter_sampler
)
528 if (bwriter_sampler
== BWRITERSTT_UNKNOWN
) return D3DSTT_UNKNOWN
;
529 if (bwriter_sampler
== BWRITERSTT_1D
) return D3DSTT_1D
;
530 if (bwriter_sampler
== BWRITERSTT_2D
) return D3DSTT_2D
;
531 if (bwriter_sampler
== BWRITERSTT_CUBE
) return D3DSTT_CUBE
;
532 if (bwriter_sampler
== BWRITERSTT_VOLUME
) return D3DSTT_VOLUME
;
533 FIXME("Unexpected BWRITERSAMPLER_TEXTURE_TYPE type %#x.\n", bwriter_sampler
);
538 static uint32_t d3d9_register(uint32_t bwriter_register
)
540 if (bwriter_register
== BWRITERSPR_TEMP
) return D3DSPR_TEMP
;
541 if (bwriter_register
== BWRITERSPR_INPUT
) return D3DSPR_INPUT
;
542 if (bwriter_register
== BWRITERSPR_CONST
) return D3DSPR_CONST
;
543 if (bwriter_register
== BWRITERSPR_ADDR
) return D3DSPR_ADDR
;
544 if (bwriter_register
== BWRITERSPR_TEXTURE
) return D3DSPR_TEXTURE
;
545 if (bwriter_register
== BWRITERSPR_RASTOUT
) return D3DSPR_RASTOUT
;
546 if (bwriter_register
== BWRITERSPR_ATTROUT
) return D3DSPR_ATTROUT
;
547 if (bwriter_register
== BWRITERSPR_TEXCRDOUT
) return D3DSPR_TEXCRDOUT
;
548 if (bwriter_register
== BWRITERSPR_OUTPUT
) return D3DSPR_OUTPUT
;
549 if (bwriter_register
== BWRITERSPR_CONSTINT
) return D3DSPR_CONSTINT
;
550 if (bwriter_register
== BWRITERSPR_COLOROUT
) return D3DSPR_COLOROUT
;
551 if (bwriter_register
== BWRITERSPR_DEPTHOUT
) return D3DSPR_DEPTHOUT
;
552 if (bwriter_register
== BWRITERSPR_SAMPLER
) return D3DSPR_SAMPLER
;
553 if (bwriter_register
== BWRITERSPR_CONSTBOOL
) return D3DSPR_CONSTBOOL
;
554 if (bwriter_register
== BWRITERSPR_LOOP
) return D3DSPR_LOOP
;
555 if (bwriter_register
== BWRITERSPR_MISCTYPE
) return D3DSPR_MISCTYPE
;
556 if (bwriter_register
== BWRITERSPR_LABEL
) return D3DSPR_LABEL
;
557 if (bwriter_register
== BWRITERSPR_PREDICATE
) return D3DSPR_PREDICATE
;
559 FIXME("Unexpected BWRITERSPR %#x.\n", bwriter_register
);
563 static uint32_t d3d9_opcode(uint32_t bwriter_opcode
)
565 switch (bwriter_opcode
)
567 case BWRITERSIO_NOP
: return D3DSIO_NOP
;
568 case BWRITERSIO_MOV
: return D3DSIO_MOV
;
569 case BWRITERSIO_ADD
: return D3DSIO_ADD
;
570 case BWRITERSIO_SUB
: return D3DSIO_SUB
;
571 case BWRITERSIO_MAD
: return D3DSIO_MAD
;
572 case BWRITERSIO_MUL
: return D3DSIO_MUL
;
573 case BWRITERSIO_RCP
: return D3DSIO_RCP
;
574 case BWRITERSIO_RSQ
: return D3DSIO_RSQ
;
575 case BWRITERSIO_DP3
: return D3DSIO_DP3
;
576 case BWRITERSIO_DP4
: return D3DSIO_DP4
;
577 case BWRITERSIO_MIN
: return D3DSIO_MIN
;
578 case BWRITERSIO_MAX
: return D3DSIO_MAX
;
579 case BWRITERSIO_SLT
: return D3DSIO_SLT
;
580 case BWRITERSIO_SGE
: return D3DSIO_SGE
;
581 case BWRITERSIO_EXP
: return D3DSIO_EXP
;
582 case BWRITERSIO_LOG
: return D3DSIO_LOG
;
583 case BWRITERSIO_LIT
: return D3DSIO_LIT
;
584 case BWRITERSIO_DST
: return D3DSIO_DST
;
585 case BWRITERSIO_LRP
: return D3DSIO_LRP
;
586 case BWRITERSIO_FRC
: return D3DSIO_FRC
;
587 case BWRITERSIO_M4x4
: return D3DSIO_M4x4
;
588 case BWRITERSIO_M4x3
: return D3DSIO_M4x3
;
589 case BWRITERSIO_M3x4
: return D3DSIO_M3x4
;
590 case BWRITERSIO_M3x3
: return D3DSIO_M3x3
;
591 case BWRITERSIO_M3x2
: return D3DSIO_M3x2
;
592 case BWRITERSIO_CALL
: return D3DSIO_CALL
;
593 case BWRITERSIO_CALLNZ
: return D3DSIO_CALLNZ
;
594 case BWRITERSIO_LOOP
: return D3DSIO_LOOP
;
595 case BWRITERSIO_RET
: return D3DSIO_RET
;
596 case BWRITERSIO_ENDLOOP
: return D3DSIO_ENDLOOP
;
597 case BWRITERSIO_LABEL
: return D3DSIO_LABEL
;
598 case BWRITERSIO_DCL
: return D3DSIO_DCL
;
599 case BWRITERSIO_POW
: return D3DSIO_POW
;
600 case BWRITERSIO_CRS
: return D3DSIO_CRS
;
601 case BWRITERSIO_SGN
: return D3DSIO_SGN
;
602 case BWRITERSIO_ABS
: return D3DSIO_ABS
;
603 case BWRITERSIO_NRM
: return D3DSIO_NRM
;
604 case BWRITERSIO_SINCOS
: return D3DSIO_SINCOS
;
605 case BWRITERSIO_REP
: return D3DSIO_REP
;
606 case BWRITERSIO_ENDREP
: return D3DSIO_ENDREP
;
607 case BWRITERSIO_IF
: return D3DSIO_IF
;
608 case BWRITERSIO_IFC
: return D3DSIO_IFC
;
609 case BWRITERSIO_ELSE
: return D3DSIO_ELSE
;
610 case BWRITERSIO_ENDIF
: return D3DSIO_ENDIF
;
611 case BWRITERSIO_BREAK
: return D3DSIO_BREAK
;
612 case BWRITERSIO_BREAKC
: return D3DSIO_BREAKC
;
613 case BWRITERSIO_MOVA
: return D3DSIO_MOVA
;
614 case BWRITERSIO_DEFB
: return D3DSIO_DEFB
;
615 case BWRITERSIO_DEFI
: return D3DSIO_DEFI
;
617 case BWRITERSIO_TEXCOORD
: return D3DSIO_TEXCOORD
;
618 case BWRITERSIO_TEXKILL
: return D3DSIO_TEXKILL
;
619 case BWRITERSIO_TEX
: return D3DSIO_TEX
;
620 case BWRITERSIO_TEXBEM
: return D3DSIO_TEXBEM
;
621 case BWRITERSIO_TEXBEML
: return D3DSIO_TEXBEML
;
622 case BWRITERSIO_TEXREG2AR
: return D3DSIO_TEXREG2AR
;
623 case BWRITERSIO_TEXREG2GB
: return D3DSIO_TEXREG2GB
;
624 case BWRITERSIO_TEXM3x2PAD
: return D3DSIO_TEXM3x2PAD
;
625 case BWRITERSIO_TEXM3x2TEX
: return D3DSIO_TEXM3x2TEX
;
626 case BWRITERSIO_TEXM3x3PAD
: return D3DSIO_TEXM3x3PAD
;
627 case BWRITERSIO_TEXM3x3TEX
: return D3DSIO_TEXM3x3TEX
;
628 case BWRITERSIO_TEXM3x3SPEC
: return D3DSIO_TEXM3x3SPEC
;
629 case BWRITERSIO_TEXM3x3VSPEC
:return D3DSIO_TEXM3x3VSPEC
;
630 case BWRITERSIO_EXPP
: return D3DSIO_EXPP
;
631 case BWRITERSIO_LOGP
: return D3DSIO_LOGP
;
632 case BWRITERSIO_CND
: return D3DSIO_CND
;
633 case BWRITERSIO_DEF
: return D3DSIO_DEF
;
634 case BWRITERSIO_TEXREG2RGB
: return D3DSIO_TEXREG2RGB
;
635 case BWRITERSIO_TEXDP3TEX
: return D3DSIO_TEXDP3TEX
;
636 case BWRITERSIO_TEXM3x2DEPTH
:return D3DSIO_TEXM3x2DEPTH
;
637 case BWRITERSIO_TEXDP3
: return D3DSIO_TEXDP3
;
638 case BWRITERSIO_TEXM3x3
: return D3DSIO_TEXM3x3
;
639 case BWRITERSIO_TEXDEPTH
: return D3DSIO_TEXDEPTH
;
640 case BWRITERSIO_CMP
: return D3DSIO_CMP
;
641 case BWRITERSIO_BEM
: return D3DSIO_BEM
;
642 case BWRITERSIO_DP2ADD
: return D3DSIO_DP2ADD
;
643 case BWRITERSIO_DSX
: return D3DSIO_DSX
;
644 case BWRITERSIO_DSY
: return D3DSIO_DSY
;
645 case BWRITERSIO_TEXLDD
: return D3DSIO_TEXLDD
;
646 case BWRITERSIO_SETP
: return D3DSIO_SETP
;
647 case BWRITERSIO_TEXLDL
: return D3DSIO_TEXLDL
;
648 case BWRITERSIO_BREAKP
: return D3DSIO_BREAKP
;
650 case BWRITERSIO_PHASE
: return D3DSIO_PHASE
;
651 case BWRITERSIO_COMMENT
: return D3DSIO_COMMENT
;
652 case BWRITERSIO_END
: return D3DSIO_END
;
654 case BWRITERSIO_TEXLDP
: return D3DSIO_TEX
| D3DSI_TEXLD_PROJECT
;
655 case BWRITERSIO_TEXLDB
: return D3DSIO_TEX
| D3DSI_TEXLD_BIAS
;
658 FIXME("Unhandled BWRITERSIO token %#x.\n", bwriter_opcode
);
663 static uint32_t d3dsp_register(D3DSHADER_PARAM_REGISTER_TYPE type
, uint32_t num
)
665 return ((type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
) |
666 ((type
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
) |
667 (num
& D3DSP_REGNUM_MASK
); /* No shift */
670 /******************************************************
671 * Implementation of the writer functions starts here *
672 ******************************************************/
673 static void write_declarations(struct bc_writer
*writer
, struct bytecode_buffer
*buffer
,
674 const struct declaration
*decls
, unsigned int num
, uint32_t type
)
676 uint32_t instr_dcl
= D3DSIO_DCL
;
679 struct shader_reg reg
;
681 ZeroMemory(®
, sizeof(reg
));
683 if (writer
->shader
->major_version
> 1)
684 instr_dcl
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
686 for(i
= 0; i
< num
; i
++) {
687 if(decls
[i
].builtin
) continue;
689 /* Write the DCL instruction */
690 put_u32(buffer
, instr_dcl
);
692 /* Write the usage and index */
693 token
= (1u << 31); /* Bit 31 of non-instruction opcodes is 1 */
694 token
|= (decls
[i
].usage
<< D3DSP_DCL_USAGE_SHIFT
) & D3DSP_DCL_USAGE_MASK
;
695 token
|= (decls
[i
].usage_idx
<< D3DSP_DCL_USAGEINDEX_SHIFT
) & D3DSP_DCL_USAGEINDEX_MASK
;
696 put_u32(buffer
, token
);
698 /* Write the dest register */
700 reg
.regnum
= decls
[i
].regnum
;
701 reg
.writemask
= decls
[i
].writemask
;
702 writer
->funcs
->dstreg(writer
, ®
, buffer
, 0, decls
[i
].mod
);
706 static void write_const(struct constant
**consts
, int num
, uint32_t opcode
, uint32_t reg_type
, struct bytecode_buffer
*buffer
, BOOL len
)
708 const uint32_t reg
= (1u << 31) | d3dsp_register( reg_type
, 0 ) | D3DSP_WRITEMASK_ALL
;
709 uint32_t instr_def
= opcode
;
713 if(opcode
== D3DSIO_DEFB
)
714 instr_def
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
716 instr_def
|= 5 << D3DSI_INSTLENGTH_SHIFT
;
719 for(i
= 0; i
< num
; i
++) {
720 /* Write the DEF instruction */
721 put_u32(buffer
, instr_def
);
723 put_u32(buffer
, reg
| (consts
[i
]->regnum
& D3DSP_REGNUM_MASK
));
724 put_u32(buffer
, consts
[i
]->value
[0].d
);
725 if(opcode
!= D3DSIO_DEFB
) {
726 put_u32(buffer
, consts
[i
]->value
[1].d
);
727 put_u32(buffer
, consts
[i
]->value
[2].d
);
728 put_u32(buffer
, consts
[i
]->value
[3].d
);
733 static void write_constF(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
734 write_const(shader
->constF
, shader
->num_cf
, D3DSIO_DEF
, D3DSPR_CONST
, buffer
, len
);
737 /* This function looks for VS 1/2 registers mapping to VS 3 output registers */
738 static HRESULT
vs_find_builtin_varyings(struct bc_writer
*writer
, const struct bwriter_shader
*shader
)
740 uint32_t usage
, usage_idx
, writemask
, regnum
;
743 for (i
= 0; i
< shader
->num_outputs
; i
++)
745 if (!shader
->outputs
[i
].builtin
)
748 usage
= shader
->outputs
[i
].usage
;
749 usage_idx
= shader
->outputs
[i
].usage_idx
;
750 writemask
= shader
->outputs
[i
].writemask
;
751 regnum
= shader
->outputs
[i
].regnum
;
755 case BWRITERDECLUSAGE_POSITION
:
756 case BWRITERDECLUSAGE_POSITIONT
:
759 WARN("dcl_position%u not supported in sm 1/2 shaders.\n", usage_idx
);
762 TRACE("o%u is oPos.\n", regnum
);
763 writer
->oPos_regnum
= regnum
;
766 case BWRITERDECLUSAGE_COLOR
:
769 WARN("dcl_color%u not supported in sm 1/2 shaders.\n", usage_idx
);
772 if (writemask
!= BWRITERSP_WRITEMASK_ALL
)
774 WARN("Only WRITEMASK_ALL is supported on color in sm 1/2\n");
777 TRACE("o%u is oD%u.\n", regnum
, usage_idx
);
778 writer
->oD_regnum
[usage_idx
] = regnum
;
781 case BWRITERDECLUSAGE_TEXCOORD
:
784 WARN("dcl_color%u not supported in sm 1/2 shaders.\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
))
792 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
795 TRACE("o%u is oT%u.\n", regnum
, usage_idx
);
796 writer
->oT_regnum
[usage_idx
] = regnum
;
799 case BWRITERDECLUSAGE_PSIZE
:
802 WARN("dcl_psize%u not supported in sm 1/2 shaders.\n", usage_idx
);
805 TRACE("o%u writemask 0x%08x is oPts.\n", regnum
, writemask
);
806 writer
->oPts_regnum
= regnum
;
807 writer
->oPts_mask
= writemask
;
810 case BWRITERDECLUSAGE_FOG
:
813 WARN("dcl_fog%u not supported in sm 1 shaders.\n", usage_idx
);
816 if (writemask
!= BWRITERSP_WRITEMASK_0
&& writemask
!= BWRITERSP_WRITEMASK_1
817 && writemask
!= BWRITERSP_WRITEMASK_2
&& writemask
!= BWRITERSP_WRITEMASK_3
)
819 WARN("Unsupported fog writemask\n");
822 TRACE("o%u writemask 0x%08x is oFog.\n", regnum
, writemask
);
823 writer
->oFog_regnum
= regnum
;
824 writer
->oFog_mask
= writemask
;
828 WARN("Varying type %u is not supported in shader model 1.x.\n", usage
);
836 static void vs_1_x_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
839 if(shader
->num_ci
|| shader
->num_cb
) {
840 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
841 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
842 This
->state
= E_INVALIDARG
;
846 hr
= vs_find_builtin_varyings(This
, shader
);
852 write_declarations(This
, buffer
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
853 write_constF(shader
, buffer
, FALSE
);
856 static HRESULT
find_ps_builtin_semantics(struct bc_writer
*writer
, const struct bwriter_shader
*shader
,
859 uint32_t usage
, usage_idx
, writemask
, regnum
;
862 writer
->v_regnum
[0] = -1;
863 writer
->v_regnum
[1] = -1;
864 for (i
= 0; i
< 8; i
++)
865 writer
->t_regnum
[i
] = -1;
867 for (i
= 0; i
< shader
->num_inputs
; i
++)
869 if (!shader
->inputs
[i
].builtin
)
872 usage
= shader
->inputs
[i
].usage
;
873 usage_idx
= shader
->inputs
[i
].usage_idx
;
874 writemask
= shader
->inputs
[i
].writemask
;
875 regnum
= shader
->inputs
[i
].regnum
;
879 case BWRITERDECLUSAGE_COLOR
:
882 WARN("dcl_color%u not supported in sm 1 shaders\n", usage_idx
);
885 if (writemask
!= BWRITERSP_WRITEMASK_ALL
)
887 WARN("Only WRITEMASK_ALL is supported on color in sm 1\n");
890 TRACE("v%u is v%u\n", regnum
, usage_idx
);
891 writer
->v_regnum
[usage_idx
] = regnum
;
894 case BWRITERDECLUSAGE_TEXCOORD
:
895 if (usage_idx
> texcoords
)
897 WARN("dcl_texcoord%u not supported in this shader version\n", usage_idx
);
900 if (writemask
!= (BWRITERSP_WRITEMASK_0
)
901 && writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
)
902 && writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
| BWRITERSP_WRITEMASK_2
)
903 && writemask
!= (BWRITERSP_WRITEMASK_ALL
))
904 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
906 writemask
= BWRITERSP_WRITEMASK_ALL
;
907 TRACE("v%u is t%u\n", regnum
, usage_idx
);
908 writer
->t_regnum
[usage_idx
] = regnum
;
912 WARN("Varying type %u is not supported in shader model 1.x\n", usage
);
920 static void ps_1_x_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
923 /* First check the constants and varyings, and complain if unsupported things are used */
924 if(shader
->num_ci
|| shader
->num_cb
) {
925 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
926 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
927 This
->state
= E_INVALIDARG
;
931 hr
= find_ps_builtin_semantics(This
, shader
, 4);
937 write_constF(shader
, buffer
, FALSE
);
940 static void ps_1_4_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
943 /* First check the constants and varyings, and complain if unsupported things are used */
944 if(shader
->num_ci
|| shader
->num_cb
) {
945 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
946 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
947 This
->state
= E_INVALIDARG
;
950 hr
= find_ps_builtin_semantics(This
, shader
, 6);
956 write_constF(shader
, buffer
, FALSE
);
959 static void end(struct bc_writer
*writer
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
)
961 put_u32(buffer
, D3DSIO_END
);
964 static uint32_t map_vs_output(struct bc_writer
*writer
, uint32_t regnum
, uint32_t mask
, BOOL
*has_components
)
968 *has_components
= TRUE
;
969 if (regnum
== writer
->oPos_regnum
)
971 return d3dsp_register( D3DSPR_RASTOUT
, D3DSRO_POSITION
);
973 if (regnum
== writer
->oFog_regnum
&& mask
== writer
->oFog_mask
)
975 *has_components
= FALSE
;
976 return d3dsp_register( D3DSPR_RASTOUT
, D3DSRO_FOG
) | D3DSP_WRITEMASK_ALL
;
978 if (regnum
== writer
->oPts_regnum
&& mask
== writer
->oPts_mask
)
980 *has_components
= FALSE
;
981 return d3dsp_register( D3DSPR_RASTOUT
, D3DSRO_POINT_SIZE
) | D3DSP_WRITEMASK_ALL
;
983 for (i
= 0; i
< 2; i
++)
985 if (regnum
== writer
->oD_regnum
[i
])
986 return d3dsp_register( D3DSPR_ATTROUT
, i
);
988 for (i
= 0; i
< 8; i
++)
990 if (regnum
== writer
->oT_regnum
[i
])
991 return d3dsp_register( D3DSPR_TEXCRDOUT
, i
);
994 /* The varying must be undeclared - if an unsupported varying was declared,
995 * the vs_find_builtin_varyings function would have caught it and this code
997 WARN("Undeclared varying %u.\n", regnum
);
998 writer
->state
= E_INVALIDARG
;
1002 static void vs_12_dstreg(struct bc_writer
*writer
, const struct shader_reg
*reg
, struct bytecode_buffer
*buffer
,
1003 uint32_t shift
, uint32_t mod
)
1005 uint32_t token
= (1u << 31); /* Bit 31 of registers is 1 */
1010 WARN("Relative addressing not supported for destination registers\n");
1011 writer
->state
= E_INVALIDARG
;
1017 case BWRITERSPR_OUTPUT
:
1018 token
|= map_vs_output(writer
, reg
->regnum
, reg
->writemask
, &has_wmask
);
1021 case BWRITERSPR_RASTOUT
:
1022 case BWRITERSPR_ATTROUT
:
1023 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1024 * but are unexpected. If we hit this path it might be due to an error.
1026 FIXME("Unexpected register type %u.\n", reg
->type
);
1028 case BWRITERSPR_INPUT
:
1029 case BWRITERSPR_TEMP
:
1030 case BWRITERSPR_CONST
:
1031 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1035 case BWRITERSPR_ADDR
:
1036 if (reg
->regnum
!= 0)
1038 WARN("Only a0 exists\n");
1039 writer
->state
= E_INVALIDARG
;
1042 token
|= d3dsp_register( D3DSPR_ADDR
, 0 );
1046 case BWRITERSPR_PREDICATE
:
1047 if (writer
->shader
->major_version
!= 2 || writer
->shader
->minor_version
!= 1)
1049 WARN("Predicate register is allowed only in vs_2_x\n");
1050 writer
->state
= E_INVALIDARG
;
1053 if (reg
->regnum
!= 0)
1055 WARN("Only predicate register p0 exists\n");
1056 writer
->state
= E_INVALIDARG
;
1059 token
|= d3dsp_register( D3DSPR_PREDICATE
, 0 );
1064 WARN("Invalid register type for 1.x-2.x vertex shader\n");
1065 writer
->state
= E_INVALIDARG
;
1069 /* strictly speaking there are no modifiers in vs_2_0 and vs_1_x, but they can be written
1070 * into the bytecode and since the compiler doesn't do such checks write them
1071 * (the checks are done by the undocumented shader validator)
1073 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1074 token
|= d3d9_dstmod(mod
);
1077 token
|= d3d9_writemask(reg
->writemask
);
1078 put_u32(buffer
, token
);
1081 static void vs_1_x_srcreg(struct bc_writer
*writer
, const struct shader_reg
*reg
, struct bytecode_buffer
*buffer
)
1083 uint32_t token
= (1u << 31); /* Bit 31 of registers is 1 */
1089 case BWRITERSPR_OUTPUT
:
1090 /* Map the swizzle to a writemask, the format expected by
1092 switch (reg
->swizzle
)
1094 case BWRITERVS_SWIZZLE_X
:
1095 component
= BWRITERSP_WRITEMASK_0
;
1097 case BWRITERVS_SWIZZLE_Y
:
1098 component
= BWRITERSP_WRITEMASK_1
;
1100 case BWRITERVS_SWIZZLE_Z
:
1101 component
= BWRITERSP_WRITEMASK_2
;
1103 case BWRITERVS_SWIZZLE_W
:
1104 component
= BWRITERSP_WRITEMASK_3
;
1109 token
|= map_vs_output(writer
, reg
->regnum
, component
, &has_swizzle
);
1112 case BWRITERSPR_RASTOUT
:
1113 case BWRITERSPR_ATTROUT
:
1114 /* These registers are mapped to input and output regs. They can
1115 * be encoded in the bytecode, but are unexpected. If we hit this
1116 * path it might be due to an error. */
1117 FIXME("Unexpected register type %u.\n", reg
->type
);
1119 case BWRITERSPR_INPUT
:
1120 case BWRITERSPR_TEMP
:
1121 case BWRITERSPR_CONST
:
1122 case BWRITERSPR_ADDR
:
1123 token
|= d3dsp_register(reg
->type
, reg
->regnum
);
1126 if (reg
->rel_reg
->type
!= BWRITERSPR_ADDR
|| reg
->rel_reg
->regnum
!= 0
1127 || reg
->rel_reg
->swizzle
!= BWRITERVS_SWIZZLE_X
)
1129 WARN("Relative addressing in vs_1_x is only allowed with a0.x\n");
1130 writer
->state
= E_INVALIDARG
;
1133 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1138 WARN("Invalid register type for 1.x vshader\n");
1139 writer
->state
= E_INVALIDARG
;
1143 token
|= d3d9_swizzle(reg
->swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1145 token
|= d3d9_srcmod(reg
->srcmod
);
1146 put_u32(buffer
, token
);
1149 static void write_srcregs(struct bc_writer
*writer
, const struct instruction
*instr
, struct bytecode_buffer
*buffer
)
1153 if (instr
->has_predicate
)
1154 writer
->funcs
->srcreg(writer
, &instr
->predicate
, buffer
);
1156 for (i
= 0; i
< instr
->num_srcs
; ++i
)
1157 writer
->funcs
->srcreg(writer
, &instr
->src
[i
], buffer
);
1160 static uint32_t map_ps13_temp(struct bc_writer
*writer
, const struct shader_reg
*reg
)
1162 if (reg
->regnum
== T0_REG
)
1163 return d3dsp_register(D3DSPR_TEXTURE
, 0);
1164 if (reg
->regnum
== T1_REG
)
1165 return d3dsp_register(D3DSPR_TEXTURE
, 1);
1166 if(reg
->regnum
== T2_REG
)
1167 return d3dsp_register(D3DSPR_TEXTURE
, 2);
1168 if (reg
->regnum
== T3_REG
)
1169 return d3dsp_register(D3DSPR_TEXTURE
, 3);
1170 return d3dsp_register(D3DSPR_TEMP
, reg
->regnum
);
1173 static uint32_t map_ps_input(struct bc_writer
*writer
, const struct shader_reg
*reg
)
1177 /* Map color interpolators */
1178 for (i
= 0; i
< ARRAY_SIZE(writer
->v_regnum
); ++i
)
1180 if (reg
->regnum
== writer
->v_regnum
[i
])
1181 return d3dsp_register(D3DSPR_INPUT
, i
);
1183 for (i
= 0; i
< ARRAY_SIZE(writer
->t_regnum
); ++i
)
1185 if(reg
->regnum
== writer
->t_regnum
[i
])
1186 return d3dsp_register(D3DSPR_TEXTURE
, i
);
1189 WARN("Invalid ps 1/2 varying\n");
1190 writer
->state
= E_INVALIDARG
;
1194 static void ps_1_0123_srcreg(struct bc_writer
*writer
, const struct shader_reg
*reg
, struct bytecode_buffer
*buffer
)
1196 uint32_t token
= 1u << 31;
1200 WARN("Relative addressing not supported in <= ps_3_0\n");
1201 writer
->state
= E_INVALIDARG
;
1207 case BWRITERSPR_INPUT
:
1208 token
|= map_ps_input(writer
, reg
);
1211 /* Take care about the texture temporaries. There's a problem: They aren't
1212 * declared anywhere, so we can only hardcode the values that are used
1213 * to map ps_1_3 shaders to the common shader structure
1215 case BWRITERSPR_TEMP
:
1216 token
|= map_ps13_temp(writer
, reg
);
1219 case BWRITERSPR_CONST
: /* Can be mapped 1:1 */
1220 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1224 WARN("Invalid register type for <= ps_1_3 shader\n");
1225 writer
->state
= E_INVALIDARG
;
1229 token
|= d3d9_swizzle(reg
->swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1231 if(reg
->srcmod
== BWRITERSPSM_DZ
|| reg
->srcmod
== BWRITERSPSM_DW
1232 || reg
->srcmod
== BWRITERSPSM_ABS
|| reg
->srcmod
== BWRITERSPSM_ABSNEG
1233 || reg
->srcmod
== BWRITERSPSM_NOT
)
1235 WARN("Invalid source modifier %u for <= ps_1_3\n", reg
->srcmod
);
1236 writer
->state
= E_INVALIDARG
;
1239 token
|= d3d9_srcmod(reg
->srcmod
);
1240 put_u32(buffer
, token
);
1243 static void ps_1_0123_dstreg(struct bc_writer
*writer
, const struct shader_reg
*reg
, struct bytecode_buffer
*buffer
,
1244 uint32_t shift
, uint32_t mod
)
1246 uint32_t token
= (1u << 31); /* Bit 31 of registers is 1 */
1250 WARN("Relative addressing not supported for destination registers\n");
1251 writer
->state
= E_INVALIDARG
;
1257 case BWRITERSPR_TEMP
:
1258 token
|= map_ps13_temp(writer
, reg
);
1261 /* texkill uses the input register as a destination parameter */
1262 case BWRITERSPR_INPUT
:
1263 token
|= map_ps_input(writer
, reg
);
1267 WARN("Invalid dest register type for 1.x pshader\n");
1268 writer
->state
= E_INVALIDARG
;
1272 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1273 token
|= d3d9_dstmod(mod
);
1275 token
|= d3d9_writemask(reg
->writemask
);
1276 put_u32(buffer
, token
);
1279 /* The length of an instruction consists of the destination register (if any),
1280 * the number of source registers, the number of address registers used for
1281 * indirect addressing, and optionally the predicate register */
1282 static unsigned int instrlen(const struct instruction
*instr
, unsigned int srcs
, unsigned int dsts
)
1284 unsigned int ret
= srcs
+ dsts
+ (instr
->has_predicate
? 1 : 0);
1287 if (dsts
&& instr
->dst
.rel_reg
)
1289 for (i
= 0; i
< srcs
; ++i
)
1290 if (instr
->src
[i
].rel_reg
)
1295 static void sm_1_x_opcode(struct bc_writer
*writer
, const struct instruction
*instr
, uint32_t token
,
1296 struct bytecode_buffer
*buffer
)
1298 /* Instruction length isn't encoded in sm_1_x. */
1300 token
|= D3DSI_COISSUE
;
1301 put_u32(buffer
, token
);
1304 static void instr_handler(struct bc_writer
*writer
, const struct instruction
*instr
, struct bytecode_buffer
*buffer
)
1306 uint32_t token
= d3d9_opcode(instr
->opcode
);
1308 writer
->funcs
->opcode(writer
, instr
, token
, buffer
);
1310 writer
->funcs
->dstreg(writer
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1311 write_srcregs(writer
, instr
, buffer
);
1314 static const struct instr_handler_table vs_1_x_handlers
[] = {
1315 {BWRITERSIO_ADD
, instr_handler
},
1316 {BWRITERSIO_NOP
, instr_handler
},
1317 {BWRITERSIO_MOV
, instr_handler
},
1318 {BWRITERSIO_SUB
, instr_handler
},
1319 {BWRITERSIO_MAD
, instr_handler
},
1320 {BWRITERSIO_MUL
, instr_handler
},
1321 {BWRITERSIO_RCP
, instr_handler
},
1322 {BWRITERSIO_RSQ
, instr_handler
},
1323 {BWRITERSIO_DP3
, instr_handler
},
1324 {BWRITERSIO_DP4
, instr_handler
},
1325 {BWRITERSIO_MIN
, instr_handler
},
1326 {BWRITERSIO_MAX
, instr_handler
},
1327 {BWRITERSIO_SLT
, instr_handler
},
1328 {BWRITERSIO_SGE
, instr_handler
},
1329 {BWRITERSIO_EXP
, instr_handler
},
1330 {BWRITERSIO_LOG
, instr_handler
},
1331 {BWRITERSIO_EXPP
, instr_handler
},
1332 {BWRITERSIO_LOGP
, instr_handler
},
1333 {BWRITERSIO_DST
, instr_handler
},
1334 {BWRITERSIO_FRC
, instr_handler
},
1335 {BWRITERSIO_M4x4
, instr_handler
},
1336 {BWRITERSIO_M4x3
, instr_handler
},
1337 {BWRITERSIO_M3x4
, instr_handler
},
1338 {BWRITERSIO_M3x3
, instr_handler
},
1339 {BWRITERSIO_M3x2
, instr_handler
},
1340 {BWRITERSIO_LIT
, instr_handler
},
1342 {BWRITERSIO_END
, NULL
}, /* Sentinel value, it signals
1343 the end of the list */
1346 static const struct bytecode_backend vs_1_x_backend
= {
1355 static void instr_ps_1_0123_texld(struct bc_writer
*writer
, const struct instruction
*instr
,
1356 struct bytecode_buffer
*buffer
)
1358 struct shader_reg reg
;
1359 uint32_t swizzlemask
;
1362 if (instr
->src
[1].type
!= BWRITERSPR_SAMPLER
|| instr
->src
[1].regnum
> 3)
1364 WARN("Unsupported sampler type %u regnum %u.\n", instr
->src
[1].type
, instr
->src
[1].regnum
);
1365 writer
->state
= E_INVALIDARG
;
1368 else if (instr
->dst
.type
!= BWRITERSPR_TEMP
)
1370 WARN("Can only sample into a temp register\n");
1371 writer
->state
= E_INVALIDARG
;
1375 idx
= instr
->src
[1].regnum
;
1376 if ((idx
== 0 && instr
->dst
.regnum
!= T0_REG
) || (idx
== 1 && instr
->dst
.regnum
!= T1_REG
)
1377 || (idx
== 2 && instr
->dst
.regnum
!= T2_REG
) || (idx
== 3 && instr
->dst
.regnum
!= T3_REG
))
1379 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_x\n", idx
, instr
->dst
.regnum
);
1380 writer
->state
= E_INVALIDARG
;
1383 if (instr
->src
[0].type
== BWRITERSPR_INPUT
)
1385 /* A simple non-dependent read tex instruction */
1386 if (instr
->src
[0].regnum
!= writer
->t_regnum
[idx
])
1388 WARN("Cannot sample from s%u with texture address data from interpolator %u\n", idx
, instr
->src
[0].regnum
);
1389 writer
->state
= E_INVALIDARG
;
1392 writer
->funcs
->opcode(writer
, instr
, D3DSIO_TEX
& D3DSI_OPCODE_MASK
, buffer
);
1394 /* map the temp dstreg to the ps_1_3 texture temporary register */
1395 writer
->funcs
->dstreg(writer
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1397 else if (instr
->src
[0].type
== BWRITERSPR_TEMP
)
1399 swizzlemask
= 3 | (3 << 2) | (3 << 4);
1400 if ((instr
->src
[0].swizzle
& swizzlemask
) == (BWRITERVS_X_X
| BWRITERVS_Y_Y
| BWRITERVS_Z_Z
))
1402 TRACE("writing texreg2rgb\n");
1403 writer
->funcs
->opcode(writer
, instr
, D3DSIO_TEXREG2RGB
& D3DSI_OPCODE_MASK
, buffer
);
1405 else if (instr
->src
[0].swizzle
== (BWRITERVS_X_W
| BWRITERVS_Y_X
| BWRITERVS_Z_X
| BWRITERVS_W_X
))
1407 TRACE("writing texreg2ar\n");
1408 writer
->funcs
->opcode(writer
, instr
, D3DSIO_TEXREG2AR
& D3DSI_OPCODE_MASK
, buffer
);
1410 else if (instr
->src
[0].swizzle
== (BWRITERVS_X_Y
| BWRITERVS_Y_Z
| BWRITERVS_Z_Z
| BWRITERVS_W_Z
))
1412 TRACE("writing texreg2gb\n");
1413 writer
->funcs
->opcode(writer
, instr
, D3DSIO_TEXREG2GB
& D3DSI_OPCODE_MASK
, buffer
);
1417 WARN("Unsupported src addr swizzle in dependent texld: 0x%08x\n", instr
->src
[0].swizzle
);
1418 writer
->state
= E_INVALIDARG
;
1422 /* Dst and src reg can be mapped normally. Both registers are
1423 * temporary registers in the source shader and have to be mapped to
1424 * the temporary form of the texture registers. However, the src reg
1425 * doesn't have a swizzle. */
1426 writer
->funcs
->dstreg(writer
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1427 reg
= instr
->src
[0];
1428 reg
.swizzle
= BWRITERVS_NOSWIZZLE
;
1429 writer
->funcs
->srcreg(writer
, ®
, buffer
);
1433 WARN("Invalid address data source register\n");
1434 writer
->state
= E_INVALIDARG
;
1439 static void instr_ps_1_0123_mov(struct bc_writer
*writer
, const struct instruction
*instr
,
1440 struct bytecode_buffer
*buffer
)
1442 uint32_t token
= D3DSIO_MOV
& D3DSI_OPCODE_MASK
;
1444 if (instr
->dst
.type
== BWRITERSPR_TEMP
&& instr
->src
[0].type
== BWRITERSPR_INPUT
)
1446 if ((instr
->dst
.regnum
== T0_REG
&& instr
->src
[0].regnum
== writer
->t_regnum
[0])
1447 || (instr
->dst
.regnum
== T1_REG
&& instr
->src
[0].regnum
== writer
->t_regnum
[1])
1448 || (instr
->dst
.regnum
== T2_REG
&& instr
->src
[0].regnum
== writer
->t_regnum
[2])
1449 || (instr
->dst
.regnum
== T3_REG
&& instr
->src
[0].regnum
== writer
->t_regnum
[3]))
1451 if (instr
->dstmod
& BWRITERSPDM_SATURATE
)
1453 writer
->funcs
->opcode(writer
, instr
, D3DSIO_TEXCOORD
& D3DSI_OPCODE_MASK
, buffer
);
1454 /* Remove the SATURATE flag, it's implicit to the instruction */
1455 writer
->funcs
->dstreg(writer
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
& (~BWRITERSPDM_SATURATE
));
1460 WARN("A varying -> temp copy is only supported with the SATURATE modifier in <=ps_1_3\n");
1461 writer
->state
= E_INVALIDARG
;
1465 else if (instr
->src
[0].regnum
== writer
->v_regnum
[0] || instr
->src
[0].regnum
== writer
->v_regnum
[1])
1467 /* Handled by the normal mov below. Just drop out of the if condition */
1471 WARN("Unsupported varying -> temp mov in <= ps_1_3\n");
1472 writer
->state
= E_INVALIDARG
;
1477 writer
->funcs
->opcode(writer
, instr
, token
, buffer
);
1478 writer
->funcs
->dstreg(writer
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1479 writer
->funcs
->srcreg(writer
, &instr
->src
[0], buffer
);
1482 static const struct instr_handler_table ps_1_0123_handlers
[] = {
1483 {BWRITERSIO_ADD
, instr_handler
},
1484 {BWRITERSIO_NOP
, instr_handler
},
1485 {BWRITERSIO_MOV
, instr_ps_1_0123_mov
},
1486 {BWRITERSIO_SUB
, instr_handler
},
1487 {BWRITERSIO_MAD
, instr_handler
},
1488 {BWRITERSIO_MUL
, instr_handler
},
1489 {BWRITERSIO_DP3
, instr_handler
},
1490 {BWRITERSIO_DP4
, instr_handler
},
1491 {BWRITERSIO_LRP
, instr_handler
},
1493 /* pshader instructions */
1494 {BWRITERSIO_CND
, instr_handler
},
1495 {BWRITERSIO_CMP
, instr_handler
},
1496 {BWRITERSIO_TEXKILL
, instr_handler
},
1497 {BWRITERSIO_TEX
, instr_ps_1_0123_texld
},
1498 {BWRITERSIO_TEXBEM
, instr_handler
},
1499 {BWRITERSIO_TEXBEML
, instr_handler
},
1500 {BWRITERSIO_TEXM3x2PAD
, instr_handler
},
1501 {BWRITERSIO_TEXM3x3PAD
, instr_handler
},
1502 {BWRITERSIO_TEXM3x3SPEC
, instr_handler
},
1503 {BWRITERSIO_TEXM3x3VSPEC
, instr_handler
},
1504 {BWRITERSIO_TEXM3x3TEX
, instr_handler
},
1505 {BWRITERSIO_TEXM3x3
, instr_handler
},
1506 {BWRITERSIO_TEXM3x2DEPTH
, instr_handler
},
1507 {BWRITERSIO_TEXM3x2TEX
, instr_handler
},
1508 {BWRITERSIO_TEXDP3
, instr_handler
},
1509 {BWRITERSIO_TEXDP3TEX
, instr_handler
},
1510 {BWRITERSIO_END
, NULL
},
1513 static const struct bytecode_backend ps_1_0123_backend
= {
1522 static void ps_1_4_srcreg(struct bc_writer
*writer
, const struct shader_reg
*reg
, struct bytecode_buffer
*buffer
)
1524 uint32_t token
= 1u << 31; /* Bit 31 of registers is 1. */
1528 WARN("Relative addressing not supported in <= ps_3_0.\n");
1529 writer
->state
= E_INVALIDARG
;
1535 case BWRITERSPR_INPUT
:
1536 token
|= map_ps_input(writer
, reg
);
1539 /* Can be mapped 1:1 */
1540 case BWRITERSPR_TEMP
:
1541 case BWRITERSPR_CONST
:
1542 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1546 WARN("Invalid register type for ps_1_4 shader\n");
1547 writer
->state
= E_INVALIDARG
;
1551 token
|= d3d9_swizzle(reg
->swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1553 if (reg
->srcmod
== BWRITERSPSM_ABS
|| reg
->srcmod
== BWRITERSPSM_ABSNEG
|| reg
->srcmod
== BWRITERSPSM_NOT
)
1555 WARN("Invalid source modifier %u for ps_1_4\n", reg
->srcmod
);
1556 writer
->state
= E_INVALIDARG
;
1559 token
|= d3d9_srcmod(reg
->srcmod
);
1560 put_u32(buffer
, token
);
1563 static void ps_1_4_dstreg(struct bc_writer
*writer
, const struct shader_reg
*reg
, struct bytecode_buffer
*buffer
,
1564 uint32_t shift
, uint32_t mod
)
1566 uint32_t token
= 1u << 31; /* Bit 31 of registers is 1. */
1570 WARN("Relative addressing not supported for destination registers\n");
1571 writer
->state
= E_INVALIDARG
;
1577 case BWRITERSPR_TEMP
: /* 1:1 mapping */
1578 token
|= d3dsp_register( reg
->type
, reg
->regnum
);
1582 case BWRITERSPR_INPUT
:
1583 token
|= map_ps_input(writer
, reg
);
1587 WARN("Invalid dest register type for 1.x pshader\n");
1588 writer
->state
= E_INVALIDARG
;
1592 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1593 token
|= d3d9_dstmod(mod
);
1595 token
|= d3d9_writemask(reg
->writemask
);
1596 put_u32(buffer
, token
);
1599 static void instr_ps_1_4_mov(struct bc_writer
*writer
, const struct instruction
*instr
,
1600 struct bytecode_buffer
*buffer
)
1602 uint32_t token
= D3DSIO_MOV
& D3DSI_OPCODE_MASK
;
1604 if (instr
->dst
.type
== BWRITERSPR_TEMP
&& instr
->src
[0].type
== BWRITERSPR_INPUT
)
1606 if (instr
->src
[0].regnum
== writer
->t_regnum
[0] || instr
->src
[0].regnum
== writer
->t_regnum
[1]
1607 || instr
->src
[0].regnum
== writer
->t_regnum
[2] || instr
->src
[0].regnum
== writer
->t_regnum
[3]
1608 || instr
->src
[0].regnum
== writer
->t_regnum
[4] || instr
->src
[0].regnum
== writer
->t_regnum
[5])
1610 /* Similar to a regular mov, but a different opcode */
1611 token
= D3DSIO_TEXCOORD
& D3DSI_OPCODE_MASK
;
1613 else if (instr
->src
[0].regnum
== writer
->v_regnum
[0] || instr
->src
[0].regnum
== writer
->v_regnum
[1])
1615 /* Handled by the normal mov below. Just drop out of the if condition */
1619 WARN("Unsupported varying -> temp mov in ps_1_4\n");
1620 writer
->state
= E_INVALIDARG
;
1625 writer
->funcs
->opcode(writer
, instr
, token
, buffer
);
1626 writer
->funcs
->dstreg(writer
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1627 writer
->funcs
->srcreg(writer
, &instr
->src
[0], buffer
);
1630 static void instr_ps_1_4_texld(struct bc_writer
*writer
, const struct instruction
*instr
,
1631 struct bytecode_buffer
*buffer
)
1633 if (instr
->src
[1].type
!= BWRITERSPR_SAMPLER
|| instr
->src
[1].regnum
> 5)
1635 WARN("Unsupported sampler type %u regnum %u.\n",
1636 instr
->src
[1].type
, instr
->src
[1].regnum
);
1637 writer
->state
= E_INVALIDARG
;
1640 else if (instr
->dst
.type
!= BWRITERSPR_TEMP
)
1642 WARN("Can only sample into a temp register\n");
1643 writer
->state
= E_INVALIDARG
;
1647 if (instr
->src
[1].regnum
!= instr
->dst
.regnum
)
1649 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_4.\n",
1650 instr
->src
[1].regnum
, instr
->dst
.regnum
);
1651 writer
->state
= E_INVALIDARG
;
1655 writer
->funcs
->opcode(writer
, instr
, D3DSIO_TEX
& D3DSI_OPCODE_MASK
, buffer
);
1656 writer
->funcs
->dstreg(writer
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1657 writer
->funcs
->srcreg(writer
, &instr
->src
[0], buffer
);
1660 static const struct instr_handler_table ps_1_4_handlers
[] = {
1661 {BWRITERSIO_ADD
, instr_handler
},
1662 {BWRITERSIO_NOP
, instr_handler
},
1663 {BWRITERSIO_MOV
, instr_ps_1_4_mov
},
1664 {BWRITERSIO_SUB
, instr_handler
},
1665 {BWRITERSIO_MAD
, instr_handler
},
1666 {BWRITERSIO_MUL
, instr_handler
},
1667 {BWRITERSIO_DP3
, instr_handler
},
1668 {BWRITERSIO_DP4
, instr_handler
},
1669 {BWRITERSIO_LRP
, instr_handler
},
1671 /* pshader instructions */
1672 {BWRITERSIO_CND
, instr_handler
},
1673 {BWRITERSIO_CMP
, instr_handler
},
1674 {BWRITERSIO_TEXKILL
, instr_handler
},
1675 {BWRITERSIO_TEX
, instr_ps_1_4_texld
},
1676 {BWRITERSIO_TEXDEPTH
, instr_handler
},
1677 {BWRITERSIO_BEM
, instr_handler
},
1679 {BWRITERSIO_PHASE
, instr_handler
},
1680 {BWRITERSIO_END
, NULL
},
1683 static const struct bytecode_backend ps_1_4_backend
= {
1692 static void write_constB(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
1693 write_const(shader
->constB
, shader
->num_cb
, D3DSIO_DEFB
, D3DSPR_CONSTBOOL
, buffer
, len
);
1696 static void write_constI(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
1697 write_const(shader
->constI
, shader
->num_ci
, D3DSIO_DEFI
, D3DSPR_CONSTINT
, buffer
, len
);
1700 static void vs_2_header(struct bc_writer
*This
,
1701 const struct bwriter_shader
*shader
,
1702 struct bytecode_buffer
*buffer
) {
1705 hr
= vs_find_builtin_varyings(This
, shader
);
1711 write_declarations(This
, buffer
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
1712 write_constF(shader
, buffer
, TRUE
);
1713 write_constB(shader
, buffer
, TRUE
);
1714 write_constI(shader
, buffer
, TRUE
);
1717 static void vs_2_srcreg(struct bc_writer
*writer
, const struct shader_reg
*reg
, struct bytecode_buffer
*buffer
)
1719 uint32_t token
= 1u << 31; /* Bit 31 of registers is 1 */
1726 case BWRITERSPR_OUTPUT
:
1727 /* Map the swizzle to a writemask, the format expected by
1729 switch (reg
->swizzle
)
1731 case BWRITERVS_SWIZZLE_X
:
1732 component
= BWRITERSP_WRITEMASK_0
;
1734 case BWRITERVS_SWIZZLE_Y
:
1735 component
= BWRITERSP_WRITEMASK_1
;
1737 case BWRITERVS_SWIZZLE_Z
:
1738 component
= BWRITERSP_WRITEMASK_2
;
1740 case BWRITERVS_SWIZZLE_W
:
1741 component
= BWRITERSP_WRITEMASK_3
;
1746 token
|= map_vs_output(writer
, reg
->regnum
, component
, &has_swizzle
);
1749 case BWRITERSPR_RASTOUT
:
1750 case BWRITERSPR_ATTROUT
:
1751 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1752 * but are unexpected. If we hit this path it might be due to an error.
1754 FIXME("Unexpected register type %u.\n", reg
->type
);
1756 case BWRITERSPR_INPUT
:
1757 case BWRITERSPR_TEMP
:
1758 case BWRITERSPR_CONST
:
1759 case BWRITERSPR_ADDR
:
1760 case BWRITERSPR_CONSTINT
:
1761 case BWRITERSPR_CONSTBOOL
:
1762 case BWRITERSPR_LABEL
:
1763 d3d9reg
= d3d9_register(reg
->type
);
1764 token
|= d3dsp_register(d3d9reg
, reg
->regnum
);
1767 case BWRITERSPR_LOOP
:
1768 if (reg
->regnum
!= 0)
1770 WARN("Only regnum 0 is supported for the loop index register in vs_2_0\n");
1771 writer
->state
= E_INVALIDARG
;
1774 token
|= d3dsp_register(D3DSPR_LOOP
, 0);
1777 case BWRITERSPR_PREDICATE
:
1778 if (writer
->shader
->major_version
!= 2 || writer
->shader
->minor_version
!= 1)
1780 WARN("Predicate register is allowed only in vs_2_x\n");
1781 writer
->state
= E_INVALIDARG
;
1784 if (reg
->regnum
> 0)
1786 WARN("Only predicate register 0 is supported\n");
1787 writer
->state
= E_INVALIDARG
;
1790 token
|= d3dsp_register(D3DSPR_PREDICATE
, 0);
1794 WARN("Invalid register type for 2.0 vshader\n");
1795 writer
->state
= E_INVALIDARG
;
1799 token
|= d3d9_swizzle(reg
->swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1800 token
|= d3d9_srcmod(reg
->srcmod
);
1803 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1805 put_u32(buffer
, token
);
1807 /* vs_2_0 and newer write the register containing the index explicitly in
1808 * the binary code. */
1809 if (token
& D3DVS_ADDRMODE_RELATIVE
)
1810 vs_2_srcreg(writer
, reg
->rel_reg
, buffer
);
1813 static void sm_2_opcode(struct bc_writer
*writer
, const struct instruction
*instr
, uint32_t token
,
1814 struct bytecode_buffer
*buffer
)
1816 unsigned int dst_count
= instr
->has_dst
? 1 : 0;
1818 /* From SM 2 onwards instruction length is encoded in the opcode field. */
1819 token
|= instrlen(instr
, instr
->num_srcs
, dst_count
) << D3DSI_INSTLENGTH_SHIFT
;
1820 if (instr
->comptype
)
1821 token
|= (d3d9_comparetype(instr
->comptype
) << 16) & (0xf << 16);
1822 if (instr
->has_predicate
)
1823 token
|= D3DSHADER_INSTRUCTION_PREDICATED
;
1824 put_u32(buffer
,token
);
1827 static const struct instr_handler_table vs_2_0_handlers
[] = {
1828 {BWRITERSIO_ADD
, instr_handler
},
1829 {BWRITERSIO_NOP
, instr_handler
},
1830 {BWRITERSIO_MOV
, instr_handler
},
1831 {BWRITERSIO_SUB
, instr_handler
},
1832 {BWRITERSIO_MAD
, instr_handler
},
1833 {BWRITERSIO_MUL
, instr_handler
},
1834 {BWRITERSIO_RCP
, instr_handler
},
1835 {BWRITERSIO_RSQ
, instr_handler
},
1836 {BWRITERSIO_DP3
, instr_handler
},
1837 {BWRITERSIO_DP4
, instr_handler
},
1838 {BWRITERSIO_MIN
, instr_handler
},
1839 {BWRITERSIO_MAX
, instr_handler
},
1840 {BWRITERSIO_SLT
, instr_handler
},
1841 {BWRITERSIO_SGE
, instr_handler
},
1842 {BWRITERSIO_ABS
, instr_handler
},
1843 {BWRITERSIO_EXP
, instr_handler
},
1844 {BWRITERSIO_LOG
, instr_handler
},
1845 {BWRITERSIO_EXPP
, instr_handler
},
1846 {BWRITERSIO_LOGP
, instr_handler
},
1847 {BWRITERSIO_DST
, instr_handler
},
1848 {BWRITERSIO_LRP
, instr_handler
},
1849 {BWRITERSIO_FRC
, instr_handler
},
1850 {BWRITERSIO_CRS
, instr_handler
},
1851 {BWRITERSIO_SGN
, instr_handler
},
1852 {BWRITERSIO_NRM
, instr_handler
},
1853 {BWRITERSIO_SINCOS
, instr_handler
},
1854 {BWRITERSIO_M4x4
, instr_handler
},
1855 {BWRITERSIO_M4x3
, instr_handler
},
1856 {BWRITERSIO_M3x4
, instr_handler
},
1857 {BWRITERSIO_M3x3
, instr_handler
},
1858 {BWRITERSIO_M3x2
, instr_handler
},
1859 {BWRITERSIO_LIT
, instr_handler
},
1860 {BWRITERSIO_POW
, instr_handler
},
1861 {BWRITERSIO_MOVA
, instr_handler
},
1863 {BWRITERSIO_CALL
, instr_handler
},
1864 {BWRITERSIO_CALLNZ
, instr_handler
},
1865 {BWRITERSIO_REP
, instr_handler
},
1866 {BWRITERSIO_ENDREP
, instr_handler
},
1867 {BWRITERSIO_IF
, instr_handler
},
1868 {BWRITERSIO_LABEL
, instr_handler
},
1869 {BWRITERSIO_ELSE
, instr_handler
},
1870 {BWRITERSIO_ENDIF
, instr_handler
},
1871 {BWRITERSIO_LOOP
, instr_handler
},
1872 {BWRITERSIO_RET
, instr_handler
},
1873 {BWRITERSIO_ENDLOOP
, instr_handler
},
1875 {BWRITERSIO_END
, NULL
},
1878 static const struct bytecode_backend vs_2_0_backend
= {
1887 static const struct instr_handler_table vs_2_x_handlers
[] = {
1888 {BWRITERSIO_ADD
, instr_handler
},
1889 {BWRITERSIO_NOP
, instr_handler
},
1890 {BWRITERSIO_MOV
, instr_handler
},
1891 {BWRITERSIO_SUB
, instr_handler
},
1892 {BWRITERSIO_MAD
, instr_handler
},
1893 {BWRITERSIO_MUL
, instr_handler
},
1894 {BWRITERSIO_RCP
, instr_handler
},
1895 {BWRITERSIO_RSQ
, instr_handler
},
1896 {BWRITERSIO_DP3
, instr_handler
},
1897 {BWRITERSIO_DP4
, instr_handler
},
1898 {BWRITERSIO_MIN
, instr_handler
},
1899 {BWRITERSIO_MAX
, instr_handler
},
1900 {BWRITERSIO_SLT
, instr_handler
},
1901 {BWRITERSIO_SGE
, instr_handler
},
1902 {BWRITERSIO_ABS
, instr_handler
},
1903 {BWRITERSIO_EXP
, instr_handler
},
1904 {BWRITERSIO_LOG
, instr_handler
},
1905 {BWRITERSIO_EXPP
, instr_handler
},
1906 {BWRITERSIO_LOGP
, instr_handler
},
1907 {BWRITERSIO_DST
, instr_handler
},
1908 {BWRITERSIO_LRP
, instr_handler
},
1909 {BWRITERSIO_FRC
, instr_handler
},
1910 {BWRITERSIO_CRS
, instr_handler
},
1911 {BWRITERSIO_SGN
, instr_handler
},
1912 {BWRITERSIO_NRM
, instr_handler
},
1913 {BWRITERSIO_SINCOS
, instr_handler
},
1914 {BWRITERSIO_M4x4
, instr_handler
},
1915 {BWRITERSIO_M4x3
, instr_handler
},
1916 {BWRITERSIO_M3x4
, instr_handler
},
1917 {BWRITERSIO_M3x3
, instr_handler
},
1918 {BWRITERSIO_M3x2
, instr_handler
},
1919 {BWRITERSIO_LIT
, instr_handler
},
1920 {BWRITERSIO_POW
, instr_handler
},
1921 {BWRITERSIO_MOVA
, instr_handler
},
1923 {BWRITERSIO_CALL
, instr_handler
},
1924 {BWRITERSIO_CALLNZ
, instr_handler
},
1925 {BWRITERSIO_REP
, instr_handler
},
1926 {BWRITERSIO_ENDREP
, instr_handler
},
1927 {BWRITERSIO_IF
, instr_handler
},
1928 {BWRITERSIO_LABEL
, instr_handler
},
1929 {BWRITERSIO_IFC
, instr_handler
},
1930 {BWRITERSIO_ELSE
, instr_handler
},
1931 {BWRITERSIO_ENDIF
, instr_handler
},
1932 {BWRITERSIO_BREAK
, instr_handler
},
1933 {BWRITERSIO_BREAKC
, instr_handler
},
1934 {BWRITERSIO_LOOP
, instr_handler
},
1935 {BWRITERSIO_RET
, instr_handler
},
1936 {BWRITERSIO_ENDLOOP
, instr_handler
},
1938 {BWRITERSIO_SETP
, instr_handler
},
1939 {BWRITERSIO_BREAKP
, instr_handler
},
1941 {BWRITERSIO_END
, NULL
},
1944 static const struct bytecode_backend vs_2_x_backend
= {
1953 static void write_samplers(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
)
1955 const uint32_t reg
= (1u << 31) | d3dsp_register(D3DSPR_SAMPLER
, 0) | D3DSP_WRITEMASK_ALL
;
1956 uint32_t instr_dcl
= D3DSIO_DCL
| (2 << D3DSI_INSTLENGTH_SHIFT
);
1960 for (i
= 0; i
< shader
->num_samplers
; ++i
)
1962 /* Write the DCL instruction */
1963 put_u32(buffer
, instr_dcl
);
1965 /* Already shifted */
1966 token
|= d3d9_sampler(shader
->samplers
[i
].type
) & D3DSP_TEXTURETYPE_MASK
;
1967 put_u32(buffer
, token
);
1968 token
= reg
| (shader
->samplers
[i
].regnum
& D3DSP_REGNUM_MASK
);
1969 token
|= d3d9_dstmod(shader
->samplers
[i
].mod
);
1970 put_u32(buffer
, token
);
1974 static void ps_2_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1975 HRESULT hr
= find_ps_builtin_semantics(This
, shader
, 8);
1981 write_declarations(This
, buffer
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
1982 write_samplers(shader
, buffer
);
1983 write_constF(shader
, buffer
, TRUE
);
1984 write_constB(shader
, buffer
, TRUE
);
1985 write_constI(shader
, buffer
, TRUE
);
1988 static void ps_2_srcreg(struct bc_writer
*writer
, const struct shader_reg
*reg
, struct bytecode_buffer
*buffer
)
1990 uint32_t token
= 1u << 31; /* Bit 31 of registers is 1 */
1995 WARN("Relative addressing not supported in <= ps_3_0\n");
1996 writer
->state
= E_INVALIDARG
;
2002 case BWRITERSPR_INPUT
:
2003 token
|= map_ps_input(writer
, reg
);
2006 /* Can be mapped 1:1 */
2007 case BWRITERSPR_TEMP
:
2008 case BWRITERSPR_CONST
:
2009 case BWRITERSPR_COLOROUT
:
2010 case BWRITERSPR_CONSTBOOL
:
2011 case BWRITERSPR_CONSTINT
:
2012 case BWRITERSPR_SAMPLER
:
2013 case BWRITERSPR_LABEL
:
2014 case BWRITERSPR_DEPTHOUT
:
2015 d3d9reg
= d3d9_register(reg
->type
);
2016 token
|= d3dsp_register(d3d9reg
, reg
->regnum
);
2019 case BWRITERSPR_PREDICATE
:
2020 if (writer
->shader
->minor_version
== 0)
2022 WARN("Predicate register not supported in ps_2_0\n");
2023 writer
->state
= E_INVALIDARG
;
2027 WARN("Predicate register with regnum %u not supported.\n", reg
->regnum
);
2028 writer
->state
= E_INVALIDARG
;
2030 token
|= d3dsp_register(D3DSPR_PREDICATE
, 0);
2034 WARN("Invalid register type for ps_2_0 shader\n");
2035 writer
->state
= E_INVALIDARG
;
2039 token
|= d3d9_swizzle(reg
->swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
2041 token
|= d3d9_srcmod(reg
->srcmod
);
2042 put_u32(buffer
, token
);
2045 static void ps_2_0_dstreg(struct bc_writer
*writer
, const struct shader_reg
*reg
, struct bytecode_buffer
*buffer
,
2046 uint32_t shift
, uint32_t mod
)
2048 uint32_t token
= 1u << 31; /* Bit 31 of registers is 1 */
2053 WARN("Relative addressing not supported for destination registers\n");
2054 writer
->state
= E_INVALIDARG
;
2060 case BWRITERSPR_TEMP
: /* 1:1 mapping */
2061 case BWRITERSPR_COLOROUT
:
2062 case BWRITERSPR_DEPTHOUT
:
2063 d3d9reg
= d3d9_register(reg
->type
);
2064 token
|= d3dsp_register(d3d9reg
, reg
->regnum
);
2067 case BWRITERSPR_PREDICATE
:
2068 if (writer
->shader
->minor_version
== 0)
2070 WARN("Predicate register not supported in ps_2_0\n");
2071 writer
->state
= E_INVALIDARG
;
2073 token
|= d3dsp_register(D3DSPR_PREDICATE
, reg
->regnum
);
2076 /* texkill uses the input register as a destination parameter */
2077 case BWRITERSPR_INPUT
:
2078 token
|= map_ps_input(writer
, reg
);
2082 WARN("Invalid dest register type for 2.x pshader\n");
2083 writer
->state
= E_INVALIDARG
;
2087 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
2088 token
|= d3d9_dstmod(mod
);
2090 token
|= d3d9_writemask(reg
->writemask
);
2091 put_u32(buffer
, token
);
2094 static const struct instr_handler_table ps_2_0_handlers
[] = {
2095 {BWRITERSIO_ADD
, instr_handler
},
2096 {BWRITERSIO_NOP
, instr_handler
},
2097 {BWRITERSIO_MOV
, instr_handler
},
2098 {BWRITERSIO_SUB
, instr_handler
},
2099 {BWRITERSIO_MAD
, instr_handler
},
2100 {BWRITERSIO_MUL
, instr_handler
},
2101 {BWRITERSIO_RCP
, instr_handler
},
2102 {BWRITERSIO_RSQ
, instr_handler
},
2103 {BWRITERSIO_DP3
, instr_handler
},
2104 {BWRITERSIO_DP4
, instr_handler
},
2105 {BWRITERSIO_MIN
, instr_handler
},
2106 {BWRITERSIO_MAX
, instr_handler
},
2107 {BWRITERSIO_ABS
, instr_handler
},
2108 {BWRITERSIO_EXP
, instr_handler
},
2109 {BWRITERSIO_LOG
, instr_handler
},
2110 {BWRITERSIO_EXPP
, instr_handler
},
2111 {BWRITERSIO_LOGP
, instr_handler
},
2112 {BWRITERSIO_LRP
, instr_handler
},
2113 {BWRITERSIO_FRC
, instr_handler
},
2114 {BWRITERSIO_CRS
, instr_handler
},
2115 {BWRITERSIO_NRM
, instr_handler
},
2116 {BWRITERSIO_SINCOS
, instr_handler
},
2117 {BWRITERSIO_M4x4
, instr_handler
},
2118 {BWRITERSIO_M4x3
, instr_handler
},
2119 {BWRITERSIO_M3x4
, instr_handler
},
2120 {BWRITERSIO_M3x3
, instr_handler
},
2121 {BWRITERSIO_M3x2
, instr_handler
},
2122 {BWRITERSIO_POW
, instr_handler
},
2123 {BWRITERSIO_DP2ADD
, instr_handler
},
2124 {BWRITERSIO_CMP
, instr_handler
},
2126 {BWRITERSIO_TEX
, instr_handler
},
2127 {BWRITERSIO_TEXLDP
, instr_handler
},
2128 {BWRITERSIO_TEXLDB
, instr_handler
},
2129 {BWRITERSIO_TEXKILL
, instr_handler
},
2131 {BWRITERSIO_END
, NULL
},
2134 static const struct bytecode_backend ps_2_0_backend
= {
2143 static const struct instr_handler_table ps_2_x_handlers
[] = {
2144 {BWRITERSIO_ADD
, instr_handler
},
2145 {BWRITERSIO_NOP
, instr_handler
},
2146 {BWRITERSIO_MOV
, instr_handler
},
2147 {BWRITERSIO_SUB
, instr_handler
},
2148 {BWRITERSIO_MAD
, instr_handler
},
2149 {BWRITERSIO_MUL
, instr_handler
},
2150 {BWRITERSIO_RCP
, instr_handler
},
2151 {BWRITERSIO_RSQ
, instr_handler
},
2152 {BWRITERSIO_DP3
, instr_handler
},
2153 {BWRITERSIO_DP4
, instr_handler
},
2154 {BWRITERSIO_MIN
, instr_handler
},
2155 {BWRITERSIO_MAX
, instr_handler
},
2156 {BWRITERSIO_ABS
, instr_handler
},
2157 {BWRITERSIO_EXP
, instr_handler
},
2158 {BWRITERSIO_LOG
, instr_handler
},
2159 {BWRITERSIO_EXPP
, instr_handler
},
2160 {BWRITERSIO_LOGP
, instr_handler
},
2161 {BWRITERSIO_LRP
, instr_handler
},
2162 {BWRITERSIO_FRC
, instr_handler
},
2163 {BWRITERSIO_CRS
, instr_handler
},
2164 {BWRITERSIO_NRM
, instr_handler
},
2165 {BWRITERSIO_SINCOS
, instr_handler
},
2166 {BWRITERSIO_M4x4
, instr_handler
},
2167 {BWRITERSIO_M4x3
, instr_handler
},
2168 {BWRITERSIO_M3x4
, instr_handler
},
2169 {BWRITERSIO_M3x3
, instr_handler
},
2170 {BWRITERSIO_M3x2
, instr_handler
},
2171 {BWRITERSIO_POW
, instr_handler
},
2172 {BWRITERSIO_DP2ADD
, instr_handler
},
2173 {BWRITERSIO_CMP
, instr_handler
},
2175 {BWRITERSIO_CALL
, instr_handler
},
2176 {BWRITERSIO_CALLNZ
, instr_handler
},
2177 {BWRITERSIO_REP
, instr_handler
},
2178 {BWRITERSIO_ENDREP
, instr_handler
},
2179 {BWRITERSIO_IF
, instr_handler
},
2180 {BWRITERSIO_LABEL
, instr_handler
},
2181 {BWRITERSIO_IFC
, instr_handler
},
2182 {BWRITERSIO_ELSE
, instr_handler
},
2183 {BWRITERSIO_ENDIF
, instr_handler
},
2184 {BWRITERSIO_BREAK
, instr_handler
},
2185 {BWRITERSIO_BREAKC
, instr_handler
},
2186 {BWRITERSIO_RET
, instr_handler
},
2188 {BWRITERSIO_TEX
, instr_handler
},
2189 {BWRITERSIO_TEXLDP
, instr_handler
},
2190 {BWRITERSIO_TEXLDB
, instr_handler
},
2191 {BWRITERSIO_TEXKILL
, instr_handler
},
2192 {BWRITERSIO_DSX
, instr_handler
},
2193 {BWRITERSIO_DSY
, instr_handler
},
2195 {BWRITERSIO_SETP
, instr_handler
},
2196 {BWRITERSIO_BREAKP
, instr_handler
},
2198 {BWRITERSIO_TEXLDD
, instr_handler
},
2200 {BWRITERSIO_END
, NULL
},
2203 static const struct bytecode_backend ps_2_x_backend
= {
2212 static void sm_3_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
2213 write_declarations(This
, buffer
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
2214 write_declarations(This
, buffer
, shader
->outputs
, shader
->num_outputs
, BWRITERSPR_OUTPUT
);
2215 write_constF(shader
, buffer
, TRUE
);
2216 write_constB(shader
, buffer
, TRUE
);
2217 write_constI(shader
, buffer
, TRUE
);
2218 write_samplers(shader
, buffer
);
2221 static void sm_3_srcreg(struct bc_writer
*writer
, const struct shader_reg
*reg
, struct bytecode_buffer
*buffer
)
2223 const struct bwriter_shader
*shader
= writer
->shader
;
2224 uint32_t token
= 1u << 31; /* Bit 31 of registers is 1 */
2227 d3d9reg
= d3d9_register(reg
->type
);
2228 token
|= d3dsp_register(d3d9reg
, reg
->regnum
);
2229 token
|= d3d9_swizzle(reg
->swizzle
) & D3DVS_SWIZZLE_MASK
;
2230 token
|= d3d9_srcmod(reg
->srcmod
);
2234 if (reg
->type
== BWRITERSPR_CONST
&& shader
->type
== ST_PIXEL
)
2236 WARN("c%u[...] is unsupported in ps_3_0.\n", reg
->regnum
);
2237 writer
->state
= E_INVALIDARG
;
2241 if (((reg
->rel_reg
->type
== BWRITERSPR_ADDR
&& shader
->type
== ST_VERTEX
)
2242 || reg
->rel_reg
->type
== BWRITERSPR_LOOP
) && reg
->rel_reg
->regnum
== 0)
2244 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
2248 WARN("Unsupported relative addressing register\n");
2249 writer
->state
= E_INVALIDARG
;
2254 put_u32(buffer
, token
);
2256 /* vs_2_0 and newer write the register containing the index explicitly in
2257 * the binary code. */
2258 if (token
& D3DVS_ADDRMODE_RELATIVE
)
2259 sm_3_srcreg(writer
, reg
->rel_reg
, buffer
);
2262 static void sm_3_dstreg(struct bc_writer
*writer
, const struct shader_reg
*reg
, struct bytecode_buffer
*buffer
,
2263 uint32_t shift
, uint32_t mod
)
2265 const struct bwriter_shader
*shader
= writer
->shader
;
2266 uint32_t token
= 1u << 31; /* Bit 31 of registers is 1 */
2271 if (shader
->type
== ST_VERTEX
&& reg
->type
== BWRITERSPR_OUTPUT
)
2273 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
2277 WARN("Relative addressing not supported for this shader type or register type\n");
2278 writer
->state
= E_INVALIDARG
;
2283 d3d9reg
= d3d9_register(reg
->type
);
2284 token
|= d3dsp_register(d3d9reg
, reg
->regnum
);
2285 token
|= d3d9_dstmod(mod
);
2286 token
|= d3d9_writemask(reg
->writemask
);
2287 put_u32(buffer
, token
);
2289 /* vs_2_0 and newer write the register containing the index explicitly in
2290 * the binary code. */
2291 if (token
& D3DVS_ADDRMODE_RELATIVE
)
2292 sm_3_srcreg(writer
, reg
->rel_reg
, buffer
);
2295 static const struct instr_handler_table vs_3_handlers
[] = {
2296 {BWRITERSIO_ADD
, instr_handler
},
2297 {BWRITERSIO_NOP
, instr_handler
},
2298 {BWRITERSIO_MOV
, instr_handler
},
2299 {BWRITERSIO_SUB
, instr_handler
},
2300 {BWRITERSIO_MAD
, instr_handler
},
2301 {BWRITERSIO_MUL
, instr_handler
},
2302 {BWRITERSIO_RCP
, instr_handler
},
2303 {BWRITERSIO_RSQ
, instr_handler
},
2304 {BWRITERSIO_DP3
, instr_handler
},
2305 {BWRITERSIO_DP4
, instr_handler
},
2306 {BWRITERSIO_MIN
, instr_handler
},
2307 {BWRITERSIO_MAX
, instr_handler
},
2308 {BWRITERSIO_SLT
, instr_handler
},
2309 {BWRITERSIO_SGE
, instr_handler
},
2310 {BWRITERSIO_ABS
, instr_handler
},
2311 {BWRITERSIO_EXP
, instr_handler
},
2312 {BWRITERSIO_LOG
, instr_handler
},
2313 {BWRITERSIO_EXPP
, instr_handler
},
2314 {BWRITERSIO_LOGP
, instr_handler
},
2315 {BWRITERSIO_DST
, instr_handler
},
2316 {BWRITERSIO_LRP
, instr_handler
},
2317 {BWRITERSIO_FRC
, instr_handler
},
2318 {BWRITERSIO_CRS
, instr_handler
},
2319 {BWRITERSIO_SGN
, instr_handler
},
2320 {BWRITERSIO_NRM
, instr_handler
},
2321 {BWRITERSIO_SINCOS
, instr_handler
},
2322 {BWRITERSIO_M4x4
, instr_handler
},
2323 {BWRITERSIO_M4x3
, instr_handler
},
2324 {BWRITERSIO_M3x4
, instr_handler
},
2325 {BWRITERSIO_M3x3
, instr_handler
},
2326 {BWRITERSIO_M3x2
, instr_handler
},
2327 {BWRITERSIO_LIT
, instr_handler
},
2328 {BWRITERSIO_POW
, instr_handler
},
2329 {BWRITERSIO_MOVA
, instr_handler
},
2331 {BWRITERSIO_CALL
, instr_handler
},
2332 {BWRITERSIO_CALLNZ
, instr_handler
},
2333 {BWRITERSIO_REP
, instr_handler
},
2334 {BWRITERSIO_ENDREP
, instr_handler
},
2335 {BWRITERSIO_IF
, instr_handler
},
2336 {BWRITERSIO_LABEL
, instr_handler
},
2337 {BWRITERSIO_IFC
, instr_handler
},
2338 {BWRITERSIO_ELSE
, instr_handler
},
2339 {BWRITERSIO_ENDIF
, instr_handler
},
2340 {BWRITERSIO_BREAK
, instr_handler
},
2341 {BWRITERSIO_BREAKC
, instr_handler
},
2342 {BWRITERSIO_LOOP
, instr_handler
},
2343 {BWRITERSIO_RET
, instr_handler
},
2344 {BWRITERSIO_ENDLOOP
, instr_handler
},
2346 {BWRITERSIO_SETP
, instr_handler
},
2347 {BWRITERSIO_BREAKP
, instr_handler
},
2348 {BWRITERSIO_TEXLDL
, instr_handler
},
2350 {BWRITERSIO_END
, NULL
},
2353 static const struct bytecode_backend vs_3_backend
= {
2362 static const struct instr_handler_table ps_3_handlers
[] = {
2363 {BWRITERSIO_ADD
, instr_handler
},
2364 {BWRITERSIO_NOP
, instr_handler
},
2365 {BWRITERSIO_MOV
, instr_handler
},
2366 {BWRITERSIO_SUB
, instr_handler
},
2367 {BWRITERSIO_MAD
, instr_handler
},
2368 {BWRITERSIO_MUL
, instr_handler
},
2369 {BWRITERSIO_RCP
, instr_handler
},
2370 {BWRITERSIO_RSQ
, instr_handler
},
2371 {BWRITERSIO_DP3
, instr_handler
},
2372 {BWRITERSIO_DP4
, instr_handler
},
2373 {BWRITERSIO_MIN
, instr_handler
},
2374 {BWRITERSIO_MAX
, instr_handler
},
2375 {BWRITERSIO_ABS
, instr_handler
},
2376 {BWRITERSIO_EXP
, instr_handler
},
2377 {BWRITERSIO_LOG
, instr_handler
},
2378 {BWRITERSIO_EXPP
, instr_handler
},
2379 {BWRITERSIO_LOGP
, instr_handler
},
2380 {BWRITERSIO_LRP
, instr_handler
},
2381 {BWRITERSIO_FRC
, instr_handler
},
2382 {BWRITERSIO_CRS
, instr_handler
},
2383 {BWRITERSIO_NRM
, instr_handler
},
2384 {BWRITERSIO_SINCOS
, instr_handler
},
2385 {BWRITERSIO_M4x4
, instr_handler
},
2386 {BWRITERSIO_M4x3
, instr_handler
},
2387 {BWRITERSIO_M3x4
, instr_handler
},
2388 {BWRITERSIO_M3x3
, instr_handler
},
2389 {BWRITERSIO_M3x2
, instr_handler
},
2390 {BWRITERSIO_POW
, instr_handler
},
2391 {BWRITERSIO_DP2ADD
, instr_handler
},
2392 {BWRITERSIO_CMP
, instr_handler
},
2394 {BWRITERSIO_CALL
, instr_handler
},
2395 {BWRITERSIO_CALLNZ
, instr_handler
},
2396 {BWRITERSIO_REP
, instr_handler
},
2397 {BWRITERSIO_ENDREP
, instr_handler
},
2398 {BWRITERSIO_IF
, instr_handler
},
2399 {BWRITERSIO_LABEL
, instr_handler
},
2400 {BWRITERSIO_IFC
, instr_handler
},
2401 {BWRITERSIO_ELSE
, instr_handler
},
2402 {BWRITERSIO_ENDIF
, instr_handler
},
2403 {BWRITERSIO_BREAK
, instr_handler
},
2404 {BWRITERSIO_BREAKC
, instr_handler
},
2405 {BWRITERSIO_LOOP
, instr_handler
},
2406 {BWRITERSIO_RET
, instr_handler
},
2407 {BWRITERSIO_ENDLOOP
, instr_handler
},
2409 {BWRITERSIO_SETP
, instr_handler
},
2410 {BWRITERSIO_BREAKP
, instr_handler
},
2411 {BWRITERSIO_TEXLDL
, instr_handler
},
2413 {BWRITERSIO_TEX
, instr_handler
},
2414 {BWRITERSIO_TEXLDP
, instr_handler
},
2415 {BWRITERSIO_TEXLDB
, instr_handler
},
2416 {BWRITERSIO_TEXKILL
, instr_handler
},
2417 {BWRITERSIO_DSX
, instr_handler
},
2418 {BWRITERSIO_DSY
, instr_handler
},
2419 {BWRITERSIO_TEXLDD
, instr_handler
},
2421 {BWRITERSIO_END
, NULL
},
2424 static const struct bytecode_backend ps_3_backend
= {
2435 enum shader_type type
;
2436 unsigned char major
, minor
;
2437 const struct bytecode_backend
*backend
;
2441 {ST_VERTEX
, 1, 0, &vs_1_x_backend
},
2442 {ST_VERTEX
, 1, 1, &vs_1_x_backend
},
2443 {ST_VERTEX
, 2, 0, &vs_2_0_backend
},
2444 {ST_VERTEX
, 2, 1, &vs_2_x_backend
},
2445 {ST_VERTEX
, 3, 0, &vs_3_backend
},
2447 {ST_PIXEL
, 1, 0, &ps_1_0123_backend
},
2448 {ST_PIXEL
, 1, 1, &ps_1_0123_backend
},
2449 {ST_PIXEL
, 1, 2, &ps_1_0123_backend
},
2450 {ST_PIXEL
, 1, 3, &ps_1_0123_backend
},
2451 {ST_PIXEL
, 1, 4, &ps_1_4_backend
},
2452 {ST_PIXEL
, 2, 0, &ps_2_0_backend
},
2453 {ST_PIXEL
, 2, 1, &ps_2_x_backend
},
2454 {ST_PIXEL
, 3, 0, &ps_3_backend
},
2457 static HRESULT
call_instr_handler(struct bc_writer
*writer
, const struct instruction
*instr
,
2458 struct bytecode_buffer
*buffer
)
2462 for (i
= 0; writer
->funcs
->instructions
[i
].opcode
!= BWRITERSIO_END
; ++i
)
2464 if (instr
->opcode
== writer
->funcs
->instructions
[i
].opcode
)
2466 if (!writer
->funcs
->instructions
[i
].func
)
2468 WARN("Opcode %u not supported by this profile.\n", instr
->opcode
);
2469 return E_INVALIDARG
;
2471 writer
->funcs
->instructions
[i
].func(writer
, instr
, buffer
);
2476 FIXME("Unhandled instruction %u - %s.\n", instr
->opcode
, debug_print_opcode(instr
->opcode
));
2477 return E_INVALIDARG
;
2480 HRESULT
shader_write_bytecode(const struct bwriter_shader
*shader
, uint32_t **result
, uint32_t *size
)
2482 struct bc_writer
*writer
;
2483 struct bytecode_buffer
*buffer
= NULL
;
2488 ERR("NULL shader structure, aborting\n");
2492 if (!(writer
= d3dcompiler_alloc(sizeof(*writer
))))
2493 return E_OUTOFMEMORY
;
2495 for (i
= 0; i
< ARRAY_SIZE(shader_backends
); ++i
)
2497 if (shader
->type
== shader_backends
[i
].type
2498 && shader
->major_version
== shader_backends
[i
].major
2499 && shader
->minor_version
== shader_backends
[i
].minor
)
2501 writer
->funcs
= shader_backends
[i
].backend
;
2508 FIXME("Unsupported shader type %#x, version %u.%u.\n",
2509 shader
->type
, shader
->major_version
, shader
->minor_version
);
2510 d3dcompiler_free(writer
);
2514 writer
->shader
= shader
;
2517 buffer
= allocate_buffer();
2519 WARN("Failed to allocate a buffer for the shader bytecode\n");
2524 /* Write shader type and version */
2525 put_u32(buffer
, sm1_version(shader
));
2527 writer
->funcs
->header(writer
, shader
, buffer
);
2528 if(FAILED(writer
->state
)) {
2533 for(i
= 0; i
< shader
->num_instrs
; i
++) {
2534 hr
= call_instr_handler(writer
, shader
->instr
[i
], buffer
);
2540 if(FAILED(writer
->state
)) {
2545 writer
->funcs
->end(writer
, shader
, buffer
);
2547 if(FAILED(buffer
->state
)) {
2552 *size
= buffer
->size
* sizeof(uint32_t);
2553 *result
= buffer
->data
;
2554 buffer
->data
= NULL
;
2559 d3dcompiler_free(buffer
->data
);
2560 d3dcompiler_free(buffer
);
2562 d3dcompiler_free(writer
);
2566 void SlDeleteShader(struct bwriter_shader
*shader
) {
2569 TRACE("Deleting shader %p\n", shader
);
2571 for(i
= 0; i
< shader
->num_cf
; i
++) {
2572 d3dcompiler_free(shader
->constF
[i
]);
2574 d3dcompiler_free(shader
->constF
);
2575 for(i
= 0; i
< shader
->num_ci
; i
++) {
2576 d3dcompiler_free(shader
->constI
[i
]);
2578 d3dcompiler_free(shader
->constI
);
2579 for(i
= 0; i
< shader
->num_cb
; i
++) {
2580 d3dcompiler_free(shader
->constB
[i
]);
2582 d3dcompiler_free(shader
->constB
);
2584 d3dcompiler_free(shader
->inputs
);
2585 d3dcompiler_free(shader
->outputs
);
2586 d3dcompiler_free(shader
->samplers
);
2588 for(i
= 0; i
< shader
->num_instrs
; i
++) {
2589 for(j
= 0; j
< shader
->instr
[i
]->num_srcs
; j
++) {
2590 d3dcompiler_free(shader
->instr
[i
]->src
[j
].rel_reg
);
2592 d3dcompiler_free(shader
->instr
[i
]->src
);
2593 d3dcompiler_free(shader
->instr
[i
]->dst
.rel_reg
);
2594 d3dcompiler_free(shader
->instr
[i
]);
2596 d3dcompiler_free(shader
->instr
);
2598 d3dcompiler_free(shader
);