Module: wine Branch: master Commit: c1f7faca453489b056a7cd18302a00793f2366b6 URL: http://source.winehq.org/git/wine.git/?a=commit;h=c1f7faca453489b056a7cd1830...
Author: Matteo Bruni matteo.mystral@gmail.com Date: Tue May 18 14:11:42 2010 +0200
d3dx9: Add some version-specific checks in the shader assembler.
---
dlls/d3dx9_36/asmparser.c | 97 ++++++++++++++++++++++++++++++++++++++ dlls/d3dx9_36/d3dx9_36_private.h | 10 ++++ dlls/d3dx9_36/tests/asm.c | 6 ++ 3 files changed, 113 insertions(+), 0 deletions(-)
diff --git a/dlls/d3dx9_36/asmparser.c b/dlls/d3dx9_36/asmparser.c index d1d75ba..bcdc85a 100644 --- a/dlls/d3dx9_36/asmparser.c +++ b/dlls/d3dx9_36/asmparser.c @@ -153,15 +153,112 @@ static void asmparser_instr(struct asm_parser *This, DWORD opcode, } }
+/* Checks for unsupported source modifiers in VS (all versions) or + PS 2.0 and newer */ +static void check_legacy_srcmod(struct asm_parser *This, DWORD srcmod) { + if(srcmod == BWRITERSPSM_BIAS || srcmod == BWRITERSPSM_BIASNEG || + srcmod == BWRITERSPSM_SIGN || srcmod == BWRITERSPSM_SIGNNEG || + srcmod == BWRITERSPSM_COMP || srcmod == BWRITERSPSM_X2 || + srcmod == BWRITERSPSM_X2NEG || srcmod == BWRITERSPSM_DZ || + srcmod == BWRITERSPSM_DW) { + asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n", + This->line_no, + debug_print_srcmod(srcmod)); + set_parse_status(This, PARSE_ERR); + } +} + +static void check_loop_swizzle(struct asm_parser *This, + const struct shader_reg *src) { + if((src->type == BWRITERSPR_LOOP && src->swizzle != BWRITERVS_NOSWIZZLE) || + (src->rel_reg && src->rel_reg->type == BWRITERSPR_LOOP && + src->rel_reg->swizzle != BWRITERVS_NOSWIZZLE)) { + asmparser_message(This, "Line %u: Swizzle not allowed on aL register\n", This->line_no); + set_parse_status(This, PARSE_ERR); + } +} + +static void check_shift_dstmod(struct asm_parser *This, DWORD shift) { + if(shift != 0) { + asmparser_message(This, "Line %u: Shift modifiers not supported in this shader version\n", + This->line_no); + set_parse_status(This, PARSE_ERR); + } +} + +static void check_ps_dstmod(struct asm_parser *This, DWORD dstmod) { + if(dstmod == BWRITERSPDM_PARTIALPRECISION || + dstmod == BWRITERSPDM_MSAMPCENTROID) { + asmparser_message(This, "Line %u: Instruction modifier %s not supported in this shader version\n", + This->line_no, + debug_print_dstmod(dstmod)); + set_parse_status(This, PARSE_ERR); + } +} + +struct allowed_reg_type { + DWORD type; + DWORD count; +}; + +static BOOL check_reg_type(const struct shader_reg *reg, + const struct allowed_reg_type *allowed) { + unsigned int i = 0; + + while(allowed[i].type != ~0U) { + if(reg->type == allowed[i].type) { + if(reg->rel_reg) return TRUE; /* The relative addressing register + can have a negative value, we + can't check the register index */ + if(reg->regnum < allowed[i].count) return TRUE; + return FALSE; + } + i++; + } + return FALSE; +} + +/* Native assembler doesn't do separate checks for src and dst registers */ +static const struct allowed_reg_type vs_3_reg_allowed[] = { + { BWRITERSPR_TEMP, 32 }, + { BWRITERSPR_INPUT, 16 }, + { BWRITERSPR_CONST, ~0U }, + { BWRITERSPR_ADDR, 1 }, + { BWRITERSPR_CONSTBOOL, 16 }, + { BWRITERSPR_CONSTINT, 16 }, + { BWRITERSPR_LOOP, 1 }, + { BWRITERSPR_LABEL, 2048 }, + { BWRITERSPR_PREDICATE, 1 }, + { BWRITERSPR_SAMPLER, 4 }, + { BWRITERSPR_OUTPUT, 12 }, + { ~0U, 0 } /* End tag */ +}; + static void asmparser_srcreg_vs_3(struct asm_parser *This, struct instruction *instr, int num, const struct shader_reg *src) { + if(!check_reg_type(src, vs_3_reg_allowed)) { + asmparser_message(This, "Line %u: Source register %s not supported in VS 3.0\n", + This->line_no, + debug_print_srcreg(src, ST_VERTEX)); + set_parse_status(This, PARSE_ERR); + } + check_loop_swizzle(This, src); + check_legacy_srcmod(This, src->srcmod); memcpy(&instr->src[num], src, sizeof(*src)); }
static void asmparser_dstreg_vs_3(struct asm_parser *This, struct instruction *instr, const struct shader_reg *dst) { + if(!check_reg_type(dst, vs_3_reg_allowed)) { + asmparser_message(This, "Line %u: Destination register %s not supported in VS 3.0\n", + This->line_no, + debug_print_dstreg(dst, ST_VERTEX)); + set_parse_status(This, PARSE_ERR); + } + check_ps_dstmod(This, instr->dstmod); + check_shift_dstmod(This, instr->shift); memcpy(&instr->dst, dst, sizeof(*dst)); instr->has_dst = TRUE; } diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h index a12cb99..ffecd31 100644 --- a/dlls/d3dx9_36/d3dx9_36_private.h +++ b/dlls/d3dx9_36/d3dx9_36_private.h @@ -371,6 +371,7 @@ struct bc_writer { };
/* Debug utility routines */ +const char *debug_print_srcmod(DWORD mod); const char *debug_print_dstmod(DWORD mod); const char *debug_print_dstreg(const struct shader_reg *reg, shader_type st); const char *debug_print_srcreg(const struct shader_reg *reg, shader_type st); @@ -510,6 +511,15 @@ typedef enum _BWRITERSAMPLER_TEXTURE_TYPE { typedef enum _BWRITERSHADER_PARAM_SRCMOD_TYPE { BWRITERSPSM_NONE = 0, BWRITERSPSM_NEG, + BWRITERSPSM_BIAS, + BWRITERSPSM_BIASNEG, + BWRITERSPSM_SIGN, + BWRITERSPSM_SIGNNEG, + BWRITERSPSM_COMP, + BWRITERSPSM_X2, + BWRITERSPSM_X2NEG, + BWRITERSPSM_DZ, + BWRITERSPSM_DW, BWRITERSPSM_ABS, BWRITERSPSM_ABSNEG, BWRITERSPSM_NOT, diff --git a/dlls/d3dx9_36/tests/asm.c b/dlls/d3dx9_36/tests/asm.c index 8a79dd4..b4e0ee5 100644 --- a/dlls/d3dx9_36/tests/asm.c +++ b/dlls/d3dx9_36/tests/asm.c @@ -1206,6 +1206,12 @@ static void failure_test(void) { /* shader 22: register r5 doesn't exist in PS < 1.4 */ "ps_1_3\n" "mov r5, r0\n", + /* shader 23: can't declare output registers in a pixel shader */ + "ps_3_0\n" + "dcl_positiont o0\n", + /* shader 24: _pp instruction modifier not allowed in vertex shaders */ + "vs_3_0\n" + "add_pp r0, r0, r1\n", }; HRESULT hr; unsigned int i;