2 * Direct3D bytecode output functions
4 * Copyright 2008 Stefan Dösinger
5 * Copyright 2009 Matteo Bruni
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
25 #include "wine/debug.h"
27 #include "d3dx9_36_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(asmshader
);
31 /****************************************************************
32 * General assembler shader construction helper routines follow *
33 ****************************************************************/
34 /* struct instruction *alloc_instr
36 * Allocates a new instruction structure with srcs registers
39 * srcs: Number of source registers to allocate
42 * A pointer to the allocated instruction structure
43 * NULL in case of an allocation failure
45 struct instruction
*alloc_instr(unsigned int srcs
) {
46 struct instruction
*ret
= asm_alloc(sizeof(*ret
));
48 ERR("Failed to allocate memory for an instruction structure\n");
53 ret
->src
= asm_alloc(srcs
* sizeof(*ret
->src
));
55 ERR("Failed to allocate memory for instruction registers\n");
64 /* void add_instruction
66 * Adds a new instruction to the shader's instructions array and grows the instruction array
69 * The function does NOT copy the instruction structure. Make sure not to release the
70 * instruction or any of its substructures like registers.
73 * shader: Shader to add the instruction to
74 * instr: Instruction to add to the shader
76 BOOL
add_instruction(struct bwriter_shader
*shader
, struct instruction
*instr
) {
77 struct instruction
**new_instructions
;
79 if(!shader
) return FALSE
;
81 if(shader
->instr_alloc_size
== 0) {
82 shader
->instr
= asm_alloc(sizeof(*shader
->instr
) * INSTRARRAY_INITIAL_SIZE
);
84 ERR("Failed to allocate the shader instruction array\n");
87 shader
->instr_alloc_size
= INSTRARRAY_INITIAL_SIZE
;
88 } else if(shader
->instr_alloc_size
== shader
->num_instrs
) {
89 new_instructions
= asm_realloc(shader
->instr
,
90 sizeof(*shader
->instr
) * (shader
->instr_alloc_size
) * 2);
91 if(!new_instructions
) {
92 ERR("Failed to grow the shader instruction array\n");
95 shader
->instr
= new_instructions
;
96 shader
->instr_alloc_size
= shader
->instr_alloc_size
* 2;
97 } else if(shader
->num_instrs
> shader
->instr_alloc_size
) {
98 ERR("More instructions than allocated. This should not happen\n");
102 shader
->instr
[shader
->num_instrs
] = instr
;
103 shader
->num_instrs
++;
107 BOOL
add_constF(struct bwriter_shader
*shader
, DWORD reg
, float x
, float y
, float z
, float w
) {
108 struct constant
*newconst
;
111 struct constant
**newarray
;
112 newarray
= asm_realloc(shader
->constF
,
113 sizeof(*shader
->constF
) * (shader
->num_cf
+ 1));
115 ERR("Failed to grow the constants array\n");
118 shader
->constF
= newarray
;
120 shader
->constF
= asm_alloc(sizeof(*shader
->constF
));
121 if(!shader
->constF
) {
122 ERR("Failed to allocate the constants array\n");
127 newconst
= asm_alloc(sizeof(*newconst
));
129 ERR("Failed to allocate a new constant\n");
132 newconst
->regnum
= reg
;
133 newconst
->value
[0].f
= x
;
134 newconst
->value
[1].f
= y
;
135 newconst
->value
[2].f
= z
;
136 newconst
->value
[3].f
= w
;
137 shader
->constF
[shader
->num_cf
] = newconst
;
143 BOOL
add_constI(struct bwriter_shader
*shader
, DWORD reg
, INT x
, INT y
, INT z
, INT w
) {
144 struct constant
*newconst
;
147 struct constant
**newarray
;
148 newarray
= asm_realloc(shader
->constI
,
149 sizeof(*shader
->constI
) * (shader
->num_ci
+ 1));
151 ERR("Failed to grow the constants array\n");
154 shader
->constI
= newarray
;
156 shader
->constI
= asm_alloc(sizeof(*shader
->constI
));
157 if(!shader
->constI
) {
158 ERR("Failed to allocate the constants array\n");
163 newconst
= asm_alloc(sizeof(*newconst
));
165 ERR("Failed to allocate a new constant\n");
168 newconst
->regnum
= reg
;
169 newconst
->value
[0].i
= x
;
170 newconst
->value
[1].i
= y
;
171 newconst
->value
[2].i
= z
;
172 newconst
->value
[3].i
= w
;
173 shader
->constI
[shader
->num_ci
] = newconst
;
179 BOOL
add_constB(struct bwriter_shader
*shader
, DWORD reg
, BOOL x
) {
180 struct constant
*newconst
;
183 struct constant
**newarray
;
184 newarray
= asm_realloc(shader
->constB
,
185 sizeof(*shader
->constB
) * (shader
->num_cb
+ 1));
187 ERR("Failed to grow the constants array\n");
190 shader
->constB
= newarray
;
192 shader
->constB
= asm_alloc(sizeof(*shader
->constB
));
193 if(!shader
->constB
) {
194 ERR("Failed to allocate the constants array\n");
199 newconst
= asm_alloc(sizeof(*newconst
));
201 ERR("Failed to allocate a new constant\n");
204 newconst
->regnum
= reg
;
205 newconst
->value
[0].b
= x
;
206 shader
->constB
[shader
->num_cb
] = newconst
;
212 BOOL
record_declaration(struct bwriter_shader
*shader
, DWORD usage
, DWORD usage_idx
, DWORD mod
, BOOL output
, DWORD regnum
, DWORD writemask
) {
214 struct declaration
**decl
;
217 if(!shader
) return FALSE
;
220 num
= &shader
->num_outputs
;
221 decl
= &shader
->outputs
;
223 num
= &shader
->num_inputs
;
224 decl
= &shader
->inputs
;
228 *decl
= asm_alloc(sizeof(**decl
));
230 ERR("Error allocating declarations array\n");
234 struct declaration
*newdecl
;
235 for(i
= 0; i
< *num
; i
++) {
236 if((*decl
)[i
].regnum
== regnum
&& ((*decl
)[i
].writemask
& writemask
)) {
237 WARN("Declaration of register %u already exists, writemask match 0x%x\n",
238 regnum
, (*decl
)[i
].writemask
& writemask
);
242 newdecl
= asm_realloc(*decl
,
243 sizeof(**decl
) * ((*num
) + 1));
245 ERR("Error reallocating declarations array\n");
250 (*decl
)[*num
].usage
= usage
;
251 (*decl
)[*num
].usage_idx
= usage_idx
;
252 (*decl
)[*num
].regnum
= regnum
;
253 (*decl
)[*num
].mod
= mod
;
254 (*decl
)[*num
].writemask
= writemask
;
260 BOOL
record_sampler(struct bwriter_shader
*shader
, DWORD samptype
, DWORD mod
, DWORD regnum
) {
263 if(!shader
) return FALSE
;
265 if(shader
->num_samplers
== 0) {
266 shader
->samplers
= asm_alloc(sizeof(*shader
->samplers
));
267 if(!shader
->samplers
) {
268 ERR("Error allocating samplers array\n");
272 struct samplerdecl
*newarray
;
274 for(i
= 0; i
< shader
->num_samplers
; i
++) {
275 if(shader
->samplers
[i
].regnum
== regnum
) {
276 WARN("Sampler %u already declared\n", regnum
);
277 /* This is not an error as far as the assembler is concerned.
278 * Direct3D might refuse to load the compiled shader though
283 newarray
= asm_realloc(shader
->samplers
,
284 sizeof(*shader
->samplers
) * (shader
->num_samplers
+ 1));
286 ERR("Error reallocating samplers array\n");
289 shader
->samplers
= newarray
;
292 shader
->samplers
[shader
->num_samplers
].type
= samptype
;
293 shader
->samplers
[shader
->num_samplers
].mod
= mod
;
294 shader
->samplers
[shader
->num_samplers
].regnum
= regnum
;
295 shader
->num_samplers
++;
300 /* shader bytecode buffer manipulation functions.
301 * allocate_buffer creates a new buffer structure, put_dword adds a new
302 * DWORD to the buffer. In the rare case of a memory allocation failure
303 * when trying to grow the buffer a flag is set in the buffer to mark it
304 * invalid. This avoids return value checking and passing in many places
306 static struct bytecode_buffer
*allocate_buffer(void) {
307 struct bytecode_buffer
*ret
;
309 ret
= asm_alloc(sizeof(*ret
));
310 if(!ret
) return NULL
;
312 ret
->alloc_size
= BYTECODEBUFFER_INITIAL_SIZE
;
313 ret
->data
= asm_alloc(sizeof(DWORD
) * ret
->alloc_size
);
322 static void put_dword(struct bytecode_buffer
*buffer
, DWORD value
) {
323 if(FAILED(buffer
->state
)) return;
325 if(buffer
->alloc_size
== buffer
->size
) {
327 buffer
->alloc_size
*= 2;
328 newarray
= asm_realloc(buffer
->data
,
329 sizeof(DWORD
) * buffer
->alloc_size
);
331 ERR("Failed to grow the buffer data memory\n");
332 buffer
->state
= E_OUTOFMEMORY
;
335 buffer
->data
= newarray
;
337 buffer
->data
[buffer
->size
++] = value
;
340 /******************************************************
341 * Implementation of the writer functions starts here *
342 ******************************************************/
343 static void write_declarations(struct bytecode_buffer
*buffer
, BOOL len
,
344 const struct declaration
*decls
, unsigned int num
, DWORD type
) {
346 DWORD instr_dcl
= D3DSIO_DCL
;
350 instr_dcl
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
353 for(i
= 0; i
< num
; i
++) {
354 /* Write the DCL instruction */
355 put_dword(buffer
, instr_dcl
);
357 /* Write the usage and index */
358 token
= (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
359 token
|= (decls
[i
].usage
<< D3DSP_DCL_USAGE_SHIFT
) & D3DSP_DCL_USAGE_MASK
;
360 token
|= (decls
[i
].usage_idx
<< D3DSP_DCL_USAGEINDEX_SHIFT
) & D3DSP_DCL_USAGEINDEX_MASK
;
361 put_dword(buffer
, token
);
363 /* Write the dest register */
364 token
= (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
365 token
|= (type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
366 token
|= (d3d9_writemask(decls
[i
].writemask
)) & D3DSP_WRITEMASK_ALL
;
367 token
|= decls
[i
].regnum
& D3DSP_REGNUM_MASK
;
368 token
|= d3d9_dstmod(decls
[i
].mod
);
369 put_dword(buffer
, token
);
373 static void write_const(struct constant
**consts
, int num
, DWORD opcode
, DWORD reg_type
, struct bytecode_buffer
*buffer
, BOOL len
) {
375 DWORD instr_def
= opcode
;
376 const DWORD reg
= (1<<31) |
377 ((reg_type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
) |
378 ((reg_type
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
) |
382 if(opcode
== D3DSIO_DEFB
)
383 instr_def
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
385 instr_def
|= 5 << D3DSI_INSTLENGTH_SHIFT
;
388 for(i
= 0; i
< num
; i
++) {
389 /* Write the DEF instruction */
390 put_dword(buffer
, instr_def
);
392 put_dword(buffer
, reg
| (consts
[i
]->regnum
& D3DSP_REGNUM_MASK
));
393 put_dword(buffer
, consts
[i
]->value
[0].d
);
394 if(opcode
!= D3DSIO_DEFB
) {
395 put_dword(buffer
, consts
[i
]->value
[1].d
);
396 put_dword(buffer
, consts
[i
]->value
[2].d
);
397 put_dword(buffer
, consts
[i
]->value
[3].d
);
402 static void write_constF(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
403 write_const(shader
->constF
, shader
->num_cf
, D3DSIO_DEF
, D3DSPR_CONST
, buffer
, len
);
406 static HRESULT
vs_find_builtin_varyings(struct bc_writer
*This
, const struct bwriter_shader
*shader
) {
408 DWORD usage
, usage_idx
, writemask
, regnum
;
410 for(i
= 0; i
< shader
->num_outputs
; i
++) {
411 usage
= shader
->outputs
[i
].usage
;
412 usage_idx
= shader
->outputs
[i
].usage_idx
;
413 writemask
= shader
->outputs
[i
].writemask
;
414 regnum
= shader
->outputs
[i
].regnum
;
417 case BWRITERDECLUSAGE_POSITION
:
418 case BWRITERDECLUSAGE_POSITIONT
:
420 WARN("dcl_position%u not supported in sm 1/2 shaders\n", usage_idx
);
423 TRACE("o%u is oPos\n", regnum
);
424 This
->oPos_regnum
= regnum
;
427 case BWRITERDECLUSAGE_COLOR
:
429 WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx
);
432 if(writemask
!= BWRITERSP_WRITEMASK_ALL
) {
433 WARN("Only WRITEMASK_ALL is supported on color in sm 1/2\n");
436 TRACE("o%u is oD%u\n", regnum
, usage_idx
);
437 This
->oD_regnum
[usage_idx
] = regnum
;
440 case BWRITERDECLUSAGE_TEXCOORD
:
442 WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx
);
445 if(writemask
!= (BWRITERSP_WRITEMASK_0
) &&
446 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
) &&
447 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
| BWRITERSP_WRITEMASK_2
) &&
448 writemask
!= (BWRITERSP_WRITEMASK_ALL
)) {
449 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
452 TRACE("o%u is oT%u\n", regnum
, usage_idx
);
453 This
->oT_regnum
[usage_idx
] = regnum
;
456 case BWRITERDECLUSAGE_PSIZE
:
458 WARN("dcl_psize%u not supported in sm 1/2 shaders\n", usage_idx
);
461 TRACE("o%u writemask 0x%08x is oPts\n", regnum
, writemask
);
462 This
->oPts_regnum
= regnum
;
463 This
->oPts_mask
= writemask
;
466 case BWRITERDECLUSAGE_FOG
:
468 WARN("dcl_fog%u not supported in sm 1 shaders\n", usage_idx
);
471 if(writemask
!= BWRITERSP_WRITEMASK_0
&& writemask
!= BWRITERSP_WRITEMASK_1
&&
472 writemask
!= BWRITERSP_WRITEMASK_2
&& writemask
!= BWRITERSP_WRITEMASK_3
) {
473 WARN("Unsupported fog writemask\n");
476 TRACE("o%u writemask 0x%08x is oFog\n", regnum
, writemask
);
477 This
->oFog_regnum
= regnum
;
478 This
->oFog_mask
= writemask
;
482 WARN("Varying type %u is not supported in shader model 1.x\n", usage
);
490 static void vs_1_x_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
493 if(shader
->num_ci
|| shader
->num_cb
) {
494 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
495 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
496 This
->state
= E_INVALIDARG
;
500 hr
= vs_find_builtin_varyings(This
, shader
);
506 /* Declare the shader type and version */
507 put_dword(buffer
, This
->version
);
509 write_declarations(buffer
, FALSE
, shader
->inputs
, shader
->num_inputs
, D3DSPR_INPUT
);
510 write_constF(shader
, buffer
, FALSE
);
514 static HRESULT
find_ps_builtin_semantics(struct bc_writer
*This
,
515 const struct bwriter_shader
*shader
,
518 DWORD usage
, usage_idx
, writemask
, regnum
;
520 This
->v_regnum
[0] = -1; This
->v_regnum
[1] = -1;
521 for(i
= 0; i
< 8; i
++) This
->t_regnum
[i
] = -1;
523 for(i
= 0; i
< shader
->num_inputs
; i
++) {
524 usage
= shader
->inputs
[i
].usage
;
525 usage_idx
= shader
->inputs
[i
].usage_idx
;
526 writemask
= shader
->inputs
[i
].writemask
;
527 regnum
= shader
->inputs
[i
].regnum
;
530 case BWRITERDECLUSAGE_COLOR
:
532 WARN("dcl_color%u not supported in sm 1 shaders\n", usage_idx
);
535 if(writemask
!= BWRITERSP_WRITEMASK_ALL
) {
536 WARN("Only WRITEMASK_ALL is supported on color in sm 1\n");
539 TRACE("v%u is v%u\n", regnum
, usage_idx
);
540 This
->v_regnum
[usage_idx
] = regnum
;
543 case BWRITERDECLUSAGE_TEXCOORD
:
544 if(usage_idx
> texcoords
) {
545 WARN("dcl_texcoord%u not supported in this shader version\n", usage_idx
);
548 if(writemask
!= (BWRITERSP_WRITEMASK_0
) &&
549 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
) &&
550 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
| BWRITERSP_WRITEMASK_2
) &&
551 writemask
!= (BWRITERSP_WRITEMASK_ALL
)) {
552 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
554 writemask
= BWRITERSP_WRITEMASK_ALL
;
556 TRACE("v%u is t%u\n", regnum
, usage_idx
);
557 This
->t_regnum
[usage_idx
] = regnum
;
561 WARN("Varying type %u is not supported in shader model 1.x\n", usage
);
569 static void end(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
570 put_dword(buffer
, D3DSIO_END
);
573 static DWORD
map_vs_output(struct bc_writer
*This
, DWORD regnum
, DWORD mask
, DWORD
*has_components
) {
577 *has_components
= TRUE
;
578 if(regnum
== This
->oPos_regnum
) {
579 token
|= (D3DSPR_RASTOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
580 token
|= D3DSRO_POSITION
& D3DSP_REGNUM_MASK
; /* No shift */
583 if(regnum
== This
->oFog_regnum
&& mask
== This
->oFog_mask
) {
584 token
|= (D3DSPR_RASTOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
585 token
|= D3DSRO_FOG
& D3DSP_REGNUM_MASK
; /* No shift */
586 token
|= D3DSP_WRITEMASK_ALL
;
587 *has_components
= FALSE
;
590 if(regnum
== This
->oPts_regnum
&& mask
== This
->oPts_mask
) {
591 token
|= (D3DSPR_RASTOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
592 token
|= D3DSRO_POINT_SIZE
& D3DSP_REGNUM_MASK
; /* No shift */
593 token
|= D3DSP_WRITEMASK_ALL
;
594 *has_components
= FALSE
;
597 for(i
= 0; i
< 2; i
++) {
598 if(regnum
== This
->oD_regnum
[i
]) {
599 token
|= (D3DSPR_ATTROUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
600 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
604 for(i
= 0; i
< 8; i
++) {
605 if(regnum
== This
->oT_regnum
[i
]) {
606 token
|= (D3DSPR_TEXCRDOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
607 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
612 /* The varying must be undeclared - if an unsupported varying was declared,
613 * the vs_find_builtin_varyings function would have caught it and this code
615 WARN("Undeclared varying %u\n", regnum
);
616 This
->state
= E_INVALIDARG
;
620 static void vs_12_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
621 struct bytecode_buffer
*buffer
,
622 DWORD shift
, DWORD mod
) {
623 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
627 WARN("Relative addressing not supported for destination registers\n");
628 This
->state
= E_INVALIDARG
;
633 case BWRITERSPR_OUTPUT
:
634 token
|= map_vs_output(This
, reg
->regnum
, reg
->writemask
, &has_wmask
);
637 case BWRITERSPR_RASTOUT
:
638 case BWRITERSPR_ATTROUT
:
639 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
640 * but are unexpected. If we hit this path it might be due to an error.
642 FIXME("Unexpected register type %u\n", reg
->type
);
644 case BWRITERSPR_INPUT
:
645 case BWRITERSPR_TEMP
:
646 case BWRITERSPR_CONST
:
647 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
648 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
652 case BWRITERSPR_ADDR
:
653 if(reg
->regnum
!= 0) {
654 WARN("Only a0 exists\n");
655 This
->state
= E_INVALIDARG
;
658 token
|= (D3DSPR_ADDR
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
659 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
663 case BWRITERSPR_PREDICATE
:
664 if(This
->version
!= BWRITERVS_VERSION(2, 1)){
665 WARN("Predicate register is allowed only in vs_2_x\n");
666 This
->state
= E_INVALIDARG
;
669 if(reg
->regnum
!= 0) {
670 WARN("Only predicate register p0 exists\n");
671 This
->state
= E_INVALIDARG
;
674 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
675 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
676 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
681 WARN("Invalid register type for 1.x-2.x vertex shader\n");
682 This
->state
= E_INVALIDARG
;
686 /* strictly speaking there are no modifiers in vs_2_0 and vs_1_x, but they can be written
687 * into the bytecode and since the compiler doesn't do such checks write them
688 * (the checks are done by the undocumented shader validator)
690 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
691 token
|= d3d9_dstmod(mod
);
694 token
|= d3d9_writemask(reg
->writemask
);
696 put_dword(buffer
, token
);
699 static void vs_1_x_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
700 struct bytecode_buffer
*buffer
) {
701 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
706 case BWRITERSPR_OUTPUT
:
707 /* Map the swizzle to a writemask, the format expected
710 switch(reg
->swizzle
) {
711 case BWRITERVS_SWIZZLE_X
:
712 component
= BWRITERSP_WRITEMASK_0
;
714 case BWRITERVS_SWIZZLE_Y
:
715 component
= BWRITERSP_WRITEMASK_1
;
717 case BWRITERVS_SWIZZLE_Z
:
718 component
= BWRITERSP_WRITEMASK_2
;
720 case BWRITERVS_SWIZZLE_W
:
721 component
= BWRITERSP_WRITEMASK_3
;
726 token
|= map_vs_output(This
, reg
->regnum
, component
, &has_swizzle
);
729 case BWRITERSPR_RASTOUT
:
730 case BWRITERSPR_ATTROUT
:
731 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
732 * but are unexpected. If we hit this path it might be due to an error.
734 FIXME("Unexpected register type %u\n", reg
->type
);
736 case BWRITERSPR_INPUT
:
737 case BWRITERSPR_TEMP
:
738 case BWRITERSPR_CONST
:
739 case BWRITERSPR_ADDR
:
740 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
741 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
743 if(reg
->rel_reg
->type
!= BWRITERSPR_ADDR
||
744 reg
->rel_reg
->regnum
!= 0 ||
745 reg
->rel_reg
->swizzle
!= BWRITERVS_SWIZZLE_X
) {
746 WARN("Relative addressing in vs_1_x is only allowed with a0.x\n");
747 This
->state
= E_INVALIDARG
;
750 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
755 WARN("Invalid register type for 1.x vshader\n");
756 This
->state
= E_INVALIDARG
;
760 token
|= d3d9_swizzle(reg
->swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
762 token
|= d3d9_srcmod(reg
->srcmod
);
763 put_dword(buffer
, token
);
766 static void write_srcregs(struct bc_writer
*This
, const struct instruction
*instr
,
767 struct bytecode_buffer
*buffer
){
769 if(instr
->has_predicate
){
770 This
->funcs
->srcreg(This
, &instr
->predicate
, buffer
);
772 for(i
= 0; i
< instr
->num_srcs
; i
++){
773 This
->funcs
->srcreg(This
, &instr
->src
[i
], buffer
);
777 static DWORD
map_ps_input(struct bc_writer
*This
,
778 const struct shader_reg
*reg
) {
780 /* Map color interpolators */
781 for(i
= 0; i
< 2; i
++) {
782 if(reg
->regnum
== This
->v_regnum
[i
]) {
783 token
|= (D3DSPR_INPUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
784 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
788 for(i
= 0; i
< 8; i
++) {
789 if(reg
->regnum
== This
->t_regnum
[i
]) {
790 token
|= (D3DSPR_TEXTURE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
791 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
796 WARN("Invalid ps 1/2 varying\n");
797 This
->state
= E_INVALIDARG
;
801 /* The length of an instruction consists of the destination register (if any),
802 * the number of source registers, the number of address registers used for
803 * indirect addressing, and optionally the predicate register
805 static DWORD
instrlen(const struct instruction
*instr
, unsigned int srcs
, unsigned int dsts
) {
807 DWORD ret
= srcs
+ dsts
+ (instr
->has_predicate
? 1 : 0);
810 if(instr
->dst
.rel_reg
) ret
++;
812 for(i
= 0; i
< srcs
; i
++) {
813 if(instr
->src
[i
].rel_reg
) ret
++;
818 static void sm_1_x_opcode(struct bc_writer
*This
,
819 const struct instruction
*instr
,
820 DWORD token
, struct bytecode_buffer
*buffer
) {
821 /* In sm_1_x instruction length isn't encoded */
823 token
|= D3DSI_COISSUE
;
825 put_dword(buffer
, token
);
828 static void instr_handler(struct bc_writer
*This
,
829 const struct instruction
*instr
,
830 struct bytecode_buffer
*buffer
) {
831 DWORD token
= d3d9_opcode(instr
->opcode
);
832 TRACE("token: %x\n", token
);
834 This
->funcs
->opcode(This
, instr
, token
, buffer
);
835 if(instr
->has_dst
) This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
836 write_srcregs(This
, instr
, buffer
);
839 static const struct instr_handler_table vs_1_x_handlers
[] = {
840 {BWRITERSIO_ADD
, instr_handler
},
841 {BWRITERSIO_NOP
, instr_handler
},
842 {BWRITERSIO_MOV
, instr_handler
},
843 {BWRITERSIO_SUB
, instr_handler
},
844 {BWRITERSIO_MAD
, instr_handler
},
845 {BWRITERSIO_MUL
, instr_handler
},
846 {BWRITERSIO_RCP
, instr_handler
},
847 {BWRITERSIO_RSQ
, instr_handler
},
848 {BWRITERSIO_DP3
, instr_handler
},
849 {BWRITERSIO_DP4
, instr_handler
},
850 {BWRITERSIO_MIN
, instr_handler
},
851 {BWRITERSIO_MAX
, instr_handler
},
852 {BWRITERSIO_SLT
, instr_handler
},
853 {BWRITERSIO_SGE
, instr_handler
},
854 {BWRITERSIO_EXP
, instr_handler
},
855 {BWRITERSIO_LOG
, instr_handler
},
856 {BWRITERSIO_EXPP
, instr_handler
},
857 {BWRITERSIO_LOGP
, instr_handler
},
858 {BWRITERSIO_DST
, instr_handler
},
859 {BWRITERSIO_FRC
, instr_handler
},
860 {BWRITERSIO_M4x4
, instr_handler
},
861 {BWRITERSIO_M4x3
, instr_handler
},
862 {BWRITERSIO_M3x4
, instr_handler
},
863 {BWRITERSIO_M3x3
, instr_handler
},
864 {BWRITERSIO_M3x2
, instr_handler
},
865 {BWRITERSIO_LIT
, instr_handler
},
867 {BWRITERSIO_END
, NULL
}, /* Sentinel value, it signals
868 the end of the list */
871 static const struct bytecode_backend vs_1_x_backend
= {
880 static void write_constB(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
881 write_const(shader
->constB
, shader
->num_cb
, D3DSIO_DEFB
, D3DSPR_CONSTBOOL
, buffer
, len
);
884 static void write_constI(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
885 write_const(shader
->constI
, shader
->num_ci
, D3DSIO_DEFI
, D3DSPR_CONSTINT
, buffer
, len
);
888 static void vs_2_header(struct bc_writer
*This
,
889 const struct bwriter_shader
*shader
,
890 struct bytecode_buffer
*buffer
) {
893 hr
= vs_find_builtin_varyings(This
, shader
);
899 /* Declare the shader type and version */
900 put_dword(buffer
, This
->version
);
902 write_declarations(buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, D3DSPR_INPUT
);
903 write_constF(shader
, buffer
, TRUE
);
904 write_constB(shader
, buffer
, TRUE
);
905 write_constI(shader
, buffer
, TRUE
);
909 static void vs_2_srcreg(struct bc_writer
*This
,
910 const struct shader_reg
*reg
,
911 struct bytecode_buffer
*buffer
) {
912 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
918 case BWRITERSPR_OUTPUT
:
919 /* Map the swizzle to a writemask, the format expected
922 switch(reg
->swizzle
) {
923 case BWRITERVS_SWIZZLE_X
:
924 component
= BWRITERSP_WRITEMASK_0
;
926 case BWRITERVS_SWIZZLE_Y
:
927 component
= BWRITERSP_WRITEMASK_1
;
929 case BWRITERVS_SWIZZLE_Z
:
930 component
= BWRITERSP_WRITEMASK_2
;
932 case BWRITERVS_SWIZZLE_W
:
933 component
= BWRITERSP_WRITEMASK_3
;
938 token
|= map_vs_output(This
, reg
->regnum
, component
, &has_swizzle
);
941 case BWRITERSPR_RASTOUT
:
942 case BWRITERSPR_ATTROUT
:
943 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
944 * but are unexpected. If we hit this path it might be due to an error.
946 FIXME("Unexpected register type %u\n", reg
->type
);
948 case BWRITERSPR_INPUT
:
949 case BWRITERSPR_TEMP
:
950 case BWRITERSPR_CONST
:
951 case BWRITERSPR_ADDR
:
952 case BWRITERSPR_CONSTINT
:
953 case BWRITERSPR_CONSTBOOL
:
954 case BWRITERSPR_LABEL
:
955 d3d9reg
= d3d9_register(reg
->type
);
956 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
957 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
958 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
961 case BWRITERSPR_LOOP
:
962 if(reg
->regnum
!= 0) {
963 WARN("Only regnum 0 is supported for the loop index register in vs_2_0\n");
964 This
->state
= E_INVALIDARG
;
967 token
|= (D3DSPR_LOOP
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
968 token
|= (D3DSPR_LOOP
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
969 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
972 case BWRITERSPR_PREDICATE
:
973 if(This
->version
!= BWRITERVS_VERSION(2, 1)){
974 WARN("Predicate register is allowed only in vs_2_x\n");
975 This
->state
= E_INVALIDARG
;
978 if(reg
->regnum
> 0) {
979 WARN("Only predicate register 0 is supported\n");
980 This
->state
= E_INVALIDARG
;
983 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
984 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
985 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
990 WARN("Invalid register type for 2.0 vshader\n");
991 This
->state
= E_INVALIDARG
;
995 token
|= d3d9_swizzle(reg
->swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
997 token
|= d3d9_srcmod(reg
->srcmod
);
1000 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1002 put_dword(buffer
, token
);
1004 /* vs_2_0 and newer write the register containing the index explicitly in the
1007 if(token
& D3DVS_ADDRMODE_RELATIVE
)
1008 vs_2_srcreg(This
, reg
->rel_reg
, buffer
);
1011 static void sm_2_opcode(struct bc_writer
*This
,
1012 const struct instruction
*instr
,
1013 DWORD token
, struct bytecode_buffer
*buffer
) {
1014 /* From sm 2 onwards instruction length is encoded in the opcode field */
1015 int dsts
= instr
->has_dst
? 1 : 0;
1016 token
|= instrlen(instr
, instr
->num_srcs
, dsts
) << D3DSI_INSTLENGTH_SHIFT
;
1018 token
|= (d3d9_comparetype(instr
->comptype
) << 16) & (0xf << 16);
1019 if(instr
->has_predicate
)
1020 token
|= D3DSHADER_INSTRUCTION_PREDICATED
;
1021 put_dword(buffer
,token
);
1024 static const struct instr_handler_table vs_2_0_handlers
[] = {
1025 {BWRITERSIO_ADD
, instr_handler
},
1026 {BWRITERSIO_NOP
, instr_handler
},
1027 {BWRITERSIO_MOV
, instr_handler
},
1028 {BWRITERSIO_SUB
, instr_handler
},
1029 {BWRITERSIO_MAD
, instr_handler
},
1030 {BWRITERSIO_MUL
, instr_handler
},
1031 {BWRITERSIO_RCP
, instr_handler
},
1032 {BWRITERSIO_RSQ
, instr_handler
},
1033 {BWRITERSIO_DP3
, instr_handler
},
1034 {BWRITERSIO_DP4
, instr_handler
},
1035 {BWRITERSIO_MIN
, instr_handler
},
1036 {BWRITERSIO_MAX
, instr_handler
},
1037 {BWRITERSIO_SLT
, instr_handler
},
1038 {BWRITERSIO_SGE
, instr_handler
},
1039 {BWRITERSIO_ABS
, instr_handler
},
1040 {BWRITERSIO_EXP
, instr_handler
},
1041 {BWRITERSIO_LOG
, instr_handler
},
1042 {BWRITERSIO_EXPP
, instr_handler
},
1043 {BWRITERSIO_LOGP
, instr_handler
},
1044 {BWRITERSIO_DST
, instr_handler
},
1045 {BWRITERSIO_LRP
, instr_handler
},
1046 {BWRITERSIO_FRC
, instr_handler
},
1047 {BWRITERSIO_CRS
, instr_handler
},
1048 {BWRITERSIO_SGN
, instr_handler
},
1049 {BWRITERSIO_NRM
, instr_handler
},
1050 {BWRITERSIO_SINCOS
, instr_handler
},
1051 {BWRITERSIO_M4x4
, instr_handler
},
1052 {BWRITERSIO_M4x3
, instr_handler
},
1053 {BWRITERSIO_M3x4
, instr_handler
},
1054 {BWRITERSIO_M3x3
, instr_handler
},
1055 {BWRITERSIO_M3x2
, instr_handler
},
1056 {BWRITERSIO_LIT
, instr_handler
},
1057 {BWRITERSIO_POW
, instr_handler
},
1058 {BWRITERSIO_MOVA
, instr_handler
},
1060 {BWRITERSIO_CALL
, instr_handler
},
1061 {BWRITERSIO_CALLNZ
, instr_handler
},
1062 {BWRITERSIO_REP
, instr_handler
},
1063 {BWRITERSIO_ENDREP
, instr_handler
},
1064 {BWRITERSIO_IF
, instr_handler
},
1065 {BWRITERSIO_LABEL
, instr_handler
},
1066 {BWRITERSIO_ELSE
, instr_handler
},
1067 {BWRITERSIO_ENDIF
, instr_handler
},
1068 {BWRITERSIO_LOOP
, instr_handler
},
1069 {BWRITERSIO_RET
, instr_handler
},
1070 {BWRITERSIO_ENDLOOP
, instr_handler
},
1072 {BWRITERSIO_END
, NULL
},
1075 static const struct bytecode_backend vs_2_0_backend
= {
1084 static const struct instr_handler_table vs_2_x_handlers
[] = {
1085 {BWRITERSIO_ADD
, instr_handler
},
1086 {BWRITERSIO_NOP
, instr_handler
},
1087 {BWRITERSIO_MOV
, instr_handler
},
1088 {BWRITERSIO_SUB
, instr_handler
},
1089 {BWRITERSIO_MAD
, instr_handler
},
1090 {BWRITERSIO_MUL
, instr_handler
},
1091 {BWRITERSIO_RCP
, instr_handler
},
1092 {BWRITERSIO_RSQ
, instr_handler
},
1093 {BWRITERSIO_DP3
, instr_handler
},
1094 {BWRITERSIO_DP4
, instr_handler
},
1095 {BWRITERSIO_MIN
, instr_handler
},
1096 {BWRITERSIO_MAX
, instr_handler
},
1097 {BWRITERSIO_SLT
, instr_handler
},
1098 {BWRITERSIO_SGE
, instr_handler
},
1099 {BWRITERSIO_ABS
, instr_handler
},
1100 {BWRITERSIO_EXP
, instr_handler
},
1101 {BWRITERSIO_LOG
, instr_handler
},
1102 {BWRITERSIO_EXPP
, instr_handler
},
1103 {BWRITERSIO_LOGP
, instr_handler
},
1104 {BWRITERSIO_DST
, instr_handler
},
1105 {BWRITERSIO_LRP
, instr_handler
},
1106 {BWRITERSIO_FRC
, instr_handler
},
1107 {BWRITERSIO_CRS
, instr_handler
},
1108 {BWRITERSIO_SGN
, instr_handler
},
1109 {BWRITERSIO_NRM
, instr_handler
},
1110 {BWRITERSIO_SINCOS
, instr_handler
},
1111 {BWRITERSIO_M4x4
, instr_handler
},
1112 {BWRITERSIO_M4x3
, instr_handler
},
1113 {BWRITERSIO_M3x4
, instr_handler
},
1114 {BWRITERSIO_M3x3
, instr_handler
},
1115 {BWRITERSIO_M3x2
, instr_handler
},
1116 {BWRITERSIO_LIT
, instr_handler
},
1117 {BWRITERSIO_POW
, instr_handler
},
1118 {BWRITERSIO_MOVA
, instr_handler
},
1120 {BWRITERSIO_CALL
, instr_handler
},
1121 {BWRITERSIO_CALLNZ
, instr_handler
},
1122 {BWRITERSIO_REP
, instr_handler
},
1123 {BWRITERSIO_ENDREP
, instr_handler
},
1124 {BWRITERSIO_IF
, instr_handler
},
1125 {BWRITERSIO_LABEL
, instr_handler
},
1126 {BWRITERSIO_IFC
, instr_handler
},
1127 {BWRITERSIO_ELSE
, instr_handler
},
1128 {BWRITERSIO_ENDIF
, instr_handler
},
1129 {BWRITERSIO_BREAK
, instr_handler
},
1130 {BWRITERSIO_BREAKC
, instr_handler
},
1131 {BWRITERSIO_LOOP
, instr_handler
},
1132 {BWRITERSIO_RET
, instr_handler
},
1133 {BWRITERSIO_ENDLOOP
, instr_handler
},
1135 {BWRITERSIO_SETP
, instr_handler
},
1136 {BWRITERSIO_BREAKP
, instr_handler
},
1138 {BWRITERSIO_END
, NULL
},
1141 static const struct bytecode_backend vs_2_x_backend
= {
1150 static void write_samplers(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1152 DWORD instr_dcl
= D3DSIO_DCL
| (2 << D3DSI_INSTLENGTH_SHIFT
);
1154 const DWORD reg
= (1<<31) |
1155 ((D3DSPR_SAMPLER
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
) |
1156 ((D3DSPR_SAMPLER
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
) |
1157 D3DSP_WRITEMASK_ALL
;
1159 for(i
= 0; i
< shader
->num_samplers
; i
++) {
1160 /* Write the DCL instruction */
1161 put_dword(buffer
, instr_dcl
);
1163 /* Already shifted */
1164 token
|= (d3d9_sampler(shader
->samplers
[i
].type
)) & D3DSP_TEXTURETYPE_MASK
;
1165 put_dword(buffer
, token
);
1166 token
= reg
| (shader
->samplers
[i
].regnum
& D3DSP_REGNUM_MASK
);
1167 token
|= d3d9_dstmod(shader
->samplers
[i
].mod
);
1168 put_dword(buffer
, token
);
1172 static void ps_2_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1173 HRESULT hr
= find_ps_builtin_semantics(This
, shader
, 8);
1179 /* Declare the shader type and version */
1180 put_dword(buffer
, This
->version
);
1181 write_samplers(shader
, buffer
);
1182 write_constF(shader
, buffer
, TRUE
);
1183 write_constB(shader
, buffer
, TRUE
);
1184 write_constI(shader
, buffer
, TRUE
);
1187 static void ps_2_srcreg(struct bc_writer
*This
,
1188 const struct shader_reg
*reg
,
1189 struct bytecode_buffer
*buffer
) {
1190 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1193 WARN("Relative addressing not supported in <= ps_3_0\n");
1194 This
->state
= E_INVALIDARG
;
1199 case BWRITERSPR_INPUT
:
1200 token
|= map_ps_input(This
, reg
);
1203 /* Can be mapped 1:1 */
1204 case BWRITERSPR_TEMP
:
1205 case BWRITERSPR_CONST
:
1206 case BWRITERSPR_COLOROUT
:
1207 case BWRITERSPR_CONSTBOOL
:
1208 case BWRITERSPR_CONSTINT
:
1209 case BWRITERSPR_SAMPLER
:
1210 case BWRITERSPR_LABEL
:
1211 case BWRITERSPR_DEPTHOUT
:
1212 d3d9reg
= d3d9_register(reg
->type
);
1213 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1214 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1215 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1218 case BWRITERSPR_PREDICATE
:
1219 if(This
->version
!= BWRITERPS_VERSION(2, 1)){
1220 WARN("Predicate register not supported in ps_2_0\n");
1221 This
->state
= E_INVALIDARG
;
1224 WARN("Predicate register with regnum %u not supported\n",
1226 This
->state
= E_INVALIDARG
;
1228 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1229 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1230 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
1234 WARN("Invalid register type for ps_2_0 shader\n");
1235 This
->state
= E_INVALIDARG
;
1239 token
|= d3d9_swizzle(reg
->swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1241 token
|= d3d9_srcmod(reg
->srcmod
);
1242 put_dword(buffer
, token
);
1245 static void ps_2_0_dstreg(struct bc_writer
*This
,
1246 const struct shader_reg
*reg
,
1247 struct bytecode_buffer
*buffer
,
1248 DWORD shift
, DWORD mod
) {
1249 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1253 WARN("Relative addressing not supported for destination registers\n");
1254 This
->state
= E_INVALIDARG
;
1259 case BWRITERSPR_TEMP
: /* 1:1 mapping */
1260 case BWRITERSPR_COLOROUT
:
1261 case BWRITERSPR_DEPTHOUT
:
1262 d3d9reg
= d3d9_register(reg
->type
);
1263 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1264 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1265 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1268 case BWRITERSPR_PREDICATE
:
1269 if(This
->version
!= BWRITERPS_VERSION(2, 1)){
1270 WARN("Predicate register not supported in ps_2_0\n");
1271 This
->state
= E_INVALIDARG
;
1273 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1274 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1275 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1278 /* texkill uses the input register as a destination parameter */
1279 case BWRITERSPR_INPUT
:
1280 token
|= map_ps_input(This
, reg
);
1284 WARN("Invalid dest register type for 2.x pshader\n");
1285 This
->state
= E_INVALIDARG
;
1289 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1290 token
|= d3d9_dstmod(mod
);
1292 token
|= d3d9_writemask(reg
->writemask
);
1293 put_dword(buffer
, token
);
1296 static const struct instr_handler_table ps_2_0_handlers
[] = {
1297 {BWRITERSIO_ADD
, instr_handler
},
1298 {BWRITERSIO_NOP
, instr_handler
},
1299 {BWRITERSIO_MOV
, instr_handler
},
1300 {BWRITERSIO_SUB
, instr_handler
},
1301 {BWRITERSIO_MAD
, instr_handler
},
1302 {BWRITERSIO_MUL
, instr_handler
},
1303 {BWRITERSIO_RCP
, instr_handler
},
1304 {BWRITERSIO_RSQ
, instr_handler
},
1305 {BWRITERSIO_DP3
, instr_handler
},
1306 {BWRITERSIO_DP4
, instr_handler
},
1307 {BWRITERSIO_MIN
, instr_handler
},
1308 {BWRITERSIO_MAX
, instr_handler
},
1309 {BWRITERSIO_ABS
, instr_handler
},
1310 {BWRITERSIO_EXP
, instr_handler
},
1311 {BWRITERSIO_LOG
, instr_handler
},
1312 {BWRITERSIO_EXPP
, instr_handler
},
1313 {BWRITERSIO_LOGP
, instr_handler
},
1314 {BWRITERSIO_LRP
, instr_handler
},
1315 {BWRITERSIO_FRC
, instr_handler
},
1316 {BWRITERSIO_CRS
, instr_handler
},
1317 {BWRITERSIO_NRM
, instr_handler
},
1318 {BWRITERSIO_SINCOS
, instr_handler
},
1319 {BWRITERSIO_M4x4
, instr_handler
},
1320 {BWRITERSIO_M4x3
, instr_handler
},
1321 {BWRITERSIO_M3x4
, instr_handler
},
1322 {BWRITERSIO_M3x3
, instr_handler
},
1323 {BWRITERSIO_M3x2
, instr_handler
},
1324 {BWRITERSIO_POW
, instr_handler
},
1325 {BWRITERSIO_DP2ADD
, instr_handler
},
1326 {BWRITERSIO_CMP
, instr_handler
},
1328 {BWRITERSIO_TEX
, instr_handler
},
1329 {BWRITERSIO_TEXLDP
, instr_handler
},
1330 {BWRITERSIO_TEXLDB
, instr_handler
},
1331 {BWRITERSIO_TEXKILL
, instr_handler
},
1333 {BWRITERSIO_END
, NULL
},
1336 static const struct bytecode_backend ps_2_0_backend
= {
1345 static const struct instr_handler_table ps_2_x_handlers
[] = {
1346 {BWRITERSIO_ADD
, instr_handler
},
1347 {BWRITERSIO_NOP
, instr_handler
},
1348 {BWRITERSIO_MOV
, instr_handler
},
1349 {BWRITERSIO_SUB
, instr_handler
},
1350 {BWRITERSIO_MAD
, instr_handler
},
1351 {BWRITERSIO_MUL
, instr_handler
},
1352 {BWRITERSIO_RCP
, instr_handler
},
1353 {BWRITERSIO_RSQ
, instr_handler
},
1354 {BWRITERSIO_DP3
, instr_handler
},
1355 {BWRITERSIO_DP4
, instr_handler
},
1356 {BWRITERSIO_MIN
, instr_handler
},
1357 {BWRITERSIO_MAX
, instr_handler
},
1358 {BWRITERSIO_ABS
, instr_handler
},
1359 {BWRITERSIO_EXP
, instr_handler
},
1360 {BWRITERSIO_LOG
, instr_handler
},
1361 {BWRITERSIO_EXPP
, instr_handler
},
1362 {BWRITERSIO_LOGP
, instr_handler
},
1363 {BWRITERSIO_LRP
, instr_handler
},
1364 {BWRITERSIO_FRC
, instr_handler
},
1365 {BWRITERSIO_CRS
, instr_handler
},
1366 {BWRITERSIO_NRM
, instr_handler
},
1367 {BWRITERSIO_SINCOS
, instr_handler
},
1368 {BWRITERSIO_M4x4
, instr_handler
},
1369 {BWRITERSIO_M4x3
, instr_handler
},
1370 {BWRITERSIO_M3x4
, instr_handler
},
1371 {BWRITERSIO_M3x3
, instr_handler
},
1372 {BWRITERSIO_M3x2
, instr_handler
},
1373 {BWRITERSIO_POW
, instr_handler
},
1374 {BWRITERSIO_DP2ADD
, instr_handler
},
1375 {BWRITERSIO_CMP
, instr_handler
},
1377 {BWRITERSIO_CALL
, instr_handler
},
1378 {BWRITERSIO_CALLNZ
, instr_handler
},
1379 {BWRITERSIO_REP
, instr_handler
},
1380 {BWRITERSIO_ENDREP
, instr_handler
},
1381 {BWRITERSIO_IF
, instr_handler
},
1382 {BWRITERSIO_LABEL
, instr_handler
},
1383 {BWRITERSIO_IFC
, instr_handler
},
1384 {BWRITERSIO_ELSE
, instr_handler
},
1385 {BWRITERSIO_ENDIF
, instr_handler
},
1386 {BWRITERSIO_BREAK
, instr_handler
},
1387 {BWRITERSIO_BREAKC
, instr_handler
},
1388 {BWRITERSIO_RET
, instr_handler
},
1390 {BWRITERSIO_TEX
, instr_handler
},
1391 {BWRITERSIO_TEXLDP
, instr_handler
},
1392 {BWRITERSIO_TEXLDB
, instr_handler
},
1393 {BWRITERSIO_TEXKILL
, instr_handler
},
1394 {BWRITERSIO_DSX
, instr_handler
},
1395 {BWRITERSIO_DSY
, instr_handler
},
1397 {BWRITERSIO_SETP
, instr_handler
},
1398 {BWRITERSIO_BREAKP
, instr_handler
},
1400 {BWRITERSIO_TEXLDD
, instr_handler
},
1402 {BWRITERSIO_END
, NULL
},
1405 static const struct bytecode_backend ps_2_x_backend
= {
1414 static void sm_3_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1415 /* Declare the shader type and version */
1416 put_dword(buffer
, This
->version
);
1418 write_declarations(buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, D3DSPR_INPUT
);
1419 write_declarations(buffer
, TRUE
, shader
->outputs
, shader
->num_outputs
, D3DSPR_OUTPUT
);
1420 write_constF(shader
, buffer
, TRUE
);
1421 write_constB(shader
, buffer
, TRUE
);
1422 write_constI(shader
, buffer
, TRUE
);
1423 write_samplers(shader
, buffer
);
1427 static void sm_3_srcreg(struct bc_writer
*This
,
1428 const struct shader_reg
*reg
,
1429 struct bytecode_buffer
*buffer
) {
1430 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1433 d3d9reg
= d3d9_register(reg
->type
);
1434 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1435 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1436 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
;
1438 token
|= d3d9_swizzle(reg
->swizzle
) & D3DVS_SWIZZLE_MASK
;
1439 token
|= d3d9_srcmod(reg
->srcmod
);
1442 if(reg
->type
== BWRITERSPR_CONST
&& This
->version
== BWRITERPS_VERSION(3, 0)) {
1443 WARN("c%u[...] is unsupported in ps_3_0\n", reg
->regnum
);
1444 This
->state
= E_INVALIDARG
;
1447 if(((reg
->rel_reg
->type
== BWRITERSPR_ADDR
&& This
->version
== BWRITERVS_VERSION(3, 0)) ||
1448 reg
->rel_reg
->type
== BWRITERSPR_LOOP
) &&
1449 reg
->rel_reg
->regnum
== 0) {
1450 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1452 WARN("Unsupported relative addressing register\n");
1453 This
->state
= E_INVALIDARG
;
1458 put_dword(buffer
, token
);
1460 /* vs_2_0 and newer write the register containing the index explicitly in the
1463 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
1464 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
1468 static void sm_3_dstreg(struct bc_writer
*This
,
1469 const struct shader_reg
*reg
,
1470 struct bytecode_buffer
*buffer
,
1471 DWORD shift
, DWORD mod
) {
1472 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1476 if(This
->version
== BWRITERVS_VERSION(3, 0) &&
1477 reg
->type
== BWRITERSPR_OUTPUT
) {
1478 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1480 WARN("Relative addressing not supported for this shader type or register type\n");
1481 This
->state
= E_INVALIDARG
;
1486 d3d9reg
= d3d9_register(reg
->type
);
1487 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1488 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1489 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1491 token
|= d3d9_dstmod(mod
);
1493 token
|= d3d9_writemask(reg
->writemask
);
1494 put_dword(buffer
, token
);
1496 /* vs_2_0 and newer write the register containing the index explicitly in the
1499 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
1500 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
1504 static const struct instr_handler_table vs_3_handlers
[] = {
1505 {BWRITERSIO_ADD
, instr_handler
},
1506 {BWRITERSIO_NOP
, instr_handler
},
1507 {BWRITERSIO_MOV
, instr_handler
},
1508 {BWRITERSIO_SUB
, instr_handler
},
1509 {BWRITERSIO_MAD
, instr_handler
},
1510 {BWRITERSIO_MUL
, instr_handler
},
1511 {BWRITERSIO_RCP
, instr_handler
},
1512 {BWRITERSIO_RSQ
, instr_handler
},
1513 {BWRITERSIO_DP3
, instr_handler
},
1514 {BWRITERSIO_DP4
, instr_handler
},
1515 {BWRITERSIO_MIN
, instr_handler
},
1516 {BWRITERSIO_MAX
, instr_handler
},
1517 {BWRITERSIO_SLT
, instr_handler
},
1518 {BWRITERSIO_SGE
, instr_handler
},
1519 {BWRITERSIO_ABS
, instr_handler
},
1520 {BWRITERSIO_EXP
, instr_handler
},
1521 {BWRITERSIO_LOG
, instr_handler
},
1522 {BWRITERSIO_EXPP
, instr_handler
},
1523 {BWRITERSIO_LOGP
, instr_handler
},
1524 {BWRITERSIO_DST
, instr_handler
},
1525 {BWRITERSIO_LRP
, instr_handler
},
1526 {BWRITERSIO_FRC
, instr_handler
},
1527 {BWRITERSIO_CRS
, instr_handler
},
1528 {BWRITERSIO_SGN
, instr_handler
},
1529 {BWRITERSIO_NRM
, instr_handler
},
1530 {BWRITERSIO_SINCOS
, instr_handler
},
1531 {BWRITERSIO_M4x4
, instr_handler
},
1532 {BWRITERSIO_M4x3
, instr_handler
},
1533 {BWRITERSIO_M3x4
, instr_handler
},
1534 {BWRITERSIO_M3x3
, instr_handler
},
1535 {BWRITERSIO_M3x2
, instr_handler
},
1536 {BWRITERSIO_LIT
, instr_handler
},
1537 {BWRITERSIO_POW
, instr_handler
},
1538 {BWRITERSIO_MOVA
, instr_handler
},
1540 {BWRITERSIO_CALL
, instr_handler
},
1541 {BWRITERSIO_CALLNZ
, instr_handler
},
1542 {BWRITERSIO_REP
, instr_handler
},
1543 {BWRITERSIO_ENDREP
, instr_handler
},
1544 {BWRITERSIO_IF
, instr_handler
},
1545 {BWRITERSIO_LABEL
, instr_handler
},
1546 {BWRITERSIO_IFC
, instr_handler
},
1547 {BWRITERSIO_ELSE
, instr_handler
},
1548 {BWRITERSIO_ENDIF
, instr_handler
},
1549 {BWRITERSIO_BREAK
, instr_handler
},
1550 {BWRITERSIO_BREAKC
, instr_handler
},
1551 {BWRITERSIO_LOOP
, instr_handler
},
1552 {BWRITERSIO_RET
, instr_handler
},
1553 {BWRITERSIO_ENDLOOP
, instr_handler
},
1555 {BWRITERSIO_SETP
, instr_handler
},
1556 {BWRITERSIO_BREAKP
, instr_handler
},
1557 {BWRITERSIO_TEXLDL
, instr_handler
},
1559 {BWRITERSIO_END
, NULL
},
1562 static const struct bytecode_backend vs_3_backend
= {
1571 static const struct instr_handler_table ps_3_handlers
[] = {
1572 {BWRITERSIO_ADD
, instr_handler
},
1573 {BWRITERSIO_NOP
, instr_handler
},
1574 {BWRITERSIO_MOV
, instr_handler
},
1575 {BWRITERSIO_SUB
, instr_handler
},
1576 {BWRITERSIO_MAD
, instr_handler
},
1577 {BWRITERSIO_MUL
, instr_handler
},
1578 {BWRITERSIO_RCP
, instr_handler
},
1579 {BWRITERSIO_RSQ
, instr_handler
},
1580 {BWRITERSIO_DP3
, instr_handler
},
1581 {BWRITERSIO_DP4
, instr_handler
},
1582 {BWRITERSIO_MIN
, instr_handler
},
1583 {BWRITERSIO_MAX
, instr_handler
},
1584 {BWRITERSIO_ABS
, instr_handler
},
1585 {BWRITERSIO_EXP
, instr_handler
},
1586 {BWRITERSIO_LOG
, instr_handler
},
1587 {BWRITERSIO_EXPP
, instr_handler
},
1588 {BWRITERSIO_LOGP
, instr_handler
},
1589 {BWRITERSIO_LRP
, instr_handler
},
1590 {BWRITERSIO_FRC
, instr_handler
},
1591 {BWRITERSIO_CRS
, instr_handler
},
1592 {BWRITERSIO_NRM
, instr_handler
},
1593 {BWRITERSIO_SINCOS
, instr_handler
},
1594 {BWRITERSIO_M4x4
, instr_handler
},
1595 {BWRITERSIO_M4x3
, instr_handler
},
1596 {BWRITERSIO_M3x4
, instr_handler
},
1597 {BWRITERSIO_M3x3
, instr_handler
},
1598 {BWRITERSIO_M3x2
, instr_handler
},
1599 {BWRITERSIO_POW
, instr_handler
},
1600 {BWRITERSIO_DP2ADD
, instr_handler
},
1601 {BWRITERSIO_CMP
, instr_handler
},
1603 {BWRITERSIO_CALL
, instr_handler
},
1604 {BWRITERSIO_CALLNZ
, instr_handler
},
1605 {BWRITERSIO_REP
, instr_handler
},
1606 {BWRITERSIO_ENDREP
, instr_handler
},
1607 {BWRITERSIO_IF
, instr_handler
},
1608 {BWRITERSIO_LABEL
, instr_handler
},
1609 {BWRITERSIO_IFC
, instr_handler
},
1610 {BWRITERSIO_ELSE
, instr_handler
},
1611 {BWRITERSIO_ENDIF
, instr_handler
},
1612 {BWRITERSIO_BREAK
, instr_handler
},
1613 {BWRITERSIO_BREAKC
, instr_handler
},
1614 {BWRITERSIO_LOOP
, instr_handler
},
1615 {BWRITERSIO_RET
, instr_handler
},
1616 {BWRITERSIO_ENDLOOP
, instr_handler
},
1618 {BWRITERSIO_SETP
, instr_handler
},
1619 {BWRITERSIO_BREAKP
, instr_handler
},
1620 {BWRITERSIO_TEXLDL
, instr_handler
},
1622 {BWRITERSIO_TEX
, instr_handler
},
1623 {BWRITERSIO_TEXLDP
, instr_handler
},
1624 {BWRITERSIO_TEXLDB
, instr_handler
},
1625 {BWRITERSIO_TEXKILL
, instr_handler
},
1626 {BWRITERSIO_DSX
, instr_handler
},
1627 {BWRITERSIO_DSY
, instr_handler
},
1628 {BWRITERSIO_TEXLDD
, instr_handler
},
1630 {BWRITERSIO_END
, NULL
},
1633 static const struct bytecode_backend ps_3_backend
= {
1642 static void init_vs10_dx9_writer(struct bc_writer
*writer
) {
1643 TRACE("Creating DirectX9 vertex shader 1.0 writer\n");
1644 writer
->funcs
= &vs_1_x_backend
;
1647 static void init_vs11_dx9_writer(struct bc_writer
*writer
) {
1648 TRACE("Creating DirectX9 vertex shader 1.1 writer\n");
1649 writer
->funcs
= &vs_1_x_backend
;
1652 static void init_vs20_dx9_writer(struct bc_writer
*writer
) {
1653 TRACE("Creating DirectX9 vertex shader 2.0 writer\n");
1654 writer
->funcs
= &vs_2_0_backend
;
1657 static void init_vs2x_dx9_writer(struct bc_writer
*writer
) {
1658 TRACE("Creating DirectX9 vertex shader 2.x writer\n");
1659 writer
->funcs
= &vs_2_x_backend
;
1662 static void init_vs30_dx9_writer(struct bc_writer
*writer
) {
1663 TRACE("Creating DirectX9 vertex shader 3.0 writer\n");
1664 writer
->funcs
= &vs_3_backend
;
1667 static void init_ps20_dx9_writer(struct bc_writer
*writer
) {
1668 TRACE("Creating DirectX9 pixel shader 2.0 writer\n");
1669 writer
->funcs
= &ps_2_0_backend
;
1672 static void init_ps2x_dx9_writer(struct bc_writer
*writer
) {
1673 TRACE("Creating DirectX9 pixel shader 2.x writer\n");
1674 writer
->funcs
= &ps_2_x_backend
;
1677 static void init_ps30_dx9_writer(struct bc_writer
*writer
) {
1678 TRACE("Creating DirectX9 pixel shader 3.0 writer\n");
1679 writer
->funcs
= &ps_3_backend
;
1682 static struct bc_writer
*create_writer(DWORD version
, DWORD dxversion
) {
1683 struct bc_writer
*ret
= asm_alloc(sizeof(*ret
));
1686 WARN("Failed to allocate a bytecode writer instance\n");
1691 case BWRITERVS_VERSION(1, 0):
1692 if(dxversion
!= 9) {
1693 WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion
);
1696 init_vs10_dx9_writer(ret
);
1698 case BWRITERVS_VERSION(1, 1):
1699 if(dxversion
!= 9) {
1700 WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion
);
1703 init_vs11_dx9_writer(ret
);
1705 case BWRITERVS_VERSION(2, 0):
1706 if(dxversion
!= 9) {
1707 WARN("Unsupported dxversion for vertex shader 2.0 requested: %u\n", dxversion
);
1710 init_vs20_dx9_writer(ret
);
1712 case BWRITERVS_VERSION(2, 1):
1713 if(dxversion
!= 9) {
1714 WARN("Unsupported dxversion for vertex shader 2.x requested: %u\n", dxversion
);
1717 init_vs2x_dx9_writer(ret
);
1719 case BWRITERVS_VERSION(3, 0):
1720 if(dxversion
!= 9) {
1721 WARN("Unsupported dxversion for vertex shader 3.0 requested: %u\n", dxversion
);
1724 init_vs30_dx9_writer(ret
);
1727 case BWRITERPS_VERSION(1, 0):
1728 if(dxversion
!= 9) {
1729 WARN("Unsupported dxversion for pixel shader 1.0 requested: %u\n", dxversion
);
1732 /* TODO: Set the appropriate writer backend */
1734 case BWRITERPS_VERSION(1, 1):
1735 if(dxversion
!= 9) {
1736 WARN("Unsupported dxversion for pixel shader 1.1 requested: %u\n", dxversion
);
1739 /* TODO: Set the appropriate writer backend */
1741 case BWRITERPS_VERSION(1, 2):
1742 if(dxversion
!= 9) {
1743 WARN("Unsupported dxversion for pixel shader 1.2 requested: %u\n", dxversion
);
1746 /* TODO: Set the appropriate writer backend */
1748 case BWRITERPS_VERSION(1, 3):
1749 if(dxversion
!= 9) {
1750 WARN("Unsupported dxversion for pixel shader 1.3 requested: %u\n", dxversion
);
1753 /* TODO: Set the appropriate writer backend */
1755 case BWRITERPS_VERSION(1, 4):
1756 if(dxversion
!= 9) {
1757 WARN("Unsupported dxversion for pixel shader 1.4 requested: %u\n", dxversion
);
1760 /* TODO: Set the appropriate writer backend */
1763 case BWRITERPS_VERSION(2, 0):
1764 if(dxversion
!= 9) {
1765 WARN("Unsupported dxversion for pixel shader 2.0 requested: %u\n", dxversion
);
1768 init_ps20_dx9_writer(ret
);
1771 case BWRITERPS_VERSION(2, 1):
1772 if(dxversion
!= 9) {
1773 WARN("Unsupported dxversion for pixel shader 2.x requested: %u\n", dxversion
);
1776 init_ps2x_dx9_writer(ret
);
1779 case BWRITERPS_VERSION(3, 0):
1780 if(dxversion
!= 9) {
1781 WARN("Unsupported dxversion for pixel shader 3.0 requested: %u\n", dxversion
);
1784 init_ps30_dx9_writer(ret
);
1788 WARN("Unexpected shader version requested: %08x\n", version
);
1791 ret
->version
= version
;
1799 static HRESULT
call_instr_handler(struct bc_writer
*writer
,
1800 const struct instruction
*instr
,
1801 struct bytecode_buffer
*buffer
) {
1804 while(writer
->funcs
->instructions
[i
].opcode
!= BWRITERSIO_END
) {
1805 if(instr
->opcode
== writer
->funcs
->instructions
[i
].opcode
) {
1806 if(!writer
->funcs
->instructions
[i
].func
) {
1807 WARN("Opcode %u not supported by this profile\n", instr
->opcode
);
1808 return E_INVALIDARG
;
1810 writer
->funcs
->instructions
[i
].func(writer
, instr
, buffer
);
1816 FIXME("Unhandled instruction %u\n", instr
->opcode
);
1817 return E_INVALIDARG
;
1820 /* SlWriteBytecode (wineshader.@)
1822 * Writes shader version specific bytecode from the shader passed in.
1823 * The returned bytecode can be passed to the Direct3D runtime like
1824 * IDirect3DDevice9::Create*Shader.
1827 * shader: Shader to translate into bytecode
1828 * version: Shader version to generate(d3d version token)
1829 * dxversion: DirectX version the code targets
1830 * result: the resulting shader bytecode
1835 DWORD
SlWriteBytecode(const struct bwriter_shader
*shader
, int dxversion
, DWORD
**result
) {
1836 struct bc_writer
*writer
;
1837 struct bytecode_buffer
*buffer
= NULL
;
1842 ERR("NULL shader structure, aborting\n");
1845 writer
= create_writer(shader
->version
, dxversion
);
1849 WARN("Could not create a bytecode writer instance. Either unsupported version\n");
1850 WARN("or out of memory\n");
1855 buffer
= allocate_buffer();
1857 WARN("Failed to allocate a buffer for the shader bytecode\n");
1862 writer
->funcs
->header(writer
, shader
, buffer
);
1863 if(FAILED(writer
->state
)) {
1868 for(i
= 0; i
< shader
->num_instrs
; i
++) {
1869 hr
= call_instr_handler(writer
, shader
->instr
[i
], buffer
);
1875 if(FAILED(writer
->state
)) {
1880 writer
->funcs
->end(writer
, shader
, buffer
);
1882 if(FAILED(buffer
->state
)) {
1887 /* Cut off unneeded memory from the result buffer */
1888 *result
= asm_realloc(buffer
->data
,
1889 sizeof(DWORD
) * buffer
->size
);
1891 *result
= buffer
->data
;
1893 buffer
->data
= NULL
;
1898 asm_free(buffer
->data
);
1905 void SlDeleteShader(struct bwriter_shader
*shader
) {
1908 TRACE("Deleting shader %p\n", shader
);
1910 for(i
= 0; i
< shader
->num_cf
; i
++) {
1911 asm_free(shader
->constF
[i
]);
1913 asm_free(shader
->constF
);
1914 for(i
= 0; i
< shader
->num_ci
; i
++) {
1915 asm_free(shader
->constI
[i
]);
1917 asm_free(shader
->constI
);
1918 for(i
= 0; i
< shader
->num_cb
; i
++) {
1919 asm_free(shader
->constB
[i
]);
1921 asm_free(shader
->constB
);
1923 asm_free(shader
->inputs
);
1924 asm_free(shader
->outputs
);
1925 asm_free(shader
->samplers
);
1927 for(i
= 0; i
< shader
->num_instrs
; i
++) {
1928 for(j
= 0; j
< shader
->instr
[i
]->num_srcs
; j
++) {
1929 asm_free(shader
->instr
[i
]->src
[j
].rel_reg
);
1931 asm_free(shader
->instr
[i
]->src
);
1932 asm_free(shader
->instr
[i
]);
1934 asm_free(shader
->instr
);