From dc1fa014ac59f635884c0aeb0117a31d26e1ab4a Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Fri, 14 May 2010 17:21:42 +0200 Subject: [PATCH] d3dx9: Add DEF instruction support in the shader assembler. --- dlls/d3dx9_36/asmparser.c | 12 ++++++++ dlls/d3dx9_36/asmshader.l | 1 + dlls/d3dx9_36/asmshader.y | 5 ++++ dlls/d3dx9_36/asmutils.c | 2 ++ dlls/d3dx9_36/bytecodewriter.c | 60 ++++++++++++++++++++++++++++++++++++++++ dlls/d3dx9_36/d3dx9_36_private.h | 14 ++++++++++ dlls/d3dx9_36/tests/asm.c | 6 ++++ 7 files changed, 100 insertions(+) diff --git a/dlls/d3dx9_36/asmparser.c b/dlls/d3dx9_36/asmparser.c index 6d0d31f065a..a2d57e0619e 100644 --- a/dlls/d3dx9_36/asmparser.c +++ b/dlls/d3dx9_36/asmparser.c @@ -38,6 +38,16 @@ static void asmparser_end(struct asm_parser *This) { TRACE("Finalizing shader\n"); } +static void asmparser_constF(struct asm_parser *This, DWORD reg, float x, float y, float z, float w) { + if(!This->shader) return; + TRACE("Adding float constant %u at pos %u\n", reg, This->shader->num_cf); + TRACE_(parsed_shader)("def c%u, %f, %f, %f, %f\n", reg, x, y, z, w); + if(!add_constF(This->shader, reg, x, y, z, w)) { + ERR("Out of memory\n"); + set_parse_status(This, PARSE_ERR); + } +} + static void asmparser_dcl_output(struct asm_parser *This, DWORD usage, DWORD num, const struct shader_reg *reg) { if(!This->shader) return; @@ -159,6 +169,8 @@ static void asmparser_coissue_unsupported(struct asm_parser *This) { } static const struct asmparser_backend parser_vs_3 = { + asmparser_constF, + asmparser_dstreg_vs_3, asmparser_srcreg_vs_3, diff --git a/dlls/d3dx9_36/asmshader.l b/dlls/d3dx9_36/asmshader.l index 9486b5333cf..690a5a7950a 100644 --- a/dlls/d3dx9_36/asmshader.l +++ b/dlls/d3dx9_36/asmshader.l @@ -138,6 +138,7 @@ m3x4 {return INSTR_M3x4; } m3x3 {return INSTR_M3x3; } m3x2 {return INSTR_M3x2; } dcl {return INSTR_DCL; } +def {return INSTR_DEF; } rep {return INSTR_REP; } endrep {return INSTR_ENDREP; } if {return INSTR_IF; } diff --git a/dlls/d3dx9_36/asmshader.y b/dlls/d3dx9_36/asmshader.y index a6ab57e9db2..bb4c43f8be5 100644 --- a/dlls/d3dx9_36/asmshader.y +++ b/dlls/d3dx9_36/asmshader.y @@ -123,6 +123,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) { %token INSTR_M3x3 %token INSTR_M3x2 %token INSTR_DCL +%token INSTR_DEF %token INSTR_REP %token INSTR_ENDREP %token INSTR_IF @@ -573,6 +574,10 @@ instruction: INSTR_ADD omods dreg ',' sregs asm_ctx.line_no); set_parse_status(&asm_ctx, PARSE_WARN); } + | INSTR_DEF REG_CONSTFLOAT ',' IMMVAL ',' IMMVAL ',' IMMVAL ',' IMMVAL + { + asm_ctx.funcs->constF(&asm_ctx, $2, $4.val, $6.val, $8.val, $10.val); + } | INSTR_REP sregs { TRACE("REP\n"); diff --git a/dlls/d3dx9_36/asmutils.c b/dlls/d3dx9_36/asmutils.c index c34f5f5669a..3772c5fb96d 100644 --- a/dlls/d3dx9_36/asmutils.c +++ b/dlls/d3dx9_36/asmutils.c @@ -191,6 +191,7 @@ DWORD d3d9_opcode(DWORD bwriter_opcode) { case BWRITERSIO_MOVA: return D3DSIO_MOVA; case BWRITERSIO_EXPP: return D3DSIO_EXPP; case BWRITERSIO_LOGP: return D3DSIO_LOGP; + case BWRITERSIO_DEF: return D3DSIO_DEF; case BWRITERSIO_SETP: return D3DSIO_SETP; case BWRITERSIO_TEXLDL: return D3DSIO_TEXLDL; case BWRITERSIO_BREAKP: return D3DSIO_BREAKP; @@ -456,6 +457,7 @@ const char *debug_print_opcode(DWORD opcode) { case BWRITERSIO_MOVA: return "mova"; case BWRITERSIO_EXPP: return "expp"; case BWRITERSIO_LOGP: return "logp"; + case BWRITERSIO_DEF: return "def"; case BWRITERSIO_SETP: return "setp"; case BWRITERSIO_TEXLDL: return "texldl"; case BWRITERSIO_BREAKP: return "breakp"; diff --git a/dlls/d3dx9_36/bytecodewriter.c b/dlls/d3dx9_36/bytecodewriter.c index 82a365537ba..c14f0223097 100644 --- a/dlls/d3dx9_36/bytecodewriter.c +++ b/dlls/d3dx9_36/bytecodewriter.c @@ -104,6 +104,42 @@ BOOL add_instruction(struct bwriter_shader *shader, struct instruction *instr) { return TRUE; } +BOOL add_constF(struct bwriter_shader *shader, DWORD reg, float x, float y, float z, float w) { + struct constant *newconst; + + if(shader->num_cf) { + struct constant **newarray; + newarray = asm_realloc(shader->constF, + sizeof(*shader->constF) * (shader->num_cf + 1)); + if(!newarray) { + ERR("Failed to grow the constants array\n"); + return FALSE; + } + shader->constF = newarray; + } else { + shader->constF = asm_alloc(sizeof(*shader->constF)); + if(!shader->constF) { + ERR("Failed to allocate the constants array\n"); + return FALSE; + } + } + + newconst = asm_alloc(sizeof(*newconst)); + if(!newconst) { + ERR("Failed to allocate a new constant\n"); + return FALSE; + } + newconst->regnum = reg; + newconst->value[0].f = x; + newconst->value[1].f = y; + newconst->value[2].f = z; + newconst->value[3].f = w; + shader->constF[shader->num_cf] = newconst; + + shader->num_cf++; + return TRUE; +} + BOOL record_declaration(struct bwriter_shader *shader, DWORD usage, DWORD usage_idx, BOOL output, DWORD regnum, DWORD writemask) { unsigned int *num; struct declaration **decl; @@ -262,6 +298,29 @@ static void write_declarations(struct bytecode_buffer *buffer, BOOL len, } } +static void write_constF(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) { + DWORD i; + DWORD instr_def = D3DSIO_DEF; + const DWORD reg = (1<<31) | + ((D3DSPR_CONST << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) | + D3DSP_WRITEMASK_ALL; + + if(len) { + instr_def |= 5 << D3DSI_INSTLENGTH_SHIFT; + } + + for(i = 0; i < shader->num_cf; i++) { + /* Write the DEF instruction */ + put_dword(buffer, instr_def); + + put_dword(buffer, reg | (shader->constF[i]->regnum & D3DSP_REGNUM_MASK)); + put_dword(buffer, shader->constF[i]->value[0].d); + put_dword(buffer, shader->constF[i]->value[1].d); + put_dword(buffer, shader->constF[i]->value[2].d); + put_dword(buffer, shader->constF[i]->value[3].d); + } +} + static void end(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) { put_dword(buffer, D3DSIO_END); } @@ -344,6 +403,7 @@ static void sm_3_header(struct bc_writer *This, const struct bwriter_shader *sha write_declarations(buffer, TRUE, shader->inputs, shader->num_inputs, D3DSPR_INPUT); write_declarations(buffer, TRUE, shader->outputs, shader->num_outputs, D3DSPR_OUTPUT); + write_constF(shader, buffer, TRUE); write_samplers(shader, buffer); return; } diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h index a102e65f749..c20119a0633 100644 --- a/dlls/d3dx9_36/d3dx9_36_private.h +++ b/dlls/d3dx9_36/d3dx9_36_private.h @@ -146,6 +146,16 @@ typedef enum BWRITER_COMPARISON_TYPE { BWRITER_COMPARISON_LE } BWRITER_COMPARISON_TYPE; +struct constant { + DWORD regnum; + union { + float f; + INT i; + BOOL b; + DWORD d; + } value[4]; +}; + struct shader_reg { DWORD type; DWORD regnum; @@ -243,6 +253,8 @@ struct src_regs { }; struct asmparser_backend { + void (*constF)(struct asm_parser *This, DWORD reg, float x, float y, float z, float w); + void (*dstreg)(struct asm_parser *This, struct instruction *instr, const struct shader_reg *dst); void (*srcreg)(struct asm_parser *This, struct instruction *instr, int num, @@ -268,6 +280,7 @@ struct asmparser_backend { struct instruction *alloc_instr(unsigned int srcs); BOOL add_instruction(struct bwriter_shader *shader, struct instruction *instr); +BOOL add_constF(struct bwriter_shader *shader, DWORD reg, float x, float y, float z, float w); BOOL record_declaration(struct bwriter_shader *shader, DWORD usage, DWORD usage_idx, BOOL output, DWORD regnum, DWORD writemask); BOOL record_sampler(struct bwriter_shader *shader, DWORD samptype, DWORD regnum); @@ -430,6 +443,7 @@ typedef enum _BWRITERSHADER_INSTRUCTION_OPCODE_TYPE { BWRITERSIO_EXPP, BWRITERSIO_LOGP, + BWRITERSIO_DEF, BWRITERSIO_SETP, BWRITERSIO_TEXLDL, BWRITERSIO_BREAKP, diff --git a/dlls/d3dx9_36/tests/asm.c b/dlls/d3dx9_36/tests/asm.c index 21adb8112be..8a79dd42df8 100644 --- a/dlls/d3dx9_36/tests/asm.c +++ b/dlls/d3dx9_36/tests/asm.c @@ -1074,6 +1074,12 @@ static void vs_3_0_test(void) { "sincos r0, r1\n", {0xfffe0300, 0x02000025, 0x800f0000, 0x80e40001, 0x0000ffff} }, + { /* shader 13 */ + "vs_3_0\n" + "def c0, 1.0f, 1.0f, 1.0f, 0.5f\n", + {0xfffe0300, 0x05000051, 0xa00f0000, 0x3f800000, 0x3f800000, 0x3f800000, + 0x3f000000, 0x0000ffff} + }, }; exec_tests("vs_3_0", tests, sizeof(tests) / sizeof(tests[0])); -- 2.11.4.GIT