2 * Direct3D bytecode output functions
4 * Copyright 2008 Stefan Dösinger
5 * Copyright 2009 Matteo Bruni
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
25 #include "wine/debug.h"
27 #include "d3dx9_36_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
31 /****************************************************************
32 * General assembler shader construction helper routines follow *
33 ****************************************************************/
34 /* struct instruction *alloc_instr
36 * Allocates a new instruction structure with srcs registers
39 * srcs: Number of source registers to allocate
42 * A pointer to the allocated instruction structure
43 * NULL in case of an allocation failure
45 struct instruction *alloc_instr(unsigned int srcs) {
46 struct instruction *ret = asm_alloc(sizeof(*ret));
48 ERR("Failed to allocate memory for an instruction structure\n");
53 ret->src = asm_alloc(srcs * sizeof(*ret->src));
55 ERR("Failed to allocate memory for instruction registers\n");
64 /* void add_instruction
66 * Adds a new instruction to the shader's instructions array and grows the instruction array
69 * The function does NOT copy the instruction structure. Make sure not to release the
70 * instruction or any of its substructures like registers.
73 * shader: Shader to add the instruction to
74 * instr: Instruction to add to the shader
76 BOOL add_instruction(struct bwriter_shader *shader, struct instruction *instr) {
77 struct instruction **new_instructions;
79 if(!shader) return FALSE;
81 if(shader->instr_alloc_size == 0) {
82 shader->instr = asm_alloc(sizeof(*shader->instr) * INSTRARRAY_INITIAL_SIZE);
84 ERR("Failed to allocate the shader instruction array\n");
87 shader->instr_alloc_size = INSTRARRAY_INITIAL_SIZE;
88 } else if(shader->instr_alloc_size == shader->num_instrs) {
89 new_instructions = asm_realloc(shader->instr,
90 sizeof(*shader->instr) * (shader->instr_alloc_size) * 2);
91 if(!new_instructions) {
92 ERR("Failed to grow the shader instruction array\n");
95 shader->instr = new_instructions;
96 shader->instr_alloc_size = shader->instr_alloc_size * 2;
97 } else if(shader->num_instrs > shader->instr_alloc_size) {
98 ERR("More instructions than allocated. This should not happen\n");
102 shader->instr[shader->num_instrs] = instr;
103 shader->num_instrs++;
107 BOOL add_constF(struct bwriter_shader *shader, DWORD reg, float x, float y, float z, float w) {
108 struct constant *newconst;
111 struct constant **newarray;
112 newarray = asm_realloc(shader->constF,
113 sizeof(*shader->constF) * (shader->num_cf + 1));
115 ERR("Failed to grow the constants array\n");
118 shader->constF = newarray;
120 shader->constF = asm_alloc(sizeof(*shader->constF));
121 if(!shader->constF) {
122 ERR("Failed to allocate the constants array\n");
127 newconst = asm_alloc(sizeof(*newconst));
129 ERR("Failed to allocate a new constant\n");
132 newconst->regnum = reg;
133 newconst->value[0].f = x;
134 newconst->value[1].f = y;
135 newconst->value[2].f = z;
136 newconst->value[3].f = w;
137 shader->constF[shader->num_cf] = newconst;
143 BOOL add_constI(struct bwriter_shader *shader, DWORD reg, INT x, INT y, INT z, INT w) {
144 struct constant *newconst;
147 struct constant **newarray;
148 newarray = asm_realloc(shader->constI,
149 sizeof(*shader->constI) * (shader->num_ci + 1));
151 ERR("Failed to grow the constants array\n");
154 shader->constI = newarray;
156 shader->constI = asm_alloc(sizeof(*shader->constI));
157 if(!shader->constI) {
158 ERR("Failed to allocate the constants array\n");
163 newconst = asm_alloc(sizeof(*newconst));
165 ERR("Failed to allocate a new constant\n");
168 newconst->regnum = reg;
169 newconst->value[0].i = x;
170 newconst->value[1].i = y;
171 newconst->value[2].i = z;
172 newconst->value[3].i = w;
173 shader->constI[shader->num_ci] = newconst;
179 BOOL add_constB(struct bwriter_shader *shader, DWORD reg, BOOL x) {
180 struct constant *newconst;
183 struct constant **newarray;
184 newarray = asm_realloc(shader->constB,
185 sizeof(*shader->constB) * (shader->num_cb + 1));
187 ERR("Failed to grow the constants array\n");
190 shader->constB = newarray;
192 shader->constB = asm_alloc(sizeof(*shader->constB));
193 if(!shader->constB) {
194 ERR("Failed to allocate the constants array\n");
199 newconst = asm_alloc(sizeof(*newconst));
201 ERR("Failed to allocate a new constant\n");
204 newconst->regnum = reg;
205 newconst->value[0].b = x;
206 shader->constB[shader->num_cb] = newconst;
212 BOOL record_declaration(struct bwriter_shader *shader, DWORD usage, DWORD usage_idx, BOOL output, DWORD regnum, DWORD writemask) {
214 struct declaration **decl;
217 if(!shader) return FALSE;
220 num = &shader->num_outputs;
221 decl = &shader->outputs;
223 num = &shader->num_inputs;
224 decl = &shader->inputs;
228 *decl = asm_alloc(sizeof(**decl));
230 ERR("Error allocating declarations array\n");
234 struct declaration *newdecl;
235 for(i = 0; i < *num; i++) {
236 if((*decl)[i].regnum == regnum && ((*decl)[i].writemask & writemask)) {
237 WARN("Declaration of register %u already exists, writemask match 0x%x\n",
238 regnum, (*decl)[i].writemask & writemask);
242 newdecl = asm_realloc(*decl,
243 sizeof(**decl) * ((*num) + 1));
245 ERR("Error reallocating declarations array\n");
250 (*decl)[*num].usage = usage;
251 (*decl)[*num].usage_idx = usage_idx;
252 (*decl)[*num].regnum = regnum;
253 (*decl)[*num].writemask = writemask;
259 BOOL record_sampler(struct bwriter_shader *shader, DWORD samptype, DWORD regnum) {
262 if(!shader) return FALSE;
264 if(shader->num_samplers == 0) {
265 shader->samplers = asm_alloc(sizeof(*shader->samplers));
266 if(!shader->samplers) {
267 ERR("Error allocating samplers array\n");
271 struct samplerdecl *newarray;
273 for(i = 0; i < shader->num_samplers; i++) {
274 if(shader->samplers[i].regnum == regnum) {
275 WARN("Sampler %u already declared\n", regnum);
276 /* This is not an error as far as the assembler is concerned.
277 * Direct3D might refuse to load the compiled shader though
282 newarray = asm_realloc(shader->samplers,
283 sizeof(*shader->samplers) * (shader->num_samplers + 1));
285 ERR("Error reallocating samplers array\n");
288 shader->samplers = newarray;
291 shader->samplers[shader->num_samplers].type = samptype;
292 shader->samplers[shader->num_samplers].regnum = regnum;
293 shader->num_samplers++;
298 /* shader bytecode buffer manipulation functions.
299 * allocate_buffer creates a new buffer structure, put_dword adds a new
300 * DWORD to the buffer. In the rare case of a memory allocation failure
301 * when trying to grow the buffer a flag is set in the buffer to mark it
302 * invalid. This avoids return value checking and passing in many places
304 static struct bytecode_buffer *allocate_buffer(void) {
305 struct bytecode_buffer *ret;
307 ret = asm_alloc(sizeof(*ret));
308 if(!ret) return NULL;
310 ret->alloc_size = BYTECODEBUFFER_INITIAL_SIZE;
311 ret->data = asm_alloc(sizeof(DWORD) * ret->alloc_size);
320 static void put_dword(struct bytecode_buffer *buffer, DWORD value) {
321 if(FAILED(buffer->state)) return;
323 if(buffer->alloc_size == buffer->size) {
325 buffer->alloc_size *= 2;
326 newarray = asm_realloc(buffer->data,
327 sizeof(DWORD) * buffer->alloc_size);
329 ERR("Failed to grow the buffer data memory\n");
330 buffer->state = E_OUTOFMEMORY;
333 buffer->data = newarray;
335 buffer->data[buffer->size++] = value;
338 /******************************************************
339 * Implementation of the writer functions starts here *
340 ******************************************************/
341 static void write_declarations(struct bytecode_buffer *buffer, BOOL len,
342 const struct declaration *decls, unsigned int num, DWORD type) {
344 DWORD instr_dcl = D3DSIO_DCL;
348 instr_dcl |= 2 << D3DSI_INSTLENGTH_SHIFT;
351 for(i = 0; i < num; i++) {
352 /* Write the DCL instruction */
353 put_dword(buffer, instr_dcl);
355 /* Write the usage and index */
356 token = (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
357 token |= (decls[i].usage << D3DSP_DCL_USAGE_SHIFT) & D3DSP_DCL_USAGE_MASK;
358 token |= (decls[i].usage_idx << D3DSP_DCL_USAGEINDEX_SHIFT) & D3DSP_DCL_USAGEINDEX_MASK;
359 put_dword(buffer, token);
361 /* Write the dest register */
362 token = (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
363 token |= (type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
364 token |= (d3d9_writemask(decls[i].writemask)) & D3DSP_WRITEMASK_ALL;
365 token |= decls[i].regnum & D3DSP_REGNUM_MASK;
366 put_dword(buffer, token);
370 static void write_const(struct constant **consts, int num, DWORD opcode, DWORD reg_type, struct bytecode_buffer *buffer, BOOL len) {
372 DWORD instr_def = opcode;
373 const DWORD reg = (1<<31) |
374 ((reg_type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) |
375 ((reg_type << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) |
379 if(opcode == D3DSIO_DEFB)
380 instr_def |= 2 << D3DSI_INSTLENGTH_SHIFT;
382 instr_def |= 5 << D3DSI_INSTLENGTH_SHIFT;
385 for(i = 0; i < num; i++) {
386 /* Write the DEF instruction */
387 put_dword(buffer, instr_def);
389 put_dword(buffer, reg | (consts[i]->regnum & D3DSP_REGNUM_MASK));
390 put_dword(buffer, consts[i]->value[0].d);
391 if(opcode != D3DSIO_DEFB) {
392 put_dword(buffer, consts[i]->value[1].d);
393 put_dword(buffer, consts[i]->value[2].d);
394 put_dword(buffer, consts[i]->value[3].d);
399 static void write_constF(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
400 write_const(shader->constF, shader->num_cf, D3DSIO_DEF, D3DSPR_CONST, buffer, len);
403 static void end(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
404 put_dword(buffer, D3DSIO_END);
407 static void write_srcregs(struct bc_writer *This, const struct instruction *instr,
408 struct bytecode_buffer *buffer){
410 if(instr->has_predicate){
411 This->funcs->srcreg(This, &instr->predicate, buffer);
413 for(i = 0; i < instr->num_srcs; i++){
414 This->funcs->srcreg(This, &instr->src[i], buffer);
418 /* The length of an instruction consists of the destination register (if any),
419 * the number of source registers, the number of address registers used for
420 * indirect addressing, and optionally the predicate register
422 static DWORD instrlen(const struct instruction *instr, unsigned int srcs, unsigned int dsts) {
424 DWORD ret = srcs + dsts + (instr->has_predicate ? 1 : 0);
427 if(instr->dst.rel_reg) ret++;
429 for(i = 0; i < srcs; i++) {
430 if(instr->src[i].rel_reg) ret++;
435 static void instr_handler(struct bc_writer *This,
436 const struct instruction *instr,
437 struct bytecode_buffer *buffer) {
438 DWORD token = d3d9_opcode(instr->opcode);
439 TRACE("token: %x\n", token);
441 This->funcs->opcode(This, instr, token, buffer);
442 if(instr->has_dst) This->funcs->dstreg(This, &instr->dst, buffer, instr->shift, instr->dstmod);
443 write_srcregs(This, instr, buffer);
446 static void write_constB(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
447 write_const(shader->constB, shader->num_cb, D3DSIO_DEFB, D3DSPR_CONSTBOOL, buffer, len);
450 static void write_constI(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
451 write_const(shader->constI, shader->num_ci, D3DSIO_DEFI, D3DSPR_CONSTINT, buffer, len);
454 static void sm_2_opcode(struct bc_writer *This,
455 const struct instruction *instr,
456 DWORD token, struct bytecode_buffer *buffer) {
457 /* From sm 2 onwards instruction length is encoded in the opcode field */
458 int dsts = instr->has_dst ? 1 : 0;
459 token |= instrlen(instr, instr->num_srcs, dsts) << D3DSI_INSTLENGTH_SHIFT;
461 token |= (d3d9_comparetype(instr->comptype) << 16) & (0xf << 16);
462 if(instr->has_predicate)
463 token |= D3DSHADER_INSTRUCTION_PREDICATED;
464 put_dword(buffer,token);
467 static void write_samplers(const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
469 DWORD instr_dcl = D3DSIO_DCL | (2 << D3DSI_INSTLENGTH_SHIFT);
471 const DWORD reg = (1<<31) |
472 ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) |
473 ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) |
476 for(i = 0; i < shader->num_samplers; i++) {
477 /* Write the DCL instruction */
478 put_dword(buffer, instr_dcl);
480 /* Already shifted */
481 token |= (d3d9_sampler(shader->samplers[i].type)) & D3DSP_TEXTURETYPE_MASK;
482 put_dword(buffer, token);
483 put_dword(buffer, reg | (shader->samplers[i].regnum & D3DSP_REGNUM_MASK));
487 static void sm_3_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
488 /* Declare the shader type and version */
489 put_dword(buffer, This->version);
491 write_declarations(buffer, TRUE, shader->inputs, shader->num_inputs, D3DSPR_INPUT);
492 write_declarations(buffer, TRUE, shader->outputs, shader->num_outputs, D3DSPR_OUTPUT);
493 write_constF(shader, buffer, TRUE);
494 write_constB(shader, buffer, TRUE);
495 write_constI(shader, buffer, TRUE);
496 write_samplers(shader, buffer);
500 static void sm_3_srcreg(struct bc_writer *This,
501 const struct shader_reg *reg,
502 struct bytecode_buffer *buffer) {
503 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
506 d3d9reg = d3d9_register(reg->type);
507 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
508 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
509 token |= reg->regnum & D3DSP_REGNUM_MASK;
511 token |= d3d9_swizzle(reg->swizzle) & D3DVS_SWIZZLE_MASK;
512 token |= d3d9_srcmod(reg->srcmod);
515 if(reg->type == BWRITERSPR_CONST && This->version == BWRITERPS_VERSION(3, 0)) {
516 WARN("c%u[...] is unsupported in ps_3_0\n", reg->regnum);
517 This->state = E_INVALIDARG;
520 if(((reg->rel_reg->type == BWRITERSPR_ADDR && This->version == BWRITERVS_VERSION(3, 0)) ||
521 reg->rel_reg->type == BWRITERSPR_LOOP) &&
522 reg->rel_reg->regnum == 0) {
523 token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
525 WARN("Unsupported relative addressing register\n");
526 This->state = E_INVALIDARG;
531 put_dword(buffer, token);
533 /* vs_2_0 and newer write the register containing the index explicitly in the
536 if(token & D3DVS_ADDRMODE_RELATIVE) {
537 sm_3_srcreg(This, reg->rel_reg, buffer);
541 static void sm_3_dstreg(struct bc_writer *This,
542 const struct shader_reg *reg,
543 struct bytecode_buffer *buffer,
544 DWORD shift, DWORD mod) {
545 DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
549 if(This->version == BWRITERVS_VERSION(3, 0) &&
550 reg->type == BWRITERSPR_OUTPUT) {
551 token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
553 WARN("Relative addressing not supported for this shader type or register type\n");
554 This->state = E_INVALIDARG;
559 d3d9reg = d3d9_register(reg->type);
560 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
561 token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
562 token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
564 token |= d3d9_dstmod(mod);
566 token |= d3d9_writemask(reg->writemask);
567 put_dword(buffer, token);
569 /* vs_2_0 and newer write the register containing the index explicitly in the
572 if(token & D3DVS_ADDRMODE_RELATIVE) {
573 sm_3_srcreg(This, reg->rel_reg, buffer);
577 static const struct instr_handler_table vs_3_handlers[] = {
578 {BWRITERSIO_ADD, instr_handler},
579 {BWRITERSIO_NOP, instr_handler},
580 {BWRITERSIO_MOV, instr_handler},
581 {BWRITERSIO_SUB, instr_handler},
582 {BWRITERSIO_MAD, instr_handler},
583 {BWRITERSIO_MUL, instr_handler},
584 {BWRITERSIO_RCP, instr_handler},
585 {BWRITERSIO_RSQ, instr_handler},
586 {BWRITERSIO_DP3, instr_handler},
587 {BWRITERSIO_DP4, instr_handler},
588 {BWRITERSIO_MIN, instr_handler},
589 {BWRITERSIO_MAX, instr_handler},
590 {BWRITERSIO_SLT, instr_handler},
591 {BWRITERSIO_SGE, instr_handler},
592 {BWRITERSIO_ABS, instr_handler},
593 {BWRITERSIO_EXP, instr_handler},
594 {BWRITERSIO_LOG, instr_handler},
595 {BWRITERSIO_EXPP, instr_handler},
596 {BWRITERSIO_LOGP, instr_handler},
597 {BWRITERSIO_DST, instr_handler},
598 {BWRITERSIO_LRP, instr_handler},
599 {BWRITERSIO_FRC, instr_handler},
600 {BWRITERSIO_CRS, instr_handler},
601 {BWRITERSIO_SGN, instr_handler},
602 {BWRITERSIO_NRM, instr_handler},
603 {BWRITERSIO_SINCOS, instr_handler},
604 {BWRITERSIO_M4x4, instr_handler},
605 {BWRITERSIO_M4x3, instr_handler},
606 {BWRITERSIO_M3x4, instr_handler},
607 {BWRITERSIO_M3x3, instr_handler},
608 {BWRITERSIO_M3x2, instr_handler},
609 {BWRITERSIO_LIT, instr_handler},
610 {BWRITERSIO_POW, instr_handler},
611 {BWRITERSIO_MOVA, instr_handler},
613 {BWRITERSIO_CALL, instr_handler},
614 {BWRITERSIO_CALLNZ, instr_handler},
615 {BWRITERSIO_REP, instr_handler},
616 {BWRITERSIO_ENDREP, instr_handler},
617 {BWRITERSIO_IF, instr_handler},
618 {BWRITERSIO_LABEL, instr_handler},
619 {BWRITERSIO_IFC, instr_handler},
620 {BWRITERSIO_ELSE, instr_handler},
621 {BWRITERSIO_ENDIF, instr_handler},
622 {BWRITERSIO_BREAK, instr_handler},
623 {BWRITERSIO_BREAKC, instr_handler},
624 {BWRITERSIO_LOOP, instr_handler},
625 {BWRITERSIO_RET, instr_handler},
626 {BWRITERSIO_ENDLOOP, instr_handler},
628 {BWRITERSIO_SETP, instr_handler},
629 {BWRITERSIO_BREAKP, instr_handler},
630 {BWRITERSIO_TEXLDL, instr_handler},
632 {BWRITERSIO_END, NULL},
635 static const struct bytecode_backend vs_3_backend = {
644 static const struct instr_handler_table ps_3_handlers[] = {
645 {BWRITERSIO_ADD, instr_handler},
646 {BWRITERSIO_NOP, instr_handler},
647 {BWRITERSIO_MOV, instr_handler},
648 {BWRITERSIO_SUB, instr_handler},
649 {BWRITERSIO_MAD, instr_handler},
650 {BWRITERSIO_MUL, instr_handler},
651 {BWRITERSIO_RCP, instr_handler},
652 {BWRITERSIO_RSQ, instr_handler},
653 {BWRITERSIO_DP3, instr_handler},
654 {BWRITERSIO_DP4, instr_handler},
655 {BWRITERSIO_MIN, instr_handler},
656 {BWRITERSIO_MAX, instr_handler},
657 {BWRITERSIO_ABS, instr_handler},
658 {BWRITERSIO_EXP, instr_handler},
659 {BWRITERSIO_LOG, instr_handler},
660 {BWRITERSIO_EXPP, instr_handler},
661 {BWRITERSIO_LOGP, instr_handler},
662 {BWRITERSIO_LRP, instr_handler},
663 {BWRITERSIO_FRC, instr_handler},
664 {BWRITERSIO_CRS, instr_handler},
665 {BWRITERSIO_NRM, instr_handler},
666 {BWRITERSIO_SINCOS, instr_handler},
667 {BWRITERSIO_M4x4, instr_handler},
668 {BWRITERSIO_M4x3, instr_handler},
669 {BWRITERSIO_M3x4, instr_handler},
670 {BWRITERSIO_M3x3, instr_handler},
671 {BWRITERSIO_M3x2, instr_handler},
672 {BWRITERSIO_POW, instr_handler},
673 {BWRITERSIO_DP2ADD, instr_handler},
674 {BWRITERSIO_CMP, instr_handler},
676 {BWRITERSIO_CALL, instr_handler},
677 {BWRITERSIO_CALLNZ, instr_handler},
678 {BWRITERSIO_REP, instr_handler},
679 {BWRITERSIO_ENDREP, instr_handler},
680 {BWRITERSIO_IF, instr_handler},
681 {BWRITERSIO_LABEL, instr_handler},
682 {BWRITERSIO_IFC, instr_handler},
683 {BWRITERSIO_ELSE, instr_handler},
684 {BWRITERSIO_ENDIF, instr_handler},
685 {BWRITERSIO_BREAK, instr_handler},
686 {BWRITERSIO_BREAKC, instr_handler},
687 {BWRITERSIO_LOOP, instr_handler},
688 {BWRITERSIO_RET, instr_handler},
689 {BWRITERSIO_ENDLOOP, instr_handler},
691 {BWRITERSIO_SETP, instr_handler},
692 {BWRITERSIO_BREAKP, instr_handler},
693 {BWRITERSIO_TEXLDL, instr_handler},
695 {BWRITERSIO_TEX, instr_handler},
696 {BWRITERSIO_TEXLDP, instr_handler},
697 {BWRITERSIO_TEXLDB, instr_handler},
698 {BWRITERSIO_TEXKILL, instr_handler},
699 {BWRITERSIO_DSX, instr_handler},
700 {BWRITERSIO_DSY, instr_handler},
701 {BWRITERSIO_TEXLDD, instr_handler},
703 {BWRITERSIO_END, NULL},
706 static const struct bytecode_backend ps_3_backend = {
715 static void init_vs30_dx9_writer(struct bc_writer *writer) {
716 TRACE("Creating DirectX9 vertex shader 3.0 writer\n");
717 writer->funcs = &vs_3_backend;
720 static void init_ps30_dx9_writer(struct bc_writer *writer) {
721 TRACE("Creating DirectX9 pixel shader 3.0 writer\n");
722 writer->funcs = &ps_3_backend;
725 static struct bc_writer *create_writer(DWORD version, DWORD dxversion) {
726 struct bc_writer *ret = asm_alloc(sizeof(*ret));
729 WARN("Failed to allocate a bytecode writer instance\n");
734 case BWRITERVS_VERSION(1, 0):
736 WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion);
739 /* TODO: Set the appropriate writer backend */
741 case BWRITERVS_VERSION(1, 1):
743 WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion);
746 /* TODO: Set the appropriate writer backend */
748 case BWRITERVS_VERSION(2, 0):
750 WARN("Unsupported dxversion for vertex shader 2.0 requested: %u\n", dxversion);
753 /* TODO: Set the appropriate writer backend */
755 case BWRITERVS_VERSION(2, 1):
757 WARN("Unsupported dxversion for vertex shader 2.x requested: %u\n", dxversion);
760 /* TODO: Set the appropriate writer backend */
762 case BWRITERVS_VERSION(3, 0):
764 WARN("Unsupported dxversion for vertex shader 3.0 requested: %u\n", dxversion);
767 init_vs30_dx9_writer(ret);
770 case BWRITERPS_VERSION(1, 0):
772 WARN("Unsupported dxversion for pixel shader 1.0 requested: %u\n", dxversion);
775 /* TODO: Set the appropriate writer backend */
777 case BWRITERPS_VERSION(1, 1):
779 WARN("Unsupported dxversion for pixel shader 1.1 requested: %u\n", dxversion);
782 /* TODO: Set the appropriate writer backend */
784 case BWRITERPS_VERSION(1, 2):
786 WARN("Unsupported dxversion for pixel shader 1.2 requested: %u\n", dxversion);
789 /* TODO: Set the appropriate writer backend */
791 case BWRITERPS_VERSION(1, 3):
793 WARN("Unsupported dxversion for pixel shader 1.3 requested: %u\n", dxversion);
796 /* TODO: Set the appropriate writer backend */
798 case BWRITERPS_VERSION(1, 4):
800 WARN("Unsupported dxversion for pixel shader 1.4 requested: %u\n", dxversion);
803 /* TODO: Set the appropriate writer backend */
806 case BWRITERPS_VERSION(2, 0):
808 WARN("Unsupported dxversion for pixel shader 2.0 requested: %u\n", dxversion);
811 /* TODO: Set the appropriate writer backend */
814 case BWRITERPS_VERSION(2, 1):
816 WARN("Unsupported dxversion for pixel shader 2.x requested: %u\n", dxversion);
819 /* TODO: Set the appropriate writer backend */
822 case BWRITERPS_VERSION(3, 0):
824 WARN("Unsupported dxversion for pixel shader 3.0 requested: %u\n", dxversion);
827 init_ps30_dx9_writer(ret);
831 WARN("Unexpected shader version requested: %08x\n", version);
834 ret->version = version;
842 static HRESULT call_instr_handler(struct bc_writer *writer,
843 const struct instruction *instr,
844 struct bytecode_buffer *buffer) {
847 while(writer->funcs->instructions[i].opcode != BWRITERSIO_END) {
848 if(instr->opcode == writer->funcs->instructions[i].opcode) {
849 if(!writer->funcs->instructions[i].func) {
850 WARN("Opcode %u not supported by this profile\n", instr->opcode);
853 writer->funcs->instructions[i].func(writer, instr, buffer);
859 FIXME("Unhandled instruction %u\n", instr->opcode);
863 /* SlWriteBytecode (wineshader.@)
865 * Writes shader version specific bytecode from the shader passed in.
866 * The returned bytecode can be passed to the Direct3D runtime like
867 * IDirect3DDevice9::Create*Shader.
870 * shader: Shader to translate into bytecode
871 * version: Shader version to generate(d3d version token)
872 * dxversion: DirectX version the code targets
873 * result: the resulting shader bytecode
878 DWORD SlWriteBytecode(const struct bwriter_shader *shader, int dxversion, DWORD **result) {
879 struct bc_writer *writer;
880 struct bytecode_buffer *buffer = NULL;
885 ERR("NULL shader structure, aborting\n");
888 writer = create_writer(shader->version, dxversion);
892 WARN("Could not create a bytecode writer instance. Either unsupported version\n");
893 WARN("or out of memory\n");
898 buffer = allocate_buffer();
900 WARN("Failed to allocate a buffer for the shader bytecode\n");
905 writer->funcs->header(writer, shader, buffer);
906 if(FAILED(writer->state)) {
911 for(i = 0; i < shader->num_instrs; i++) {
912 hr = call_instr_handler(writer, shader->instr[i], buffer);
918 if(FAILED(writer->state)) {
923 writer->funcs->end(writer, shader, buffer);
925 if(FAILED(buffer->state)) {
930 /* Cut off unneeded memory from the result buffer */
931 *result = asm_realloc(buffer->data,
932 sizeof(DWORD) * buffer->size);
934 *result = buffer->data;
941 asm_free(buffer->data);
948 void SlDeleteShader(struct bwriter_shader *shader) {
951 TRACE("Deleting shader %p\n", shader);
953 for(i = 0; i < shader->num_cf; i++) {
954 asm_free(shader->constF[i]);
956 asm_free(shader->constF);
957 for(i = 0; i < shader->num_ci; i++) {
958 asm_free(shader->constI[i]);
960 asm_free(shader->constI);
961 for(i = 0; i < shader->num_cb; i++) {
962 asm_free(shader->constB[i]);
964 asm_free(shader->constB);
966 asm_free(shader->inputs);
967 asm_free(shader->outputs);
968 asm_free(shader->samplers);
970 for(i = 0; i < shader->num_instrs; i++) {
971 for(j = 0; j < shader->instr[i]->num_srcs; j++) {
972 asm_free(shader->instr[i]->src[j].rel_reg);
974 asm_free(shader->instr[i]->src);
975 asm_free(shader->instr[i]);
977 asm_free(shader->instr);