2 * Direct3D bytecode output functions
4 * Copyright 2008 Stefan Dösinger
5 * Copyright 2009 Matteo Bruni
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
25 #include "wine/debug.h"
27 #include "d3d9types.h"
28 #include "d3dcompiler_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(asmshader
);
32 /****************************************************************
33 * General assembler shader construction helper routines follow *
34 ****************************************************************/
35 /* struct instruction *alloc_instr
37 * Allocates a new instruction structure with srcs registers
40 * srcs: Number of source registers to allocate
43 * A pointer to the allocated instruction structure
44 * NULL in case of an allocation failure
46 struct instruction
*alloc_instr(unsigned int srcs
) {
47 struct instruction
*ret
= asm_alloc(sizeof(*ret
));
49 ERR("Failed to allocate memory for an instruction structure\n");
54 ret
->src
= asm_alloc(srcs
* sizeof(*ret
->src
));
56 ERR("Failed to allocate memory for instruction registers\n");
65 /* void add_instruction
67 * Adds a new instruction to the shader's instructions array and grows the instruction array
70 * The function does NOT copy the instruction structure. Make sure not to release the
71 * instruction or any of its substructures like registers.
74 * shader: Shader to add the instruction to
75 * instr: Instruction to add to the shader
77 BOOL
add_instruction(struct bwriter_shader
*shader
, struct instruction
*instr
) {
78 struct instruction
**new_instructions
;
80 if(!shader
) return FALSE
;
82 if(shader
->instr_alloc_size
== 0) {
83 shader
->instr
= asm_alloc(sizeof(*shader
->instr
) * INSTRARRAY_INITIAL_SIZE
);
85 ERR("Failed to allocate the shader instruction array\n");
88 shader
->instr_alloc_size
= INSTRARRAY_INITIAL_SIZE
;
89 } else if(shader
->instr_alloc_size
== shader
->num_instrs
) {
90 new_instructions
= asm_realloc(shader
->instr
,
91 sizeof(*shader
->instr
) * (shader
->instr_alloc_size
) * 2);
92 if(!new_instructions
) {
93 ERR("Failed to grow the shader instruction array\n");
96 shader
->instr
= new_instructions
;
97 shader
->instr_alloc_size
= shader
->instr_alloc_size
* 2;
98 } else if(shader
->num_instrs
> shader
->instr_alloc_size
) {
99 ERR("More instructions than allocated. This should not happen\n");
103 shader
->instr
[shader
->num_instrs
] = instr
;
104 shader
->num_instrs
++;
108 BOOL
add_constF(struct bwriter_shader
*shader
, DWORD reg
, float x
, float y
, float z
, float w
) {
109 struct constant
*newconst
;
112 struct constant
**newarray
;
113 newarray
= asm_realloc(shader
->constF
,
114 sizeof(*shader
->constF
) * (shader
->num_cf
+ 1));
116 ERR("Failed to grow the constants array\n");
119 shader
->constF
= newarray
;
121 shader
->constF
= asm_alloc(sizeof(*shader
->constF
));
122 if(!shader
->constF
) {
123 ERR("Failed to allocate the constants array\n");
128 newconst
= asm_alloc(sizeof(*newconst
));
130 ERR("Failed to allocate a new constant\n");
133 newconst
->regnum
= reg
;
134 newconst
->value
[0].f
= x
;
135 newconst
->value
[1].f
= y
;
136 newconst
->value
[2].f
= z
;
137 newconst
->value
[3].f
= w
;
138 shader
->constF
[shader
->num_cf
] = newconst
;
144 BOOL
add_constI(struct bwriter_shader
*shader
, DWORD reg
, INT x
, INT y
, INT z
, INT w
) {
145 struct constant
*newconst
;
148 struct constant
**newarray
;
149 newarray
= asm_realloc(shader
->constI
,
150 sizeof(*shader
->constI
) * (shader
->num_ci
+ 1));
152 ERR("Failed to grow the constants array\n");
155 shader
->constI
= newarray
;
157 shader
->constI
= asm_alloc(sizeof(*shader
->constI
));
158 if(!shader
->constI
) {
159 ERR("Failed to allocate the constants array\n");
164 newconst
= asm_alloc(sizeof(*newconst
));
166 ERR("Failed to allocate a new constant\n");
169 newconst
->regnum
= reg
;
170 newconst
->value
[0].i
= x
;
171 newconst
->value
[1].i
= y
;
172 newconst
->value
[2].i
= z
;
173 newconst
->value
[3].i
= w
;
174 shader
->constI
[shader
->num_ci
] = newconst
;
180 BOOL
add_constB(struct bwriter_shader
*shader
, DWORD reg
, BOOL x
) {
181 struct constant
*newconst
;
184 struct constant
**newarray
;
185 newarray
= asm_realloc(shader
->constB
,
186 sizeof(*shader
->constB
) * (shader
->num_cb
+ 1));
188 ERR("Failed to grow the constants array\n");
191 shader
->constB
= newarray
;
193 shader
->constB
= asm_alloc(sizeof(*shader
->constB
));
194 if(!shader
->constB
) {
195 ERR("Failed to allocate the constants array\n");
200 newconst
= asm_alloc(sizeof(*newconst
));
202 ERR("Failed to allocate a new constant\n");
205 newconst
->regnum
= reg
;
206 newconst
->value
[0].b
= x
;
207 shader
->constB
[shader
->num_cb
] = newconst
;
213 BOOL
record_declaration(struct bwriter_shader
*shader
, DWORD usage
,
214 DWORD usage_idx
, DWORD mod
, BOOL output
,
215 DWORD regnum
, DWORD writemask
, BOOL builtin
) {
217 struct declaration
**decl
;
220 if(!shader
) return FALSE
;
223 num
= &shader
->num_outputs
;
224 decl
= &shader
->outputs
;
226 num
= &shader
->num_inputs
;
227 decl
= &shader
->inputs
;
231 *decl
= asm_alloc(sizeof(**decl
));
233 ERR("Error allocating declarations array\n");
237 struct declaration
*newdecl
;
238 for(i
= 0; i
< *num
; i
++) {
239 if((*decl
)[i
].regnum
== regnum
&& ((*decl
)[i
].writemask
& writemask
)) {
240 WARN("Declaration of register %u already exists, writemask match 0x%x\n",
241 regnum
, (*decl
)[i
].writemask
& writemask
);
245 newdecl
= asm_realloc(*decl
,
246 sizeof(**decl
) * ((*num
) + 1));
248 ERR("Error reallocating declarations array\n");
253 (*decl
)[*num
].usage
= usage
;
254 (*decl
)[*num
].usage_idx
= usage_idx
;
255 (*decl
)[*num
].regnum
= regnum
;
256 (*decl
)[*num
].mod
= mod
;
257 (*decl
)[*num
].writemask
= writemask
;
258 (*decl
)[*num
].builtin
= builtin
;
264 BOOL
record_sampler(struct bwriter_shader
*shader
, DWORD samptype
, DWORD mod
, DWORD regnum
) {
267 if(!shader
) return FALSE
;
269 if(shader
->num_samplers
== 0) {
270 shader
->samplers
= asm_alloc(sizeof(*shader
->samplers
));
271 if(!shader
->samplers
) {
272 ERR("Error allocating samplers array\n");
276 struct samplerdecl
*newarray
;
278 for(i
= 0; i
< shader
->num_samplers
; i
++) {
279 if(shader
->samplers
[i
].regnum
== regnum
) {
280 WARN("Sampler %u already declared\n", regnum
);
281 /* This is not an error as far as the assembler is concerned.
282 * Direct3D might refuse to load the compiled shader though
287 newarray
= asm_realloc(shader
->samplers
,
288 sizeof(*shader
->samplers
) * (shader
->num_samplers
+ 1));
290 ERR("Error reallocating samplers array\n");
293 shader
->samplers
= newarray
;
296 shader
->samplers
[shader
->num_samplers
].type
= samptype
;
297 shader
->samplers
[shader
->num_samplers
].mod
= mod
;
298 shader
->samplers
[shader
->num_samplers
].regnum
= regnum
;
299 shader
->num_samplers
++;
304 /* shader bytecode buffer manipulation functions.
305 * allocate_buffer creates a new buffer structure, put_dword adds a new
306 * DWORD to the buffer. In the rare case of a memory allocation failure
307 * when trying to grow the buffer a flag is set in the buffer to mark it
308 * invalid. This avoids return value checking and passing in many places
310 static struct bytecode_buffer
*allocate_buffer(void) {
311 struct bytecode_buffer
*ret
;
313 ret
= asm_alloc(sizeof(*ret
));
314 if(!ret
) return NULL
;
316 ret
->alloc_size
= BYTECODEBUFFER_INITIAL_SIZE
;
317 ret
->data
= asm_alloc(sizeof(DWORD
) * ret
->alloc_size
);
326 static void put_dword(struct bytecode_buffer
*buffer
, DWORD value
) {
327 if(FAILED(buffer
->state
)) return;
329 if(buffer
->alloc_size
== buffer
->size
) {
331 buffer
->alloc_size
*= 2;
332 newarray
= asm_realloc(buffer
->data
,
333 sizeof(DWORD
) * buffer
->alloc_size
);
335 ERR("Failed to grow the buffer data memory\n");
336 buffer
->state
= E_OUTOFMEMORY
;
339 buffer
->data
= newarray
;
341 buffer
->data
[buffer
->size
++] = value
;
344 /******************************************************
345 * Implementation of the writer functions starts here *
346 ******************************************************/
347 static void write_declarations(struct bc_writer
*This
,
348 struct bytecode_buffer
*buffer
, BOOL len
,
349 const struct declaration
*decls
, unsigned int num
, DWORD type
) {
351 DWORD instr_dcl
= D3DSIO_DCL
;
353 struct shader_reg reg
;
355 ZeroMemory(®
, sizeof(reg
));
358 instr_dcl
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
361 for(i
= 0; i
< num
; i
++) {
362 if(decls
[i
].builtin
) continue;
364 /* Write the DCL instruction */
365 put_dword(buffer
, instr_dcl
);
367 /* Write the usage and index */
368 token
= (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
369 token
|= (decls
[i
].usage
<< D3DSP_DCL_USAGE_SHIFT
) & D3DSP_DCL_USAGE_MASK
;
370 token
|= (decls
[i
].usage_idx
<< D3DSP_DCL_USAGEINDEX_SHIFT
) & D3DSP_DCL_USAGEINDEX_MASK
;
371 put_dword(buffer
, token
);
373 /* Write the dest register */
375 reg
.regnum
= decls
[i
].regnum
;
376 reg
.u
.writemask
= decls
[i
].writemask
;
377 This
->funcs
->dstreg(This
, ®
, buffer
, 0, decls
[i
].mod
);
381 static void write_const(struct constant
**consts
, int num
, DWORD opcode
, DWORD reg_type
, struct bytecode_buffer
*buffer
, BOOL len
) {
383 DWORD instr_def
= opcode
;
384 const DWORD reg
= (1<<31) |
385 ((reg_type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
) |
386 ((reg_type
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
) |
390 if(opcode
== D3DSIO_DEFB
)
391 instr_def
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
393 instr_def
|= 5 << D3DSI_INSTLENGTH_SHIFT
;
396 for(i
= 0; i
< num
; i
++) {
397 /* Write the DEF instruction */
398 put_dword(buffer
, instr_def
);
400 put_dword(buffer
, reg
| (consts
[i
]->regnum
& D3DSP_REGNUM_MASK
));
401 put_dword(buffer
, consts
[i
]->value
[0].d
);
402 if(opcode
!= D3DSIO_DEFB
) {
403 put_dword(buffer
, consts
[i
]->value
[1].d
);
404 put_dword(buffer
, consts
[i
]->value
[2].d
);
405 put_dword(buffer
, consts
[i
]->value
[3].d
);
410 static void write_constF(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
411 write_const(shader
->constF
, shader
->num_cf
, D3DSIO_DEF
, D3DSPR_CONST
, buffer
, len
);
414 /* This function looks for VS 1/2 registers mapping to VS 3 output registers */
415 static HRESULT
vs_find_builtin_varyings(struct bc_writer
*This
, const struct bwriter_shader
*shader
) {
417 DWORD usage
, usage_idx
, writemask
, regnum
;
419 for(i
= 0; i
< shader
->num_outputs
; i
++) {
420 if(!shader
->outputs
[i
].builtin
) continue;
422 usage
= shader
->outputs
[i
].usage
;
423 usage_idx
= shader
->outputs
[i
].usage_idx
;
424 writemask
= shader
->outputs
[i
].writemask
;
425 regnum
= shader
->outputs
[i
].regnum
;
428 case BWRITERDECLUSAGE_POSITION
:
429 case BWRITERDECLUSAGE_POSITIONT
:
431 WARN("dcl_position%u not supported in sm 1/2 shaders\n", usage_idx
);
434 TRACE("o%u is oPos\n", regnum
);
435 This
->oPos_regnum
= regnum
;
438 case BWRITERDECLUSAGE_COLOR
:
440 WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx
);
443 if(writemask
!= BWRITERSP_WRITEMASK_ALL
) {
444 WARN("Only WRITEMASK_ALL is supported on color in sm 1/2\n");
447 TRACE("o%u is oD%u\n", regnum
, usage_idx
);
448 This
->oD_regnum
[usage_idx
] = regnum
;
451 case BWRITERDECLUSAGE_TEXCOORD
:
453 WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx
);
456 if(writemask
!= (BWRITERSP_WRITEMASK_0
) &&
457 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
) &&
458 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
| BWRITERSP_WRITEMASK_2
) &&
459 writemask
!= (BWRITERSP_WRITEMASK_ALL
)) {
460 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
463 TRACE("o%u is oT%u\n", regnum
, usage_idx
);
464 This
->oT_regnum
[usage_idx
] = regnum
;
467 case BWRITERDECLUSAGE_PSIZE
:
469 WARN("dcl_psize%u not supported in sm 1/2 shaders\n", usage_idx
);
472 TRACE("o%u writemask 0x%08x is oPts\n", regnum
, writemask
);
473 This
->oPts_regnum
= regnum
;
474 This
->oPts_mask
= writemask
;
477 case BWRITERDECLUSAGE_FOG
:
479 WARN("dcl_fog%u not supported in sm 1 shaders\n", usage_idx
);
482 if(writemask
!= BWRITERSP_WRITEMASK_0
&& writemask
!= BWRITERSP_WRITEMASK_1
&&
483 writemask
!= BWRITERSP_WRITEMASK_2
&& writemask
!= BWRITERSP_WRITEMASK_3
) {
484 WARN("Unsupported fog writemask\n");
487 TRACE("o%u writemask 0x%08x is oFog\n", regnum
, writemask
);
488 This
->oFog_regnum
= regnum
;
489 This
->oFog_mask
= writemask
;
493 WARN("Varying type %u is not supported in shader model 1.x\n", usage
);
501 static void vs_1_x_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
504 if(shader
->num_ci
|| shader
->num_cb
) {
505 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
506 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
507 This
->state
= E_INVALIDARG
;
511 hr
= vs_find_builtin_varyings(This
, shader
);
517 /* Declare the shader type and version */
518 put_dword(buffer
, This
->version
);
520 write_declarations(This
, buffer
, FALSE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
521 write_constF(shader
, buffer
, FALSE
);
525 static HRESULT
find_ps_builtin_semantics(struct bc_writer
*This
,
526 const struct bwriter_shader
*shader
,
529 DWORD usage
, usage_idx
, writemask
, regnum
;
531 This
->v_regnum
[0] = -1; This
->v_regnum
[1] = -1;
532 for(i
= 0; i
< 8; i
++) This
->t_regnum
[i
] = -1;
534 for(i
= 0; i
< shader
->num_inputs
; i
++) {
535 if(!shader
->inputs
[i
].builtin
) continue;
537 usage
= shader
->inputs
[i
].usage
;
538 usage_idx
= shader
->inputs
[i
].usage_idx
;
539 writemask
= shader
->inputs
[i
].writemask
;
540 regnum
= shader
->inputs
[i
].regnum
;
543 case BWRITERDECLUSAGE_COLOR
:
545 WARN("dcl_color%u not supported in sm 1 shaders\n", usage_idx
);
548 if(writemask
!= BWRITERSP_WRITEMASK_ALL
) {
549 WARN("Only WRITEMASK_ALL is supported on color in sm 1\n");
552 TRACE("v%u is v%u\n", regnum
, usage_idx
);
553 This
->v_regnum
[usage_idx
] = regnum
;
556 case BWRITERDECLUSAGE_TEXCOORD
:
557 if(usage_idx
> texcoords
) {
558 WARN("dcl_texcoord%u not supported in this shader version\n", usage_idx
);
561 if(writemask
!= (BWRITERSP_WRITEMASK_0
) &&
562 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
) &&
563 writemask
!= (BWRITERSP_WRITEMASK_0
| BWRITERSP_WRITEMASK_1
| BWRITERSP_WRITEMASK_2
) &&
564 writemask
!= (BWRITERSP_WRITEMASK_ALL
)) {
565 WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
567 writemask
= BWRITERSP_WRITEMASK_ALL
;
569 TRACE("v%u is t%u\n", regnum
, usage_idx
);
570 This
->t_regnum
[usage_idx
] = regnum
;
574 WARN("Varying type %u is not supported in shader model 1.x\n", usage
);
582 static void ps_1_x_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
585 /* First check the constants and varyings, and complain if unsupported things are used */
586 if(shader
->num_ci
|| shader
->num_cb
) {
587 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
588 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
589 This
->state
= E_INVALIDARG
;
593 hr
= find_ps_builtin_semantics(This
, shader
, 4);
599 /* Declare the shader type and version */
600 put_dword(buffer
, This
->version
);
601 write_constF(shader
, buffer
, TRUE
);
604 static void ps_1_4_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
607 /* First check the constants and varyings, and complain if unsupported things are used */
608 if(shader
->num_ci
|| shader
->num_cb
) {
609 WARN("Int and bool constants are not supported in shader model 1 shaders\n");
610 WARN("Got %u int and %u boolean constants\n", shader
->num_ci
, shader
->num_cb
);
611 This
->state
= E_INVALIDARG
;
614 hr
= find_ps_builtin_semantics(This
, shader
, 6);
620 /* Declare the shader type and version */
621 put_dword(buffer
, This
->version
);
622 write_constF(shader
, buffer
, TRUE
);
625 static void end(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
626 put_dword(buffer
, D3DSIO_END
);
629 static DWORD
map_vs_output(struct bc_writer
*This
, DWORD regnum
, DWORD mask
, DWORD
*has_components
) {
633 *has_components
= TRUE
;
634 if(regnum
== This
->oPos_regnum
) {
635 token
|= (D3DSPR_RASTOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
636 token
|= D3DSRO_POSITION
& D3DSP_REGNUM_MASK
; /* No shift */
639 if(regnum
== This
->oFog_regnum
&& mask
== This
->oFog_mask
) {
640 token
|= (D3DSPR_RASTOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
641 token
|= D3DSRO_FOG
& D3DSP_REGNUM_MASK
; /* No shift */
642 token
|= D3DSP_WRITEMASK_ALL
;
643 *has_components
= FALSE
;
646 if(regnum
== This
->oPts_regnum
&& mask
== This
->oPts_mask
) {
647 token
|= (D3DSPR_RASTOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
648 token
|= D3DSRO_POINT_SIZE
& D3DSP_REGNUM_MASK
; /* No shift */
649 token
|= D3DSP_WRITEMASK_ALL
;
650 *has_components
= FALSE
;
653 for(i
= 0; i
< 2; i
++) {
654 if(regnum
== This
->oD_regnum
[i
]) {
655 token
|= (D3DSPR_ATTROUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
656 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
660 for(i
= 0; i
< 8; i
++) {
661 if(regnum
== This
->oT_regnum
[i
]) {
662 token
|= (D3DSPR_TEXCRDOUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
663 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
668 /* The varying must be undeclared - if an unsupported varying was declared,
669 * the vs_find_builtin_varyings function would have caught it and this code
671 WARN("Undeclared varying %u\n", regnum
);
672 This
->state
= E_INVALIDARG
;
676 static void vs_12_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
677 struct bytecode_buffer
*buffer
,
678 DWORD shift
, DWORD mod
) {
679 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
683 WARN("Relative addressing not supported for destination registers\n");
684 This
->state
= E_INVALIDARG
;
689 case BWRITERSPR_OUTPUT
:
690 token
|= map_vs_output(This
, reg
->regnum
, reg
->u
.writemask
, &has_wmask
);
693 case BWRITERSPR_RASTOUT
:
694 case BWRITERSPR_ATTROUT
:
695 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
696 * but are unexpected. If we hit this path it might be due to an error.
698 FIXME("Unexpected register type %u\n", reg
->type
);
700 case BWRITERSPR_INPUT
:
701 case BWRITERSPR_TEMP
:
702 case BWRITERSPR_CONST
:
703 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
704 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
708 case BWRITERSPR_ADDR
:
709 if(reg
->regnum
!= 0) {
710 WARN("Only a0 exists\n");
711 This
->state
= E_INVALIDARG
;
714 token
|= (D3DSPR_ADDR
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
715 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
719 case BWRITERSPR_PREDICATE
:
720 if(This
->version
!= BWRITERVS_VERSION(2, 1)){
721 WARN("Predicate register is allowed only in vs_2_x\n");
722 This
->state
= E_INVALIDARG
;
725 if(reg
->regnum
!= 0) {
726 WARN("Only predicate register p0 exists\n");
727 This
->state
= E_INVALIDARG
;
730 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
731 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
732 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
737 WARN("Invalid register type for 1.x-2.x vertex shader\n");
738 This
->state
= E_INVALIDARG
;
742 /* strictly speaking there are no modifiers in vs_2_0 and vs_1_x, but they can be written
743 * into the bytecode and since the compiler doesn't do such checks write them
744 * (the checks are done by the undocumented shader validator)
746 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
747 token
|= d3d9_dstmod(mod
);
750 token
|= d3d9_writemask(reg
->u
.writemask
);
752 put_dword(buffer
, token
);
755 static void vs_1_x_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
756 struct bytecode_buffer
*buffer
) {
757 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
762 case BWRITERSPR_OUTPUT
:
763 /* Map the swizzle to a writemask, the format expected
766 switch(reg
->u
.swizzle
) {
767 case BWRITERVS_SWIZZLE_X
:
768 component
= BWRITERSP_WRITEMASK_0
;
770 case BWRITERVS_SWIZZLE_Y
:
771 component
= BWRITERSP_WRITEMASK_1
;
773 case BWRITERVS_SWIZZLE_Z
:
774 component
= BWRITERSP_WRITEMASK_2
;
776 case BWRITERVS_SWIZZLE_W
:
777 component
= BWRITERSP_WRITEMASK_3
;
782 token
|= map_vs_output(This
, reg
->regnum
, component
, &has_swizzle
);
785 case BWRITERSPR_RASTOUT
:
786 case BWRITERSPR_ATTROUT
:
787 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
788 * but are unexpected. If we hit this path it might be due to an error.
790 FIXME("Unexpected register type %u\n", reg
->type
);
792 case BWRITERSPR_INPUT
:
793 case BWRITERSPR_TEMP
:
794 case BWRITERSPR_CONST
:
795 case BWRITERSPR_ADDR
:
796 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
797 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
799 if(reg
->rel_reg
->type
!= BWRITERSPR_ADDR
||
800 reg
->rel_reg
->regnum
!= 0 ||
801 reg
->rel_reg
->u
.swizzle
!= BWRITERVS_SWIZZLE_X
) {
802 WARN("Relative addressing in vs_1_x is only allowed with a0.x\n");
803 This
->state
= E_INVALIDARG
;
806 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
811 WARN("Invalid register type for 1.x vshader\n");
812 This
->state
= E_INVALIDARG
;
816 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
818 token
|= d3d9_srcmod(reg
->srcmod
);
819 put_dword(buffer
, token
);
822 static void write_srcregs(struct bc_writer
*This
, const struct instruction
*instr
,
823 struct bytecode_buffer
*buffer
){
825 if(instr
->has_predicate
){
826 This
->funcs
->srcreg(This
, &instr
->predicate
, buffer
);
828 for(i
= 0; i
< instr
->num_srcs
; i
++){
829 This
->funcs
->srcreg(This
, &instr
->src
[i
], buffer
);
833 static DWORD
map_ps13_temp(struct bc_writer
*This
, const struct shader_reg
*reg
) {
835 if(reg
->regnum
== T0_REG
) {
836 token
|= (D3DSPR_TEXTURE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
837 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
838 } else if(reg
->regnum
== T1_REG
) {
839 token
|= (D3DSPR_TEXTURE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
840 token
|= 1 & D3DSP_REGNUM_MASK
; /* No shift */
841 } else if(reg
->regnum
== T2_REG
) {
842 token
|= (D3DSPR_TEXTURE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
843 token
|= 2 & D3DSP_REGNUM_MASK
; /* No shift */
844 } else if(reg
->regnum
== T3_REG
) {
845 token
|= (D3DSPR_TEXTURE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
846 token
|= 3 & D3DSP_REGNUM_MASK
; /* No shift */
848 token
|= (D3DSPR_TEMP
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
849 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
854 static DWORD
map_ps_input(struct bc_writer
*This
,
855 const struct shader_reg
*reg
) {
857 /* Map color interpolators */
858 for(i
= 0; i
< 2; i
++) {
859 if(reg
->regnum
== This
->v_regnum
[i
]) {
860 token
|= (D3DSPR_INPUT
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
861 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
865 for(i
= 0; i
< 8; i
++) {
866 if(reg
->regnum
== This
->t_regnum
[i
]) {
867 token
|= (D3DSPR_TEXTURE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
868 token
|= i
& D3DSP_REGNUM_MASK
; /* No shift */
873 WARN("Invalid ps 1/2 varying\n");
874 This
->state
= E_INVALIDARG
;
878 static void ps_1_0123_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
879 struct bytecode_buffer
*buffer
) {
880 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
882 WARN("Relative addressing not supported in <= ps_3_0\n");
883 This
->state
= E_INVALIDARG
;
888 case BWRITERSPR_INPUT
:
889 token
|= map_ps_input(This
, reg
);
892 /* Take care about the texture temporaries. There's a problem: They aren't
893 * declared anywhere, so we can only hardcode the values that are used
894 * to map ps_1_3 shaders to the common shader structure
896 case BWRITERSPR_TEMP
:
897 token
|= map_ps13_temp(This
, reg
);
900 case BWRITERSPR_CONST
: /* Can be mapped 1:1 */
901 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
902 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
906 WARN("Invalid register type for <= ps_1_3 shader\n");
907 This
->state
= E_INVALIDARG
;
911 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
913 if(reg
->srcmod
== BWRITERSPSM_DZ
|| reg
->srcmod
== BWRITERSPSM_DW
||
914 reg
->srcmod
== BWRITERSPSM_ABS
|| reg
->srcmod
== BWRITERSPSM_ABSNEG
||
915 reg
->srcmod
== BWRITERSPSM_NOT
) {
916 WARN("Invalid source modifier %u for <= ps_1_3\n", reg
->srcmod
);
917 This
->state
= E_INVALIDARG
;
920 token
|= d3d9_srcmod(reg
->srcmod
);
921 put_dword(buffer
, token
);
924 static void ps_1_0123_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
925 struct bytecode_buffer
*buffer
,
926 DWORD shift
, DWORD mod
) {
927 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
930 WARN("Relative addressing not supported for destination registers\n");
931 This
->state
= E_INVALIDARG
;
936 case BWRITERSPR_TEMP
:
937 token
|= map_ps13_temp(This
, reg
);
940 /* texkill uses the input register as a destination parameter */
941 case BWRITERSPR_INPUT
:
942 token
|= map_ps_input(This
, reg
);
946 WARN("Invalid dest register type for 1.x pshader\n");
947 This
->state
= E_INVALIDARG
;
951 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
952 token
|= d3d9_dstmod(mod
);
954 token
|= d3d9_writemask(reg
->u
.writemask
);
955 put_dword(buffer
, token
);
958 /* The length of an instruction consists of the destination register (if any),
959 * the number of source registers, the number of address registers used for
960 * indirect addressing, and optionally the predicate register
962 static DWORD
instrlen(const struct instruction
*instr
, unsigned int srcs
, unsigned int dsts
) {
964 DWORD ret
= srcs
+ dsts
+ (instr
->has_predicate
? 1 : 0);
967 if(instr
->dst
.rel_reg
) ret
++;
969 for(i
= 0; i
< srcs
; i
++) {
970 if(instr
->src
[i
].rel_reg
) ret
++;
975 static void sm_1_x_opcode(struct bc_writer
*This
,
976 const struct instruction
*instr
,
977 DWORD token
, struct bytecode_buffer
*buffer
) {
978 /* In sm_1_x instruction length isn't encoded */
980 token
|= D3DSI_COISSUE
;
982 put_dword(buffer
, token
);
985 static void instr_handler(struct bc_writer
*This
,
986 const struct instruction
*instr
,
987 struct bytecode_buffer
*buffer
) {
988 DWORD token
= d3d9_opcode(instr
->opcode
);
990 This
->funcs
->opcode(This
, instr
, token
, buffer
);
991 if(instr
->has_dst
) This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
992 write_srcregs(This
, instr
, buffer
);
995 static const struct instr_handler_table vs_1_x_handlers
[] = {
996 {BWRITERSIO_ADD
, instr_handler
},
997 {BWRITERSIO_NOP
, instr_handler
},
998 {BWRITERSIO_MOV
, instr_handler
},
999 {BWRITERSIO_SUB
, instr_handler
},
1000 {BWRITERSIO_MAD
, instr_handler
},
1001 {BWRITERSIO_MUL
, instr_handler
},
1002 {BWRITERSIO_RCP
, instr_handler
},
1003 {BWRITERSIO_RSQ
, instr_handler
},
1004 {BWRITERSIO_DP3
, instr_handler
},
1005 {BWRITERSIO_DP4
, instr_handler
},
1006 {BWRITERSIO_MIN
, instr_handler
},
1007 {BWRITERSIO_MAX
, instr_handler
},
1008 {BWRITERSIO_SLT
, instr_handler
},
1009 {BWRITERSIO_SGE
, instr_handler
},
1010 {BWRITERSIO_EXP
, instr_handler
},
1011 {BWRITERSIO_LOG
, instr_handler
},
1012 {BWRITERSIO_EXPP
, instr_handler
},
1013 {BWRITERSIO_LOGP
, instr_handler
},
1014 {BWRITERSIO_DST
, instr_handler
},
1015 {BWRITERSIO_FRC
, instr_handler
},
1016 {BWRITERSIO_M4x4
, instr_handler
},
1017 {BWRITERSIO_M4x3
, instr_handler
},
1018 {BWRITERSIO_M3x4
, instr_handler
},
1019 {BWRITERSIO_M3x3
, instr_handler
},
1020 {BWRITERSIO_M3x2
, instr_handler
},
1021 {BWRITERSIO_LIT
, instr_handler
},
1023 {BWRITERSIO_END
, NULL
}, /* Sentinel value, it signals
1024 the end of the list */
1027 static const struct bytecode_backend vs_1_x_backend
= {
1036 static void instr_ps_1_0123_texld(struct bc_writer
*This
,
1037 const struct instruction
*instr
,
1038 struct bytecode_buffer
*buffer
) {
1040 struct shader_reg reg
;
1043 if(instr
->src
[1].type
!= BWRITERSPR_SAMPLER
||
1044 instr
->src
[1].regnum
> 3) {
1045 WARN("Unsupported sampler type %u regnum %u\n",
1046 instr
->src
[1].type
, instr
->src
[1].regnum
);
1047 This
->state
= E_INVALIDARG
;
1049 } else if(instr
->dst
.type
!= BWRITERSPR_TEMP
) {
1050 WARN("Can only sample into a temp register\n");
1051 This
->state
= E_INVALIDARG
;
1055 idx
= instr
->src
[1].regnum
;
1056 if((idx
== 0 && instr
->dst
.regnum
!= T0_REG
) ||
1057 (idx
== 1 && instr
->dst
.regnum
!= T1_REG
) ||
1058 (idx
== 2 && instr
->dst
.regnum
!= T2_REG
) ||
1059 (idx
== 3 && instr
->dst
.regnum
!= T3_REG
)) {
1060 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_x\n",
1061 idx
, instr
->dst
.regnum
);
1062 This
->state
= E_INVALIDARG
;
1065 if(instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1066 /* A simple non-dependent read tex instruction */
1067 if(instr
->src
[0].regnum
!= This
->t_regnum
[idx
]) {
1068 WARN("Cannot sample from s%u with texture address data from interpolator %u\n",
1069 idx
, instr
->src
[0].regnum
);
1070 This
->state
= E_INVALIDARG
;
1073 This
->funcs
->opcode(This
, instr
, D3DSIO_TEX
& D3DSI_OPCODE_MASK
, buffer
);
1075 /* map the temp dstreg to the ps_1_3 texture temporary register */
1076 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1077 } else if(instr
->src
[0].type
== BWRITERSPR_TEMP
) {
1079 swizzlemask
= (3 << BWRITERVS_SWIZZLE_SHIFT
) |
1080 (3 << (BWRITERVS_SWIZZLE_SHIFT
+ 2)) |
1081 (3 << (BWRITERVS_SWIZZLE_SHIFT
+ 4));
1082 if((instr
->src
[0].u
.swizzle
& swizzlemask
) == (BWRITERVS_X_X
| BWRITERVS_Y_Y
| BWRITERVS_Z_Z
)) {
1083 TRACE("writing texreg2rgb\n");
1084 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2RGB
& D3DSI_OPCODE_MASK
, buffer
);
1085 } else if(instr
->src
[0].u
.swizzle
== (BWRITERVS_X_W
| BWRITERVS_Y_X
| BWRITERVS_Z_X
| BWRITERVS_W_X
)) {
1086 TRACE("writing texreg2ar\n");
1087 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2AR
& D3DSI_OPCODE_MASK
, buffer
);
1088 } else if(instr
->src
[0].u
.swizzle
== (BWRITERVS_X_Y
| BWRITERVS_Y_Z
| BWRITERVS_Z_Z
| BWRITERVS_W_Z
)) {
1089 TRACE("writing texreg2gb\n");
1090 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXREG2GB
& D3DSI_OPCODE_MASK
, buffer
);
1092 WARN("Unsupported src addr swizzle in dependent texld: 0x%08x\n", instr
->src
[0].u
.swizzle
);
1093 This
->state
= E_INVALIDARG
;
1097 /* Dst and src reg can be mapped normally. Both registers are temporary registers in the
1098 * source shader and have to be mapped to the temporary form of the texture registers. However,
1099 * the src reg doesn't have a swizzle
1101 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1102 reg
= instr
->src
[0];
1103 reg
.u
.swizzle
= BWRITERVS_NOSWIZZLE
;
1104 This
->funcs
->srcreg(This
, ®
, buffer
);
1106 WARN("Invalid address data source register\n");
1107 This
->state
= E_INVALIDARG
;
1112 static void instr_ps_1_0123_mov(struct bc_writer
*This
,
1113 const struct instruction
*instr
,
1114 struct bytecode_buffer
*buffer
) {
1115 DWORD token
= D3DSIO_MOV
& D3DSI_OPCODE_MASK
;
1117 if(instr
->dst
.type
== BWRITERSPR_TEMP
&& instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1118 if((instr
->dst
.regnum
== T0_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[0]) ||
1119 (instr
->dst
.regnum
== T1_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[1]) ||
1120 (instr
->dst
.regnum
== T2_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[2]) ||
1121 (instr
->dst
.regnum
== T3_REG
&& instr
->src
[0].regnum
== This
->t_regnum
[3])) {
1122 if(instr
->dstmod
& BWRITERSPDM_SATURATE
) {
1123 This
->funcs
->opcode(This
, instr
, D3DSIO_TEXCOORD
& D3DSI_OPCODE_MASK
, buffer
);
1124 /* Remove the SATURATE flag, it's implicit to the instruction */
1125 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
& (~BWRITERSPDM_SATURATE
));
1128 WARN("A varying -> temp copy is only supported with the SATURATE modifier in <=ps_1_3\n");
1129 This
->state
= E_INVALIDARG
;
1132 } else if(instr
->src
[0].regnum
== This
->v_regnum
[0] ||
1133 instr
->src
[0].regnum
== This
->v_regnum
[1]) {
1134 /* Handled by the normal mov below. Just drop out of the if condition */
1136 WARN("Unsupported varying -> temp mov in <= ps_1_3\n");
1137 This
->state
= E_INVALIDARG
;
1142 This
->funcs
->opcode(This
, instr
, token
, buffer
);
1143 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1144 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1147 static const struct instr_handler_table ps_1_0123_handlers
[] = {
1148 {BWRITERSIO_ADD
, instr_handler
},
1149 {BWRITERSIO_NOP
, instr_handler
},
1150 {BWRITERSIO_MOV
, instr_ps_1_0123_mov
},
1151 {BWRITERSIO_SUB
, instr_handler
},
1152 {BWRITERSIO_MAD
, instr_handler
},
1153 {BWRITERSIO_MUL
, instr_handler
},
1154 {BWRITERSIO_DP3
, instr_handler
},
1155 {BWRITERSIO_DP4
, instr_handler
},
1156 {BWRITERSIO_LRP
, instr_handler
},
1158 /* pshader instructions */
1159 {BWRITERSIO_CND
, instr_handler
},
1160 {BWRITERSIO_CMP
, instr_handler
},
1161 {BWRITERSIO_TEXKILL
, instr_handler
},
1162 {BWRITERSIO_TEX
, instr_ps_1_0123_texld
},
1163 {BWRITERSIO_TEXBEM
, instr_handler
},
1164 {BWRITERSIO_TEXBEML
, instr_handler
},
1165 {BWRITERSIO_TEXM3x2PAD
, instr_handler
},
1166 {BWRITERSIO_TEXM3x3PAD
, instr_handler
},
1167 {BWRITERSIO_TEXM3x3SPEC
, instr_handler
},
1168 {BWRITERSIO_TEXM3x3VSPEC
, instr_handler
},
1169 {BWRITERSIO_TEXM3x3TEX
, instr_handler
},
1170 {BWRITERSIO_TEXM3x3
, instr_handler
},
1171 {BWRITERSIO_TEXM3x2DEPTH
, instr_handler
},
1172 {BWRITERSIO_TEXM3x2TEX
, instr_handler
},
1173 {BWRITERSIO_TEXDP3
, instr_handler
},
1174 {BWRITERSIO_TEXDP3TEX
, instr_handler
},
1175 {BWRITERSIO_END
, NULL
},
1178 static const struct bytecode_backend ps_1_0123_backend
= {
1187 static void ps_1_4_srcreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1188 struct bytecode_buffer
*buffer
) {
1189 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1191 WARN("Relative addressing not supported in <= ps_3_0\n");
1192 This
->state
= E_INVALIDARG
;
1197 case BWRITERSPR_INPUT
:
1198 token
|= map_ps_input(This
, reg
);
1201 /* Can be mapped 1:1 */
1202 case BWRITERSPR_TEMP
:
1203 case BWRITERSPR_CONST
:
1204 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1205 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1209 WARN("Invalid register type for ps_1_4 shader\n");
1210 This
->state
= E_INVALIDARG
;
1214 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1216 if(reg
->srcmod
== BWRITERSPSM_ABS
|| reg
->srcmod
== BWRITERSPSM_ABSNEG
||
1217 reg
->srcmod
== BWRITERSPSM_NOT
) {
1218 WARN("Invalid source modifier %u for ps_1_4\n", reg
->srcmod
);
1219 This
->state
= E_INVALIDARG
;
1222 token
|= d3d9_srcmod(reg
->srcmod
);
1223 put_dword(buffer
, token
);
1226 static void ps_1_4_dstreg(struct bc_writer
*This
, const struct shader_reg
*reg
,
1227 struct bytecode_buffer
*buffer
,
1228 DWORD shift
, DWORD mod
) {
1229 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1232 WARN("Relative addressing not supported for destination registers\n");
1233 This
->state
= E_INVALIDARG
;
1238 case BWRITERSPR_TEMP
: /* 1:1 mapping */
1239 token
|= (reg
->type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1240 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1244 case BWRITERSPR_INPUT
:
1245 token
|= map_ps_input(This
, reg
);
1249 WARN("Invalid dest register type for 1.x pshader\n");
1250 This
->state
= E_INVALIDARG
;
1254 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1255 token
|= d3d9_dstmod(mod
);
1257 token
|= d3d9_writemask(reg
->u
.writemask
);
1258 put_dword(buffer
, token
);
1261 static void instr_ps_1_4_mov(struct bc_writer
*This
,
1262 const struct instruction
*instr
,
1263 struct bytecode_buffer
*buffer
) {
1264 DWORD token
= D3DSIO_MOV
& D3DSI_OPCODE_MASK
;
1266 if(instr
->dst
.type
== BWRITERSPR_TEMP
&& instr
->src
[0].type
== BWRITERSPR_INPUT
) {
1267 if(instr
->src
[0].regnum
== This
->t_regnum
[0] ||
1268 instr
->src
[0].regnum
== This
->t_regnum
[1] ||
1269 instr
->src
[0].regnum
== This
->t_regnum
[2] ||
1270 instr
->src
[0].regnum
== This
->t_regnum
[3] ||
1271 instr
->src
[0].regnum
== This
->t_regnum
[4] ||
1272 instr
->src
[0].regnum
== This
->t_regnum
[5]) {
1273 /* Similar to a regular mov, but a different opcode */
1274 token
= D3DSIO_TEXCOORD
& D3DSI_OPCODE_MASK
;
1275 } else if(instr
->src
[0].regnum
== This
->v_regnum
[0] ||
1276 instr
->src
[0].regnum
== This
->v_regnum
[1]) {
1277 /* Handled by the normal mov below. Just drop out of the if condition */
1279 WARN("Unsupported varying -> temp mov in ps_1_4\n");
1280 This
->state
= E_INVALIDARG
;
1285 This
->funcs
->opcode(This
, instr
, token
, buffer
);
1286 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1287 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1290 static void instr_ps_1_4_texld(struct bc_writer
*This
,
1291 const struct instruction
*instr
,
1292 struct bytecode_buffer
*buffer
) {
1293 if(instr
->src
[1].type
!= BWRITERSPR_SAMPLER
||
1294 instr
->src
[1].regnum
> 5) {
1295 WARN("Unsupported sampler type %u regnum %u\n",
1296 instr
->src
[1].type
, instr
->src
[1].regnum
);
1297 This
->state
= E_INVALIDARG
;
1299 } else if(instr
->dst
.type
!= BWRITERSPR_TEMP
) {
1300 WARN("Can only sample into a temp register\n");
1301 This
->state
= E_INVALIDARG
;
1305 if(instr
->src
[1].regnum
!= instr
->dst
.regnum
) {
1306 WARN("Sampling from sampler s%u to register r%u is not possible in ps_1_4\n",
1307 instr
->src
[1].regnum
, instr
->dst
.regnum
);
1308 This
->state
= E_INVALIDARG
;
1312 This
->funcs
->opcode(This
, instr
, D3DSIO_TEX
& D3DSI_OPCODE_MASK
, buffer
);
1313 This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
1314 This
->funcs
->srcreg(This
, &instr
->src
[0], buffer
);
1317 static const struct instr_handler_table ps_1_4_handlers
[] = {
1318 {BWRITERSIO_ADD
, instr_handler
},
1319 {BWRITERSIO_NOP
, instr_handler
},
1320 {BWRITERSIO_MOV
, instr_ps_1_4_mov
},
1321 {BWRITERSIO_SUB
, instr_handler
},
1322 {BWRITERSIO_MAD
, instr_handler
},
1323 {BWRITERSIO_MUL
, instr_handler
},
1324 {BWRITERSIO_DP3
, instr_handler
},
1325 {BWRITERSIO_DP4
, instr_handler
},
1326 {BWRITERSIO_LRP
, instr_handler
},
1328 /* pshader instructions */
1329 {BWRITERSIO_CND
, instr_handler
},
1330 {BWRITERSIO_CMP
, instr_handler
},
1331 {BWRITERSIO_TEXKILL
, instr_handler
},
1332 {BWRITERSIO_TEX
, instr_ps_1_4_texld
},
1333 {BWRITERSIO_TEXDEPTH
, instr_handler
},
1334 {BWRITERSIO_BEM
, instr_handler
},
1336 {BWRITERSIO_PHASE
, instr_handler
},
1337 {BWRITERSIO_END
, NULL
},
1340 static const struct bytecode_backend ps_1_4_backend
= {
1349 static void write_constB(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
1350 write_const(shader
->constB
, shader
->num_cb
, D3DSIO_DEFB
, D3DSPR_CONSTBOOL
, buffer
, len
);
1353 static void write_constI(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
, BOOL len
) {
1354 write_const(shader
->constI
, shader
->num_ci
, D3DSIO_DEFI
, D3DSPR_CONSTINT
, buffer
, len
);
1357 static void vs_2_header(struct bc_writer
*This
,
1358 const struct bwriter_shader
*shader
,
1359 struct bytecode_buffer
*buffer
) {
1362 hr
= vs_find_builtin_varyings(This
, shader
);
1368 /* Declare the shader type and version */
1369 put_dword(buffer
, This
->version
);
1371 write_declarations(This
, buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
1372 write_constF(shader
, buffer
, TRUE
);
1373 write_constB(shader
, buffer
, TRUE
);
1374 write_constI(shader
, buffer
, TRUE
);
1378 static void vs_2_srcreg(struct bc_writer
*This
,
1379 const struct shader_reg
*reg
,
1380 struct bytecode_buffer
*buffer
) {
1381 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1387 case BWRITERSPR_OUTPUT
:
1388 /* Map the swizzle to a writemask, the format expected
1391 switch(reg
->u
.swizzle
) {
1392 case BWRITERVS_SWIZZLE_X
:
1393 component
= BWRITERSP_WRITEMASK_0
;
1395 case BWRITERVS_SWIZZLE_Y
:
1396 component
= BWRITERSP_WRITEMASK_1
;
1398 case BWRITERVS_SWIZZLE_Z
:
1399 component
= BWRITERSP_WRITEMASK_2
;
1401 case BWRITERVS_SWIZZLE_W
:
1402 component
= BWRITERSP_WRITEMASK_3
;
1407 token
|= map_vs_output(This
, reg
->regnum
, component
, &has_swizzle
);
1410 case BWRITERSPR_RASTOUT
:
1411 case BWRITERSPR_ATTROUT
:
1412 /* These registers are mapped to input and output regs. They can be encoded in the bytecode,
1413 * but are unexpected. If we hit this path it might be due to an error.
1415 FIXME("Unexpected register type %u\n", reg
->type
);
1417 case BWRITERSPR_INPUT
:
1418 case BWRITERSPR_TEMP
:
1419 case BWRITERSPR_CONST
:
1420 case BWRITERSPR_ADDR
:
1421 case BWRITERSPR_CONSTINT
:
1422 case BWRITERSPR_CONSTBOOL
:
1423 case BWRITERSPR_LABEL
:
1424 d3d9reg
= d3d9_register(reg
->type
);
1425 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1426 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1427 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1430 case BWRITERSPR_LOOP
:
1431 if(reg
->regnum
!= 0) {
1432 WARN("Only regnum 0 is supported for the loop index register in vs_2_0\n");
1433 This
->state
= E_INVALIDARG
;
1436 token
|= (D3DSPR_LOOP
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1437 token
|= (D3DSPR_LOOP
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1438 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
1441 case BWRITERSPR_PREDICATE
:
1442 if(This
->version
!= BWRITERVS_VERSION(2, 1)){
1443 WARN("Predicate register is allowed only in vs_2_x\n");
1444 This
->state
= E_INVALIDARG
;
1447 if(reg
->regnum
> 0) {
1448 WARN("Only predicate register 0 is supported\n");
1449 This
->state
= E_INVALIDARG
;
1452 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1453 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1454 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
1459 WARN("Invalid register type for 2.0 vshader\n");
1460 This
->state
= E_INVALIDARG
;
1464 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1466 token
|= d3d9_srcmod(reg
->srcmod
);
1469 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1471 put_dword(buffer
, token
);
1473 /* vs_2_0 and newer write the register containing the index explicitly in the
1476 if(token
& D3DVS_ADDRMODE_RELATIVE
)
1477 vs_2_srcreg(This
, reg
->rel_reg
, buffer
);
1480 static void sm_2_opcode(struct bc_writer
*This
,
1481 const struct instruction
*instr
,
1482 DWORD token
, struct bytecode_buffer
*buffer
) {
1483 /* From sm 2 onwards instruction length is encoded in the opcode field */
1484 int dsts
= instr
->has_dst
? 1 : 0;
1485 token
|= instrlen(instr
, instr
->num_srcs
, dsts
) << D3DSI_INSTLENGTH_SHIFT
;
1487 token
|= (d3d9_comparetype(instr
->comptype
) << 16) & (0xf << 16);
1488 if(instr
->has_predicate
)
1489 token
|= D3DSHADER_INSTRUCTION_PREDICATED
;
1490 put_dword(buffer
,token
);
1493 static const struct instr_handler_table vs_2_0_handlers
[] = {
1494 {BWRITERSIO_ADD
, instr_handler
},
1495 {BWRITERSIO_NOP
, instr_handler
},
1496 {BWRITERSIO_MOV
, instr_handler
},
1497 {BWRITERSIO_SUB
, instr_handler
},
1498 {BWRITERSIO_MAD
, instr_handler
},
1499 {BWRITERSIO_MUL
, instr_handler
},
1500 {BWRITERSIO_RCP
, instr_handler
},
1501 {BWRITERSIO_RSQ
, instr_handler
},
1502 {BWRITERSIO_DP3
, instr_handler
},
1503 {BWRITERSIO_DP4
, instr_handler
},
1504 {BWRITERSIO_MIN
, instr_handler
},
1505 {BWRITERSIO_MAX
, instr_handler
},
1506 {BWRITERSIO_SLT
, instr_handler
},
1507 {BWRITERSIO_SGE
, instr_handler
},
1508 {BWRITERSIO_ABS
, instr_handler
},
1509 {BWRITERSIO_EXP
, instr_handler
},
1510 {BWRITERSIO_LOG
, instr_handler
},
1511 {BWRITERSIO_EXPP
, instr_handler
},
1512 {BWRITERSIO_LOGP
, instr_handler
},
1513 {BWRITERSIO_DST
, instr_handler
},
1514 {BWRITERSIO_LRP
, instr_handler
},
1515 {BWRITERSIO_FRC
, instr_handler
},
1516 {BWRITERSIO_CRS
, instr_handler
},
1517 {BWRITERSIO_SGN
, instr_handler
},
1518 {BWRITERSIO_NRM
, instr_handler
},
1519 {BWRITERSIO_SINCOS
, instr_handler
},
1520 {BWRITERSIO_M4x4
, instr_handler
},
1521 {BWRITERSIO_M4x3
, instr_handler
},
1522 {BWRITERSIO_M3x4
, instr_handler
},
1523 {BWRITERSIO_M3x3
, instr_handler
},
1524 {BWRITERSIO_M3x2
, instr_handler
},
1525 {BWRITERSIO_LIT
, instr_handler
},
1526 {BWRITERSIO_POW
, instr_handler
},
1527 {BWRITERSIO_MOVA
, instr_handler
},
1529 {BWRITERSIO_CALL
, instr_handler
},
1530 {BWRITERSIO_CALLNZ
, instr_handler
},
1531 {BWRITERSIO_REP
, instr_handler
},
1532 {BWRITERSIO_ENDREP
, instr_handler
},
1533 {BWRITERSIO_IF
, instr_handler
},
1534 {BWRITERSIO_LABEL
, instr_handler
},
1535 {BWRITERSIO_ELSE
, instr_handler
},
1536 {BWRITERSIO_ENDIF
, instr_handler
},
1537 {BWRITERSIO_LOOP
, instr_handler
},
1538 {BWRITERSIO_RET
, instr_handler
},
1539 {BWRITERSIO_ENDLOOP
, instr_handler
},
1541 {BWRITERSIO_END
, NULL
},
1544 static const struct bytecode_backend vs_2_0_backend
= {
1553 static const struct instr_handler_table vs_2_x_handlers
[] = {
1554 {BWRITERSIO_ADD
, instr_handler
},
1555 {BWRITERSIO_NOP
, instr_handler
},
1556 {BWRITERSIO_MOV
, instr_handler
},
1557 {BWRITERSIO_SUB
, instr_handler
},
1558 {BWRITERSIO_MAD
, instr_handler
},
1559 {BWRITERSIO_MUL
, instr_handler
},
1560 {BWRITERSIO_RCP
, instr_handler
},
1561 {BWRITERSIO_RSQ
, instr_handler
},
1562 {BWRITERSIO_DP3
, instr_handler
},
1563 {BWRITERSIO_DP4
, instr_handler
},
1564 {BWRITERSIO_MIN
, instr_handler
},
1565 {BWRITERSIO_MAX
, instr_handler
},
1566 {BWRITERSIO_SLT
, instr_handler
},
1567 {BWRITERSIO_SGE
, instr_handler
},
1568 {BWRITERSIO_ABS
, instr_handler
},
1569 {BWRITERSIO_EXP
, instr_handler
},
1570 {BWRITERSIO_LOG
, instr_handler
},
1571 {BWRITERSIO_EXPP
, instr_handler
},
1572 {BWRITERSIO_LOGP
, instr_handler
},
1573 {BWRITERSIO_DST
, instr_handler
},
1574 {BWRITERSIO_LRP
, instr_handler
},
1575 {BWRITERSIO_FRC
, instr_handler
},
1576 {BWRITERSIO_CRS
, instr_handler
},
1577 {BWRITERSIO_SGN
, instr_handler
},
1578 {BWRITERSIO_NRM
, instr_handler
},
1579 {BWRITERSIO_SINCOS
, instr_handler
},
1580 {BWRITERSIO_M4x4
, instr_handler
},
1581 {BWRITERSIO_M4x3
, instr_handler
},
1582 {BWRITERSIO_M3x4
, instr_handler
},
1583 {BWRITERSIO_M3x3
, instr_handler
},
1584 {BWRITERSIO_M3x2
, instr_handler
},
1585 {BWRITERSIO_LIT
, instr_handler
},
1586 {BWRITERSIO_POW
, instr_handler
},
1587 {BWRITERSIO_MOVA
, instr_handler
},
1589 {BWRITERSIO_CALL
, instr_handler
},
1590 {BWRITERSIO_CALLNZ
, instr_handler
},
1591 {BWRITERSIO_REP
, instr_handler
},
1592 {BWRITERSIO_ENDREP
, instr_handler
},
1593 {BWRITERSIO_IF
, instr_handler
},
1594 {BWRITERSIO_LABEL
, instr_handler
},
1595 {BWRITERSIO_IFC
, instr_handler
},
1596 {BWRITERSIO_ELSE
, instr_handler
},
1597 {BWRITERSIO_ENDIF
, instr_handler
},
1598 {BWRITERSIO_BREAK
, instr_handler
},
1599 {BWRITERSIO_BREAKC
, instr_handler
},
1600 {BWRITERSIO_LOOP
, instr_handler
},
1601 {BWRITERSIO_RET
, instr_handler
},
1602 {BWRITERSIO_ENDLOOP
, instr_handler
},
1604 {BWRITERSIO_SETP
, instr_handler
},
1605 {BWRITERSIO_BREAKP
, instr_handler
},
1607 {BWRITERSIO_END
, NULL
},
1610 static const struct bytecode_backend vs_2_x_backend
= {
1619 static void write_samplers(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1621 DWORD instr_dcl
= D3DSIO_DCL
| (2 << D3DSI_INSTLENGTH_SHIFT
);
1623 const DWORD reg
= (1<<31) |
1624 ((D3DSPR_SAMPLER
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
) |
1625 ((D3DSPR_SAMPLER
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
) |
1626 D3DSP_WRITEMASK_ALL
;
1628 for(i
= 0; i
< shader
->num_samplers
; i
++) {
1629 /* Write the DCL instruction */
1630 put_dword(buffer
, instr_dcl
);
1632 /* Already shifted */
1633 token
|= (d3d9_sampler(shader
->samplers
[i
].type
)) & D3DSP_TEXTURETYPE_MASK
;
1634 put_dword(buffer
, token
);
1635 token
= reg
| (shader
->samplers
[i
].regnum
& D3DSP_REGNUM_MASK
);
1636 token
|= d3d9_dstmod(shader
->samplers
[i
].mod
);
1637 put_dword(buffer
, token
);
1641 static void ps_2_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1642 HRESULT hr
= find_ps_builtin_semantics(This
, shader
, 8);
1648 /* Declare the shader type and version */
1649 put_dword(buffer
, This
->version
);
1650 write_declarations(This
, buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
1651 write_samplers(shader
, buffer
);
1652 write_constF(shader
, buffer
, TRUE
);
1653 write_constB(shader
, buffer
, TRUE
);
1654 write_constI(shader
, buffer
, TRUE
);
1657 static void ps_2_srcreg(struct bc_writer
*This
,
1658 const struct shader_reg
*reg
,
1659 struct bytecode_buffer
*buffer
) {
1660 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1663 WARN("Relative addressing not supported in <= ps_3_0\n");
1664 This
->state
= E_INVALIDARG
;
1669 case BWRITERSPR_INPUT
:
1670 token
|= map_ps_input(This
, reg
);
1673 /* Can be mapped 1:1 */
1674 case BWRITERSPR_TEMP
:
1675 case BWRITERSPR_CONST
:
1676 case BWRITERSPR_COLOROUT
:
1677 case BWRITERSPR_CONSTBOOL
:
1678 case BWRITERSPR_CONSTINT
:
1679 case BWRITERSPR_SAMPLER
:
1680 case BWRITERSPR_LABEL
:
1681 case BWRITERSPR_DEPTHOUT
:
1682 d3d9reg
= d3d9_register(reg
->type
);
1683 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1684 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1685 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1688 case BWRITERSPR_PREDICATE
:
1689 if(This
->version
!= BWRITERPS_VERSION(2, 1)){
1690 WARN("Predicate register not supported in ps_2_0\n");
1691 This
->state
= E_INVALIDARG
;
1694 WARN("Predicate register with regnum %u not supported\n",
1696 This
->state
= E_INVALIDARG
;
1698 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1699 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1700 token
|= 0 & D3DSP_REGNUM_MASK
; /* No shift */
1704 WARN("Invalid register type for ps_2_0 shader\n");
1705 This
->state
= E_INVALIDARG
;
1709 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
; /* already shifted */
1711 token
|= d3d9_srcmod(reg
->srcmod
);
1712 put_dword(buffer
, token
);
1715 static void ps_2_0_dstreg(struct bc_writer
*This
,
1716 const struct shader_reg
*reg
,
1717 struct bytecode_buffer
*buffer
,
1718 DWORD shift
, DWORD mod
) {
1719 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1723 WARN("Relative addressing not supported for destination registers\n");
1724 This
->state
= E_INVALIDARG
;
1729 case BWRITERSPR_TEMP
: /* 1:1 mapping */
1730 case BWRITERSPR_COLOROUT
:
1731 case BWRITERSPR_DEPTHOUT
:
1732 d3d9reg
= d3d9_register(reg
->type
);
1733 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1734 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1735 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1738 case BWRITERSPR_PREDICATE
:
1739 if(This
->version
!= BWRITERPS_VERSION(2, 1)){
1740 WARN("Predicate register not supported in ps_2_0\n");
1741 This
->state
= E_INVALIDARG
;
1743 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1744 token
|= (D3DSPR_PREDICATE
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1745 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1748 /* texkill uses the input register as a destination parameter */
1749 case BWRITERSPR_INPUT
:
1750 token
|= map_ps_input(This
, reg
);
1754 WARN("Invalid dest register type for 2.x pshader\n");
1755 This
->state
= E_INVALIDARG
;
1759 token
|= (shift
<< D3DSP_DSTSHIFT_SHIFT
) & D3DSP_DSTSHIFT_MASK
;
1760 token
|= d3d9_dstmod(mod
);
1762 token
|= d3d9_writemask(reg
->u
.writemask
);
1763 put_dword(buffer
, token
);
1766 static const struct instr_handler_table ps_2_0_handlers
[] = {
1767 {BWRITERSIO_ADD
, instr_handler
},
1768 {BWRITERSIO_NOP
, instr_handler
},
1769 {BWRITERSIO_MOV
, instr_handler
},
1770 {BWRITERSIO_SUB
, instr_handler
},
1771 {BWRITERSIO_MAD
, instr_handler
},
1772 {BWRITERSIO_MUL
, instr_handler
},
1773 {BWRITERSIO_RCP
, instr_handler
},
1774 {BWRITERSIO_RSQ
, instr_handler
},
1775 {BWRITERSIO_DP3
, instr_handler
},
1776 {BWRITERSIO_DP4
, instr_handler
},
1777 {BWRITERSIO_MIN
, instr_handler
},
1778 {BWRITERSIO_MAX
, instr_handler
},
1779 {BWRITERSIO_ABS
, instr_handler
},
1780 {BWRITERSIO_EXP
, instr_handler
},
1781 {BWRITERSIO_LOG
, instr_handler
},
1782 {BWRITERSIO_EXPP
, instr_handler
},
1783 {BWRITERSIO_LOGP
, instr_handler
},
1784 {BWRITERSIO_LRP
, instr_handler
},
1785 {BWRITERSIO_FRC
, instr_handler
},
1786 {BWRITERSIO_CRS
, instr_handler
},
1787 {BWRITERSIO_NRM
, instr_handler
},
1788 {BWRITERSIO_SINCOS
, instr_handler
},
1789 {BWRITERSIO_M4x4
, instr_handler
},
1790 {BWRITERSIO_M4x3
, instr_handler
},
1791 {BWRITERSIO_M3x4
, instr_handler
},
1792 {BWRITERSIO_M3x3
, instr_handler
},
1793 {BWRITERSIO_M3x2
, instr_handler
},
1794 {BWRITERSIO_POW
, instr_handler
},
1795 {BWRITERSIO_DP2ADD
, instr_handler
},
1796 {BWRITERSIO_CMP
, instr_handler
},
1798 {BWRITERSIO_TEX
, instr_handler
},
1799 {BWRITERSIO_TEXLDP
, instr_handler
},
1800 {BWRITERSIO_TEXLDB
, instr_handler
},
1801 {BWRITERSIO_TEXKILL
, instr_handler
},
1803 {BWRITERSIO_END
, NULL
},
1806 static const struct bytecode_backend ps_2_0_backend
= {
1815 static const struct instr_handler_table ps_2_x_handlers
[] = {
1816 {BWRITERSIO_ADD
, instr_handler
},
1817 {BWRITERSIO_NOP
, instr_handler
},
1818 {BWRITERSIO_MOV
, instr_handler
},
1819 {BWRITERSIO_SUB
, instr_handler
},
1820 {BWRITERSIO_MAD
, instr_handler
},
1821 {BWRITERSIO_MUL
, instr_handler
},
1822 {BWRITERSIO_RCP
, instr_handler
},
1823 {BWRITERSIO_RSQ
, instr_handler
},
1824 {BWRITERSIO_DP3
, instr_handler
},
1825 {BWRITERSIO_DP4
, instr_handler
},
1826 {BWRITERSIO_MIN
, instr_handler
},
1827 {BWRITERSIO_MAX
, instr_handler
},
1828 {BWRITERSIO_ABS
, instr_handler
},
1829 {BWRITERSIO_EXP
, instr_handler
},
1830 {BWRITERSIO_LOG
, instr_handler
},
1831 {BWRITERSIO_EXPP
, instr_handler
},
1832 {BWRITERSIO_LOGP
, instr_handler
},
1833 {BWRITERSIO_LRP
, instr_handler
},
1834 {BWRITERSIO_FRC
, instr_handler
},
1835 {BWRITERSIO_CRS
, instr_handler
},
1836 {BWRITERSIO_NRM
, instr_handler
},
1837 {BWRITERSIO_SINCOS
, instr_handler
},
1838 {BWRITERSIO_M4x4
, instr_handler
},
1839 {BWRITERSIO_M4x3
, instr_handler
},
1840 {BWRITERSIO_M3x4
, instr_handler
},
1841 {BWRITERSIO_M3x3
, instr_handler
},
1842 {BWRITERSIO_M3x2
, instr_handler
},
1843 {BWRITERSIO_POW
, instr_handler
},
1844 {BWRITERSIO_DP2ADD
, instr_handler
},
1845 {BWRITERSIO_CMP
, instr_handler
},
1847 {BWRITERSIO_CALL
, instr_handler
},
1848 {BWRITERSIO_CALLNZ
, instr_handler
},
1849 {BWRITERSIO_REP
, instr_handler
},
1850 {BWRITERSIO_ENDREP
, instr_handler
},
1851 {BWRITERSIO_IF
, instr_handler
},
1852 {BWRITERSIO_LABEL
, instr_handler
},
1853 {BWRITERSIO_IFC
, instr_handler
},
1854 {BWRITERSIO_ELSE
, instr_handler
},
1855 {BWRITERSIO_ENDIF
, instr_handler
},
1856 {BWRITERSIO_BREAK
, instr_handler
},
1857 {BWRITERSIO_BREAKC
, instr_handler
},
1858 {BWRITERSIO_RET
, instr_handler
},
1860 {BWRITERSIO_TEX
, instr_handler
},
1861 {BWRITERSIO_TEXLDP
, instr_handler
},
1862 {BWRITERSIO_TEXLDB
, instr_handler
},
1863 {BWRITERSIO_TEXKILL
, instr_handler
},
1864 {BWRITERSIO_DSX
, instr_handler
},
1865 {BWRITERSIO_DSY
, instr_handler
},
1867 {BWRITERSIO_SETP
, instr_handler
},
1868 {BWRITERSIO_BREAKP
, instr_handler
},
1870 {BWRITERSIO_TEXLDD
, instr_handler
},
1872 {BWRITERSIO_END
, NULL
},
1875 static const struct bytecode_backend ps_2_x_backend
= {
1884 static void sm_3_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
1885 /* Declare the shader type and version */
1886 put_dword(buffer
, This
->version
);
1888 write_declarations(This
, buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, BWRITERSPR_INPUT
);
1889 write_declarations(This
, buffer
, TRUE
, shader
->outputs
, shader
->num_outputs
, BWRITERSPR_OUTPUT
);
1890 write_constF(shader
, buffer
, TRUE
);
1891 write_constB(shader
, buffer
, TRUE
);
1892 write_constI(shader
, buffer
, TRUE
);
1893 write_samplers(shader
, buffer
);
1897 static void sm_3_srcreg(struct bc_writer
*This
,
1898 const struct shader_reg
*reg
,
1899 struct bytecode_buffer
*buffer
) {
1900 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1903 d3d9reg
= d3d9_register(reg
->type
);
1904 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1905 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1906 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
;
1908 token
|= d3d9_swizzle(reg
->u
.swizzle
) & D3DVS_SWIZZLE_MASK
;
1909 token
|= d3d9_srcmod(reg
->srcmod
);
1912 if(reg
->type
== BWRITERSPR_CONST
&& This
->version
== BWRITERPS_VERSION(3, 0)) {
1913 WARN("c%u[...] is unsupported in ps_3_0\n", reg
->regnum
);
1914 This
->state
= E_INVALIDARG
;
1917 if(((reg
->rel_reg
->type
== BWRITERSPR_ADDR
&& This
->version
== BWRITERVS_VERSION(3, 0)) ||
1918 reg
->rel_reg
->type
== BWRITERSPR_LOOP
) &&
1919 reg
->rel_reg
->regnum
== 0) {
1920 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1922 WARN("Unsupported relative addressing register\n");
1923 This
->state
= E_INVALIDARG
;
1928 put_dword(buffer
, token
);
1930 /* vs_2_0 and newer write the register containing the index explicitly in the
1933 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
1934 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
1938 static void sm_3_dstreg(struct bc_writer
*This
,
1939 const struct shader_reg
*reg
,
1940 struct bytecode_buffer
*buffer
,
1941 DWORD shift
, DWORD mod
) {
1942 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
1946 if(This
->version
== BWRITERVS_VERSION(3, 0) &&
1947 reg
->type
== BWRITERSPR_OUTPUT
) {
1948 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
1950 WARN("Relative addressing not supported for this shader type or register type\n");
1951 This
->state
= E_INVALIDARG
;
1956 d3d9reg
= d3d9_register(reg
->type
);
1957 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
1958 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
1959 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
1961 token
|= d3d9_dstmod(mod
);
1963 token
|= d3d9_writemask(reg
->u
.writemask
);
1964 put_dword(buffer
, token
);
1966 /* vs_2_0 and newer write the register containing the index explicitly in the
1969 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
1970 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
1974 static const struct instr_handler_table vs_3_handlers
[] = {
1975 {BWRITERSIO_ADD
, instr_handler
},
1976 {BWRITERSIO_NOP
, instr_handler
},
1977 {BWRITERSIO_MOV
, instr_handler
},
1978 {BWRITERSIO_SUB
, instr_handler
},
1979 {BWRITERSIO_MAD
, instr_handler
},
1980 {BWRITERSIO_MUL
, instr_handler
},
1981 {BWRITERSIO_RCP
, instr_handler
},
1982 {BWRITERSIO_RSQ
, instr_handler
},
1983 {BWRITERSIO_DP3
, instr_handler
},
1984 {BWRITERSIO_DP4
, instr_handler
},
1985 {BWRITERSIO_MIN
, instr_handler
},
1986 {BWRITERSIO_MAX
, instr_handler
},
1987 {BWRITERSIO_SLT
, instr_handler
},
1988 {BWRITERSIO_SGE
, instr_handler
},
1989 {BWRITERSIO_ABS
, instr_handler
},
1990 {BWRITERSIO_EXP
, instr_handler
},
1991 {BWRITERSIO_LOG
, instr_handler
},
1992 {BWRITERSIO_EXPP
, instr_handler
},
1993 {BWRITERSIO_LOGP
, instr_handler
},
1994 {BWRITERSIO_DST
, instr_handler
},
1995 {BWRITERSIO_LRP
, instr_handler
},
1996 {BWRITERSIO_FRC
, instr_handler
},
1997 {BWRITERSIO_CRS
, instr_handler
},
1998 {BWRITERSIO_SGN
, instr_handler
},
1999 {BWRITERSIO_NRM
, instr_handler
},
2000 {BWRITERSIO_SINCOS
, instr_handler
},
2001 {BWRITERSIO_M4x4
, instr_handler
},
2002 {BWRITERSIO_M4x3
, instr_handler
},
2003 {BWRITERSIO_M3x4
, instr_handler
},
2004 {BWRITERSIO_M3x3
, instr_handler
},
2005 {BWRITERSIO_M3x2
, instr_handler
},
2006 {BWRITERSIO_LIT
, instr_handler
},
2007 {BWRITERSIO_POW
, instr_handler
},
2008 {BWRITERSIO_MOVA
, instr_handler
},
2010 {BWRITERSIO_CALL
, instr_handler
},
2011 {BWRITERSIO_CALLNZ
, instr_handler
},
2012 {BWRITERSIO_REP
, instr_handler
},
2013 {BWRITERSIO_ENDREP
, instr_handler
},
2014 {BWRITERSIO_IF
, instr_handler
},
2015 {BWRITERSIO_LABEL
, instr_handler
},
2016 {BWRITERSIO_IFC
, instr_handler
},
2017 {BWRITERSIO_ELSE
, instr_handler
},
2018 {BWRITERSIO_ENDIF
, instr_handler
},
2019 {BWRITERSIO_BREAK
, instr_handler
},
2020 {BWRITERSIO_BREAKC
, instr_handler
},
2021 {BWRITERSIO_LOOP
, instr_handler
},
2022 {BWRITERSIO_RET
, instr_handler
},
2023 {BWRITERSIO_ENDLOOP
, instr_handler
},
2025 {BWRITERSIO_SETP
, instr_handler
},
2026 {BWRITERSIO_BREAKP
, instr_handler
},
2027 {BWRITERSIO_TEXLDL
, instr_handler
},
2029 {BWRITERSIO_END
, NULL
},
2032 static const struct bytecode_backend vs_3_backend
= {
2041 static const struct instr_handler_table ps_3_handlers
[] = {
2042 {BWRITERSIO_ADD
, instr_handler
},
2043 {BWRITERSIO_NOP
, instr_handler
},
2044 {BWRITERSIO_MOV
, instr_handler
},
2045 {BWRITERSIO_SUB
, instr_handler
},
2046 {BWRITERSIO_MAD
, instr_handler
},
2047 {BWRITERSIO_MUL
, instr_handler
},
2048 {BWRITERSIO_RCP
, instr_handler
},
2049 {BWRITERSIO_RSQ
, instr_handler
},
2050 {BWRITERSIO_DP3
, instr_handler
},
2051 {BWRITERSIO_DP4
, instr_handler
},
2052 {BWRITERSIO_MIN
, instr_handler
},
2053 {BWRITERSIO_MAX
, instr_handler
},
2054 {BWRITERSIO_ABS
, instr_handler
},
2055 {BWRITERSIO_EXP
, instr_handler
},
2056 {BWRITERSIO_LOG
, instr_handler
},
2057 {BWRITERSIO_EXPP
, instr_handler
},
2058 {BWRITERSIO_LOGP
, instr_handler
},
2059 {BWRITERSIO_LRP
, instr_handler
},
2060 {BWRITERSIO_FRC
, instr_handler
},
2061 {BWRITERSIO_CRS
, instr_handler
},
2062 {BWRITERSIO_NRM
, instr_handler
},
2063 {BWRITERSIO_SINCOS
, instr_handler
},
2064 {BWRITERSIO_M4x4
, instr_handler
},
2065 {BWRITERSIO_M4x3
, instr_handler
},
2066 {BWRITERSIO_M3x4
, instr_handler
},
2067 {BWRITERSIO_M3x3
, instr_handler
},
2068 {BWRITERSIO_M3x2
, instr_handler
},
2069 {BWRITERSIO_POW
, instr_handler
},
2070 {BWRITERSIO_DP2ADD
, instr_handler
},
2071 {BWRITERSIO_CMP
, instr_handler
},
2073 {BWRITERSIO_CALL
, instr_handler
},
2074 {BWRITERSIO_CALLNZ
, instr_handler
},
2075 {BWRITERSIO_REP
, instr_handler
},
2076 {BWRITERSIO_ENDREP
, instr_handler
},
2077 {BWRITERSIO_IF
, instr_handler
},
2078 {BWRITERSIO_LABEL
, instr_handler
},
2079 {BWRITERSIO_IFC
, instr_handler
},
2080 {BWRITERSIO_ELSE
, instr_handler
},
2081 {BWRITERSIO_ENDIF
, instr_handler
},
2082 {BWRITERSIO_BREAK
, instr_handler
},
2083 {BWRITERSIO_BREAKC
, instr_handler
},
2084 {BWRITERSIO_LOOP
, instr_handler
},
2085 {BWRITERSIO_RET
, instr_handler
},
2086 {BWRITERSIO_ENDLOOP
, instr_handler
},
2088 {BWRITERSIO_SETP
, instr_handler
},
2089 {BWRITERSIO_BREAKP
, instr_handler
},
2090 {BWRITERSIO_TEXLDL
, instr_handler
},
2092 {BWRITERSIO_TEX
, instr_handler
},
2093 {BWRITERSIO_TEXLDP
, instr_handler
},
2094 {BWRITERSIO_TEXLDB
, instr_handler
},
2095 {BWRITERSIO_TEXKILL
, instr_handler
},
2096 {BWRITERSIO_DSX
, instr_handler
},
2097 {BWRITERSIO_DSY
, instr_handler
},
2098 {BWRITERSIO_TEXLDD
, instr_handler
},
2100 {BWRITERSIO_END
, NULL
},
2103 static const struct bytecode_backend ps_3_backend
= {
2112 static void init_vs10_dx9_writer(struct bc_writer
*writer
) {
2113 TRACE("Creating DirectX9 vertex shader 1.0 writer\n");
2114 writer
->funcs
= &vs_1_x_backend
;
2117 static void init_vs11_dx9_writer(struct bc_writer
*writer
) {
2118 TRACE("Creating DirectX9 vertex shader 1.1 writer\n");
2119 writer
->funcs
= &vs_1_x_backend
;
2122 static void init_vs20_dx9_writer(struct bc_writer
*writer
) {
2123 TRACE("Creating DirectX9 vertex shader 2.0 writer\n");
2124 writer
->funcs
= &vs_2_0_backend
;
2127 static void init_vs2x_dx9_writer(struct bc_writer
*writer
) {
2128 TRACE("Creating DirectX9 vertex shader 2.x writer\n");
2129 writer
->funcs
= &vs_2_x_backend
;
2132 static void init_vs30_dx9_writer(struct bc_writer
*writer
) {
2133 TRACE("Creating DirectX9 vertex shader 3.0 writer\n");
2134 writer
->funcs
= &vs_3_backend
;
2137 static void init_ps10_dx9_writer(struct bc_writer
*writer
) {
2138 TRACE("Creating DirectX9 pixel shader 1.0 writer\n");
2139 writer
->funcs
= &ps_1_0123_backend
;
2142 static void init_ps11_dx9_writer(struct bc_writer
*writer
) {
2143 TRACE("Creating DirectX9 pixel shader 1.1 writer\n");
2144 writer
->funcs
= &ps_1_0123_backend
;
2147 static void init_ps12_dx9_writer(struct bc_writer
*writer
) {
2148 TRACE("Creating DirectX9 pixel shader 1.2 writer\n");
2149 writer
->funcs
= &ps_1_0123_backend
;
2152 static void init_ps13_dx9_writer(struct bc_writer
*writer
) {
2153 TRACE("Creating DirectX9 pixel shader 1.3 writer\n");
2154 writer
->funcs
= &ps_1_0123_backend
;
2157 static void init_ps14_dx9_writer(struct bc_writer
*writer
) {
2158 TRACE("Creating DirectX9 pixel shader 1.4 writer\n");
2159 writer
->funcs
= &ps_1_4_backend
;
2162 static void init_ps20_dx9_writer(struct bc_writer
*writer
) {
2163 TRACE("Creating DirectX9 pixel shader 2.0 writer\n");
2164 writer
->funcs
= &ps_2_0_backend
;
2167 static void init_ps2x_dx9_writer(struct bc_writer
*writer
) {
2168 TRACE("Creating DirectX9 pixel shader 2.x writer\n");
2169 writer
->funcs
= &ps_2_x_backend
;
2172 static void init_ps30_dx9_writer(struct bc_writer
*writer
) {
2173 TRACE("Creating DirectX9 pixel shader 3.0 writer\n");
2174 writer
->funcs
= &ps_3_backend
;
2177 static struct bc_writer
*create_writer(DWORD version
, DWORD dxversion
) {
2178 struct bc_writer
*ret
= asm_alloc(sizeof(*ret
));
2181 WARN("Failed to allocate a bytecode writer instance\n");
2186 case BWRITERVS_VERSION(1, 0):
2187 if(dxversion
!= 9) {
2188 WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion
);
2191 init_vs10_dx9_writer(ret
);
2193 case BWRITERVS_VERSION(1, 1):
2194 if(dxversion
!= 9) {
2195 WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion
);
2198 init_vs11_dx9_writer(ret
);
2200 case BWRITERVS_VERSION(2, 0):
2201 if(dxversion
!= 9) {
2202 WARN("Unsupported dxversion for vertex shader 2.0 requested: %u\n", dxversion
);
2205 init_vs20_dx9_writer(ret
);
2207 case BWRITERVS_VERSION(2, 1):
2208 if(dxversion
!= 9) {
2209 WARN("Unsupported dxversion for vertex shader 2.x requested: %u\n", dxversion
);
2212 init_vs2x_dx9_writer(ret
);
2214 case BWRITERVS_VERSION(3, 0):
2215 if(dxversion
!= 9) {
2216 WARN("Unsupported dxversion for vertex shader 3.0 requested: %u\n", dxversion
);
2219 init_vs30_dx9_writer(ret
);
2222 case BWRITERPS_VERSION(1, 0):
2223 if(dxversion
!= 9) {
2224 WARN("Unsupported dxversion for pixel shader 1.0 requested: %u\n", dxversion
);
2227 init_ps10_dx9_writer(ret
);
2229 case BWRITERPS_VERSION(1, 1):
2230 if(dxversion
!= 9) {
2231 WARN("Unsupported dxversion for pixel shader 1.1 requested: %u\n", dxversion
);
2234 init_ps11_dx9_writer(ret
);
2236 case BWRITERPS_VERSION(1, 2):
2237 if(dxversion
!= 9) {
2238 WARN("Unsupported dxversion for pixel shader 1.2 requested: %u\n", dxversion
);
2241 init_ps12_dx9_writer(ret
);
2243 case BWRITERPS_VERSION(1, 3):
2244 if(dxversion
!= 9) {
2245 WARN("Unsupported dxversion for pixel shader 1.3 requested: %u\n", dxversion
);
2248 init_ps13_dx9_writer(ret
);
2250 case BWRITERPS_VERSION(1, 4):
2251 if(dxversion
!= 9) {
2252 WARN("Unsupported dxversion for pixel shader 1.4 requested: %u\n", dxversion
);
2255 init_ps14_dx9_writer(ret
);
2258 case BWRITERPS_VERSION(2, 0):
2259 if(dxversion
!= 9) {
2260 WARN("Unsupported dxversion for pixel shader 2.0 requested: %u\n", dxversion
);
2263 init_ps20_dx9_writer(ret
);
2266 case BWRITERPS_VERSION(2, 1):
2267 if(dxversion
!= 9) {
2268 WARN("Unsupported dxversion for pixel shader 2.x requested: %u\n", dxversion
);
2271 init_ps2x_dx9_writer(ret
);
2274 case BWRITERPS_VERSION(3, 0):
2275 if(dxversion
!= 9) {
2276 WARN("Unsupported dxversion for pixel shader 3.0 requested: %u\n", dxversion
);
2279 init_ps30_dx9_writer(ret
);
2283 WARN("Unexpected shader version requested: %08x\n", version
);
2286 ret
->version
= version
;
2294 static HRESULT
call_instr_handler(struct bc_writer
*writer
,
2295 const struct instruction
*instr
,
2296 struct bytecode_buffer
*buffer
) {
2299 while(writer
->funcs
->instructions
[i
].opcode
!= BWRITERSIO_END
) {
2300 if(instr
->opcode
== writer
->funcs
->instructions
[i
].opcode
) {
2301 if(!writer
->funcs
->instructions
[i
].func
) {
2302 WARN("Opcode %u not supported by this profile\n", instr
->opcode
);
2303 return E_INVALIDARG
;
2305 writer
->funcs
->instructions
[i
].func(writer
, instr
, buffer
);
2311 FIXME("Unhandled instruction %u - %s\n", instr
->opcode
,
2312 debug_print_opcode(instr
->opcode
));
2313 return E_INVALIDARG
;
2316 /* SlWriteBytecode (wineshader.@)
2318 * Writes shader version specific bytecode from the shader passed in.
2319 * The returned bytecode can be passed to the Direct3D runtime like
2320 * IDirect3DDevice9::Create*Shader.
2323 * shader: Shader to translate into bytecode
2324 * version: Shader version to generate(d3d version token)
2325 * dxversion: DirectX version the code targets
2326 * result: the resulting shader bytecode
2331 DWORD
SlWriteBytecode(const struct bwriter_shader
*shader
, int dxversion
, DWORD
**result
) {
2332 struct bc_writer
*writer
;
2333 struct bytecode_buffer
*buffer
= NULL
;
2338 ERR("NULL shader structure, aborting\n");
2341 writer
= create_writer(shader
->version
, dxversion
);
2345 WARN("Could not create a bytecode writer instance. Either unsupported version\n");
2346 WARN("or out of memory\n");
2351 buffer
= allocate_buffer();
2353 WARN("Failed to allocate a buffer for the shader bytecode\n");
2358 writer
->funcs
->header(writer
, shader
, buffer
);
2359 if(FAILED(writer
->state
)) {
2364 for(i
= 0; i
< shader
->num_instrs
; i
++) {
2365 hr
= call_instr_handler(writer
, shader
->instr
[i
], buffer
);
2371 if(FAILED(writer
->state
)) {
2376 writer
->funcs
->end(writer
, shader
, buffer
);
2378 if(FAILED(buffer
->state
)) {
2383 /* Cut off unneeded memory from the result buffer */
2384 *result
= asm_realloc(buffer
->data
,
2385 sizeof(DWORD
) * buffer
->size
);
2387 *result
= buffer
->data
;
2389 buffer
->data
= NULL
;
2394 asm_free(buffer
->data
);
2401 void SlDeleteShader(struct bwriter_shader
*shader
) {
2404 TRACE("Deleting shader %p\n", shader
);
2406 for(i
= 0; i
< shader
->num_cf
; i
++) {
2407 asm_free(shader
->constF
[i
]);
2409 asm_free(shader
->constF
);
2410 for(i
= 0; i
< shader
->num_ci
; i
++) {
2411 asm_free(shader
->constI
[i
]);
2413 asm_free(shader
->constI
);
2414 for(i
= 0; i
< shader
->num_cb
; i
++) {
2415 asm_free(shader
->constB
[i
]);
2417 asm_free(shader
->constB
);
2419 asm_free(shader
->inputs
);
2420 asm_free(shader
->outputs
);
2421 asm_free(shader
->samplers
);
2423 for(i
= 0; i
< shader
->num_instrs
; i
++) {
2424 for(j
= 0; j
< shader
->instr
[i
]->num_srcs
; j
++) {
2425 asm_free(shader
->instr
[i
]->src
[j
].rel_reg
);
2427 asm_free(shader
->instr
[i
]->src
);
2428 asm_free(shader
->instr
[i
]);
2430 asm_free(shader
->instr
);