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
record_declaration(struct bwriter_shader
*shader
, DWORD usage
, DWORD usage_idx
, BOOL output
, DWORD regnum
, DWORD writemask
) {
109 struct declaration
**decl
;
112 if(!shader
) return FALSE
;
115 num
= &shader
->num_outputs
;
116 decl
= &shader
->outputs
;
118 num
= &shader
->num_inputs
;
119 decl
= &shader
->inputs
;
123 *decl
= asm_alloc(sizeof(**decl
));
125 ERR("Error allocating declarations array\n");
129 struct declaration
*newdecl
;
130 for(i
= 0; i
< *num
; i
++) {
131 if((*decl
)[i
].regnum
== regnum
&& ((*decl
)[i
].writemask
& writemask
)) {
132 WARN("Declaration of register %u already exists, writemask match 0x%x\n",
133 regnum
, (*decl
)[i
].writemask
& writemask
);
137 newdecl
= asm_realloc(*decl
,
138 sizeof(**decl
) * ((*num
) + 1));
140 ERR("Error reallocating declarations array\n");
145 (*decl
)[*num
].usage
= usage
;
146 (*decl
)[*num
].usage_idx
= usage_idx
;
147 (*decl
)[*num
].regnum
= regnum
;
148 (*decl
)[*num
].writemask
= writemask
;
154 BOOL
record_sampler(struct bwriter_shader
*shader
, DWORD samptype
, DWORD regnum
) {
157 if(!shader
) return FALSE
;
159 if(shader
->num_samplers
== 0) {
160 shader
->samplers
= asm_alloc(sizeof(*shader
->samplers
));
161 if(!shader
->samplers
) {
162 ERR("Error allocating samplers array\n");
166 struct samplerdecl
*newarray
;
168 for(i
= 0; i
< shader
->num_samplers
; i
++) {
169 if(shader
->samplers
[i
].regnum
== regnum
) {
170 WARN("Sampler %u already declared\n", regnum
);
171 /* This is not an error as far as the assembler is concerned.
172 * Direct3D might refuse to load the compiled shader though
177 newarray
= asm_realloc(shader
->samplers
,
178 sizeof(*shader
->samplers
) * (shader
->num_samplers
+ 1));
180 ERR("Error reallocating samplers array\n");
183 shader
->samplers
= newarray
;
186 shader
->samplers
[shader
->num_samplers
].type
= samptype
;
187 shader
->samplers
[shader
->num_samplers
].regnum
= regnum
;
188 shader
->num_samplers
++;
193 /* shader bytecode buffer manipulation functions.
194 * allocate_buffer creates a new buffer structure, put_dword adds a new
195 * DWORD to the buffer. In the rare case of a memory allocation failure
196 * when trying to grow the buffer a flag is set in the buffer to mark it
197 * invalid. This avoids return value checking and passing in many places
199 static struct bytecode_buffer
*allocate_buffer(void) {
200 struct bytecode_buffer
*ret
;
202 ret
= asm_alloc(sizeof(*ret
));
203 if(!ret
) return NULL
;
205 ret
->alloc_size
= BYTECODEBUFFER_INITIAL_SIZE
;
206 ret
->data
= asm_alloc(sizeof(DWORD
) * ret
->alloc_size
);
215 static void put_dword(struct bytecode_buffer
*buffer
, DWORD value
) {
216 if(FAILED(buffer
->state
)) return;
218 if(buffer
->alloc_size
== buffer
->size
) {
220 buffer
->alloc_size
*= 2;
221 newarray
= asm_realloc(buffer
->data
,
222 sizeof(DWORD
) * buffer
->alloc_size
);
224 ERR("Failed to grow the buffer data memory\n");
225 buffer
->state
= E_OUTOFMEMORY
;
228 buffer
->data
= newarray
;
230 buffer
->data
[buffer
->size
++] = value
;
233 /******************************************************
234 * Implementation of the writer functions starts here *
235 ******************************************************/
236 static void write_declarations(struct bytecode_buffer
*buffer
, BOOL len
,
237 const struct declaration
*decls
, unsigned int num
, DWORD type
) {
239 DWORD instr_dcl
= D3DSIO_DCL
;
243 instr_dcl
|= 2 << D3DSI_INSTLENGTH_SHIFT
;
246 for(i
= 0; i
< num
; i
++) {
247 /* Write the DCL instruction */
248 put_dword(buffer
, instr_dcl
);
250 /* Write the usage and index */
251 token
= (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
252 token
|= (decls
[i
].usage
<< D3DSP_DCL_USAGE_SHIFT
) & D3DSP_DCL_USAGE_MASK
;
253 token
|= (decls
[i
].usage_idx
<< D3DSP_DCL_USAGEINDEX_SHIFT
) & D3DSP_DCL_USAGEINDEX_MASK
;
254 put_dword(buffer
, token
);
256 /* Write the dest register */
257 token
= (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
258 token
|= (type
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
259 token
|= (d3d9_writemask(decls
[i
].writemask
)) & D3DSP_WRITEMASK_ALL
;
260 token
|= decls
[i
].regnum
& D3DSP_REGNUM_MASK
;
261 put_dword(buffer
, token
);
265 static void end(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
266 put_dword(buffer
, D3DSIO_END
);
269 static void write_srcregs(struct bc_writer
*This
, const struct instruction
*instr
,
270 struct bytecode_buffer
*buffer
){
272 if(instr
->has_predicate
){
273 This
->funcs
->srcreg(This
, &instr
->predicate
, buffer
);
275 for(i
= 0; i
< instr
->num_srcs
; i
++){
276 This
->funcs
->srcreg(This
, &instr
->src
[i
], buffer
);
280 /* The length of an instruction consists of the destination register (if any),
281 * the number of source registers, the number of address registers used for
282 * indirect addressing, and optionally the predicate register
284 static DWORD
instrlen(const struct instruction
*instr
, unsigned int srcs
, unsigned int dsts
) {
286 DWORD ret
= srcs
+ dsts
+ (instr
->has_predicate
? 1 : 0);
289 if(instr
->dst
.rel_reg
) ret
++;
291 for(i
= 0; i
< srcs
; i
++) {
292 if(instr
->src
[i
].rel_reg
) ret
++;
297 static void instr_handler(struct bc_writer
*This
,
298 const struct instruction
*instr
,
299 struct bytecode_buffer
*buffer
) {
300 DWORD token
= d3d9_opcode(instr
->opcode
);
301 TRACE("token: %x\n", token
);
303 This
->funcs
->opcode(This
, instr
, token
, buffer
);
304 if(instr
->has_dst
) This
->funcs
->dstreg(This
, &instr
->dst
, buffer
, instr
->shift
, instr
->dstmod
);
305 write_srcregs(This
, instr
, buffer
);
308 static void sm_2_opcode(struct bc_writer
*This
,
309 const struct instruction
*instr
,
310 DWORD token
, struct bytecode_buffer
*buffer
) {
311 /* From sm 2 onwards instruction length is encoded in the opcode field */
312 int dsts
= instr
->has_dst
? 1 : 0;
313 token
|= instrlen(instr
, instr
->num_srcs
, dsts
) << D3DSI_INSTLENGTH_SHIFT
;
315 token
|= (d3d9_comparetype(instr
->comptype
) << 16) & (0xf << 16);
316 if(instr
->has_predicate
)
317 token
|= D3DSHADER_INSTRUCTION_PREDICATED
;
318 put_dword(buffer
,token
);
321 static void write_samplers(const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
323 DWORD instr_dcl
= D3DSIO_DCL
| (2 << D3DSI_INSTLENGTH_SHIFT
);
325 const DWORD reg
= (1<<31) |
326 ((D3DSPR_SAMPLER
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
) |
327 ((D3DSPR_SAMPLER
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
) |
330 for(i
= 0; i
< shader
->num_samplers
; i
++) {
331 /* Write the DCL instruction */
332 put_dword(buffer
, instr_dcl
);
334 /* Already shifted */
335 token
|= (d3d9_sampler(shader
->samplers
[i
].type
)) & D3DSP_TEXTURETYPE_MASK
;
336 put_dword(buffer
, token
);
337 put_dword(buffer
, reg
| (shader
->samplers
[i
].regnum
& D3DSP_REGNUM_MASK
));
341 static void sm_3_header(struct bc_writer
*This
, const struct bwriter_shader
*shader
, struct bytecode_buffer
*buffer
) {
342 /* Declare the shader type and version */
343 put_dword(buffer
, This
->version
);
345 write_declarations(buffer
, TRUE
, shader
->inputs
, shader
->num_inputs
, D3DSPR_INPUT
);
346 write_declarations(buffer
, TRUE
, shader
->outputs
, shader
->num_outputs
, D3DSPR_OUTPUT
);
347 write_samplers(shader
, buffer
);
351 static void sm_3_srcreg(struct bc_writer
*This
,
352 const struct shader_reg
*reg
,
353 struct bytecode_buffer
*buffer
) {
354 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
357 d3d9reg
= d3d9_register(reg
->type
);
358 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
359 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
360 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
;
362 token
|= d3d9_swizzle(reg
->swizzle
) & D3DVS_SWIZZLE_MASK
;
363 token
|= d3d9_srcmod(reg
->srcmod
);
366 if(reg
->type
== BWRITERSPR_CONST
&& This
->version
== BWRITERPS_VERSION(3, 0)) {
367 WARN("c%u[...] is unsupported in ps_3_0\n", reg
->regnum
);
368 This
->state
= E_INVALIDARG
;
371 if(((reg
->rel_reg
->type
== BWRITERSPR_ADDR
&& This
->version
== BWRITERVS_VERSION(3, 0)) ||
372 reg
->rel_reg
->type
== BWRITERSPR_LOOP
) &&
373 reg
->rel_reg
->regnum
== 0) {
374 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
376 WARN("Unsupported relative addressing register\n");
377 This
->state
= E_INVALIDARG
;
382 put_dword(buffer
, token
);
384 /* vs_2_0 and newer write the register containing the index explicitly in the
387 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
388 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
392 static void sm_3_dstreg(struct bc_writer
*This
,
393 const struct shader_reg
*reg
,
394 struct bytecode_buffer
*buffer
,
395 DWORD shift
, DWORD mod
) {
396 DWORD token
= (1 << 31); /* Bit 31 of registers is 1 */
400 if(This
->version
== BWRITERVS_VERSION(3, 0) &&
401 reg
->type
== BWRITERSPR_OUTPUT
) {
402 token
|= D3DVS_ADDRMODE_RELATIVE
& D3DVS_ADDRESSMODE_MASK
;
404 WARN("Relative addressing not supported for this shader type or register type\n");
405 This
->state
= E_INVALIDARG
;
410 d3d9reg
= d3d9_register(reg
->type
);
411 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT
) & D3DSP_REGTYPE_MASK
;
412 token
|= (d3d9reg
<< D3DSP_REGTYPE_SHIFT2
) & D3DSP_REGTYPE_MASK2
;
413 token
|= reg
->regnum
& D3DSP_REGNUM_MASK
; /* No shift */
415 token
|= d3d9_dstmod(mod
);
417 token
|= d3d9_writemask(reg
->writemask
);
418 put_dword(buffer
, token
);
420 /* vs_2_0 and newer write the register containing the index explicitly in the
423 if(token
& D3DVS_ADDRMODE_RELATIVE
) {
424 sm_3_srcreg(This
, reg
->rel_reg
, buffer
);
428 static const struct instr_handler_table vs_3_handlers
[] = {
429 {BWRITERSIO_ADD
, instr_handler
},
430 {BWRITERSIO_NOP
, instr_handler
},
431 {BWRITERSIO_MOV
, instr_handler
},
432 {BWRITERSIO_SUB
, instr_handler
},
433 {BWRITERSIO_MAD
, instr_handler
},
434 {BWRITERSIO_MUL
, instr_handler
},
435 {BWRITERSIO_RCP
, instr_handler
},
436 {BWRITERSIO_RSQ
, instr_handler
},
437 {BWRITERSIO_DP3
, instr_handler
},
438 {BWRITERSIO_DP4
, instr_handler
},
439 {BWRITERSIO_MIN
, instr_handler
},
440 {BWRITERSIO_MAX
, instr_handler
},
441 {BWRITERSIO_SLT
, instr_handler
},
442 {BWRITERSIO_SGE
, instr_handler
},
443 {BWRITERSIO_ABS
, instr_handler
},
444 {BWRITERSIO_EXP
, instr_handler
},
445 {BWRITERSIO_LOG
, instr_handler
},
446 {BWRITERSIO_EXPP
, instr_handler
},
447 {BWRITERSIO_LOGP
, instr_handler
},
448 {BWRITERSIO_DST
, instr_handler
},
449 {BWRITERSIO_LRP
, instr_handler
},
450 {BWRITERSIO_FRC
, instr_handler
},
451 {BWRITERSIO_CRS
, instr_handler
},
452 {BWRITERSIO_SGN
, instr_handler
},
453 {BWRITERSIO_NRM
, instr_handler
},
454 {BWRITERSIO_SINCOS
, instr_handler
},
455 {BWRITERSIO_M4x4
, instr_handler
},
456 {BWRITERSIO_M4x3
, instr_handler
},
457 {BWRITERSIO_M3x4
, instr_handler
},
458 {BWRITERSIO_M3x3
, instr_handler
},
459 {BWRITERSIO_M3x2
, instr_handler
},
460 {BWRITERSIO_LIT
, instr_handler
},
461 {BWRITERSIO_POW
, instr_handler
},
462 {BWRITERSIO_MOVA
, instr_handler
},
464 {BWRITERSIO_CALL
, instr_handler
},
465 {BWRITERSIO_CALLNZ
, instr_handler
},
466 {BWRITERSIO_REP
, instr_handler
},
467 {BWRITERSIO_ENDREP
, instr_handler
},
468 {BWRITERSIO_IF
, instr_handler
},
469 {BWRITERSIO_LABEL
, instr_handler
},
470 {BWRITERSIO_IFC
, instr_handler
},
471 {BWRITERSIO_ELSE
, instr_handler
},
472 {BWRITERSIO_ENDIF
, instr_handler
},
473 {BWRITERSIO_BREAK
, instr_handler
},
474 {BWRITERSIO_BREAKC
, instr_handler
},
475 {BWRITERSIO_LOOP
, instr_handler
},
476 {BWRITERSIO_RET
, instr_handler
},
477 {BWRITERSIO_ENDLOOP
, instr_handler
},
479 {BWRITERSIO_SETP
, instr_handler
},
480 {BWRITERSIO_BREAKP
, instr_handler
},
481 {BWRITERSIO_TEXLDL
, instr_handler
},
483 {BWRITERSIO_END
, NULL
},
486 static const struct bytecode_backend vs_3_backend
= {
495 static void init_vs30_dx9_writer(struct bc_writer
*writer
) {
496 TRACE("Creating DirectX9 vertex shader 3.0 writer\n");
497 writer
->funcs
= &vs_3_backend
;
500 static struct bc_writer
*create_writer(DWORD version
, DWORD dxversion
) {
501 struct bc_writer
*ret
= asm_alloc(sizeof(*ret
));
504 WARN("Failed to allocate a bytecode writer instance\n");
509 case BWRITERVS_VERSION(1, 0):
511 WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion
);
514 /* TODO: Set the appropriate writer backend */
516 case BWRITERVS_VERSION(1, 1):
518 WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion
);
521 /* TODO: Set the appropriate writer backend */
523 case BWRITERVS_VERSION(2, 0):
525 WARN("Unsupported dxversion for vertex shader 2.0 requested: %u\n", dxversion
);
528 /* TODO: Set the appropriate writer backend */
530 case BWRITERVS_VERSION(2, 1):
532 WARN("Unsupported dxversion for vertex shader 2.x requested: %u\n", dxversion
);
535 /* TODO: Set the appropriate writer backend */
537 case BWRITERVS_VERSION(3, 0):
539 WARN("Unsupported dxversion for vertex shader 3.0 requested: %u\n", dxversion
);
542 init_vs30_dx9_writer(ret
);
545 case BWRITERPS_VERSION(1, 0):
547 WARN("Unsupported dxversion for pixel shader 1.0 requested: %u\n", dxversion
);
550 /* TODO: Set the appropriate writer backend */
552 case BWRITERPS_VERSION(1, 1):
554 WARN("Unsupported dxversion for pixel shader 1.1 requested: %u\n", dxversion
);
557 /* TODO: Set the appropriate writer backend */
559 case BWRITERPS_VERSION(1, 2):
561 WARN("Unsupported dxversion for pixel shader 1.2 requested: %u\n", dxversion
);
564 /* TODO: Set the appropriate writer backend */
566 case BWRITERPS_VERSION(1, 3):
568 WARN("Unsupported dxversion for pixel shader 1.3 requested: %u\n", dxversion
);
571 /* TODO: Set the appropriate writer backend */
573 case BWRITERPS_VERSION(1, 4):
575 WARN("Unsupported dxversion for pixel shader 1.4 requested: %u\n", dxversion
);
578 /* TODO: Set the appropriate writer backend */
581 case BWRITERPS_VERSION(2, 0):
583 WARN("Unsupported dxversion for pixel shader 2.0 requested: %u\n", dxversion
);
586 /* TODO: Set the appropriate writer backend */
589 case BWRITERPS_VERSION(2, 1):
591 WARN("Unsupported dxversion for pixel shader 2.x requested: %u\n", dxversion
);
594 /* TODO: Set the appropriate writer backend */
597 case BWRITERPS_VERSION(3, 0):
599 WARN("Unsupported dxversion for pixel shader 3.0 requested: %u\n", dxversion
);
602 /* TODO: Set the appropriate writer backend */
606 WARN("Unexpected shader version requested: %08x\n", version
);
609 ret
->version
= version
;
617 static HRESULT
call_instr_handler(struct bc_writer
*writer
,
618 const struct instruction
*instr
,
619 struct bytecode_buffer
*buffer
) {
622 while(writer
->funcs
->instructions
[i
].opcode
!= BWRITERSIO_END
) {
623 if(instr
->opcode
== writer
->funcs
->instructions
[i
].opcode
) {
624 if(!writer
->funcs
->instructions
[i
].func
) {
625 WARN("Opcode %u not supported by this profile\n", instr
->opcode
);
628 writer
->funcs
->instructions
[i
].func(writer
, instr
, buffer
);
634 FIXME("Unhandled instruction %u\n", instr
->opcode
);
638 /* SlWriteBytecode (wineshader.@)
640 * Writes shader version specific bytecode from the shader passed in.
641 * The returned bytecode can be passed to the Direct3D runtime like
642 * IDirect3DDevice9::Create*Shader.
645 * shader: Shader to translate into bytecode
646 * version: Shader version to generate(d3d version token)
647 * dxversion: DirectX version the code targets
648 * result: the resulting shader bytecode
653 DWORD
SlWriteBytecode(const struct bwriter_shader
*shader
, int dxversion
, DWORD
**result
) {
654 struct bc_writer
*writer
;
655 struct bytecode_buffer
*buffer
= NULL
;
660 ERR("NULL shader structure, aborting\n");
663 writer
= create_writer(shader
->version
, dxversion
);
667 WARN("Could not create a bytecode writer instance. Either unsupported version\n");
668 WARN("or out of memory\n");
673 buffer
= allocate_buffer();
675 WARN("Failed to allocate a buffer for the shader bytecode\n");
680 writer
->funcs
->header(writer
, shader
, buffer
);
681 if(FAILED(writer
->state
)) {
686 for(i
= 0; i
< shader
->num_instrs
; i
++) {
687 hr
= call_instr_handler(writer
, shader
->instr
[i
], buffer
);
693 if(FAILED(writer
->state
)) {
698 writer
->funcs
->end(writer
, shader
, buffer
);
700 if(FAILED(buffer
->state
)) {
705 /* Cut off unneeded memory from the result buffer */
706 *result
= asm_realloc(buffer
->data
,
707 sizeof(DWORD
) * buffer
->size
);
709 *result
= buffer
->data
;
716 asm_free(buffer
->data
);
723 void SlDeleteShader(struct bwriter_shader
*shader
) {
726 TRACE("Deleting shader %p\n", shader
);
728 for(i
= 0; i
< shader
->num_cf
; i
++) {
729 asm_free(shader
->constF
[i
]);
731 asm_free(shader
->constF
);
732 for(i
= 0; i
< shader
->num_ci
; i
++) {
733 asm_free(shader
->constI
[i
]);
735 asm_free(shader
->constI
);
736 for(i
= 0; i
< shader
->num_cb
; i
++) {
737 asm_free(shader
->constB
[i
]);
739 asm_free(shader
->constB
);
741 asm_free(shader
->inputs
);
742 asm_free(shader
->outputs
);
743 asm_free(shader
->samplers
);
745 for(i
= 0; i
< shader
->num_instrs
; i
++) {
746 for(j
= 0; j
< shader
->instr
[i
]->num_srcs
; j
++) {
747 asm_free(shader
->instr
[i
]->src
[j
].rel_reg
);
749 asm_free(shader
->instr
[i
]->src
);
750 asm_free(shader
->instr
[i
]);
752 asm_free(shader
->instr
);