d3dx9: Add some version-specific checks in the shader assembler.

Matteo Bruni matteo.mystral at gmail.com
Tue May 18 07:55:44 CDT 2010


Native assembler checks these conditions and errors out if they are
not met, so we have to do the same.
-------------- next part --------------
From 6e88557379f49b048042fb2870b0a1acd1c68e67 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Tue, 18 May 2010 14:11:42 +0200
Subject: 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;
-- 
1.6.4.4


More information about the wine-patches mailing list