[WINED3D 4/11] Do not rely on num_params to skip unhandled tokens in shaders 2.0

Ivan Gyurdiev ivg2 at cornell.edu
Wed May 17 01:00:47 CDT 2006


Pixel and vertex shader code depends very much on the num_params field 
of the instruction. This is unfortunate, because that doesn't work - 
shaders 2.0 and above do not keep the instruction size fixed, and can 
include various other tokens, which break down parsing completely. Each 
destination or source operand can have an extra relative addressing 
token following it, and there's also predication tokens optionally 
attached to the instruction.

This is the first of a several patches to remove the dependency on 
num_params. It adds a new function for skipping unhandled opcodes, which 
selects between using num_params, and using a field in the instruction 
token to check how long it is. The field is reserved for shaders 1.0.

-------------- next part --------------
---

 dlls/wined3d/baseshader.c |   28 ++++++++++++++++++++--------
 1 files changed, 20 insertions(+), 8 deletions(-)

8d4eb60ef818a0dc0e13859843798611ba1a6ff8
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index 79a47e6..6ea5e9d 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -85,6 +85,20 @@ const SHADER_OPCODE* shader_get_opcode(
     return NULL;
 }
 
+/* Return the number of parameters to skip for an opcode */
+static inline int shader_skip_opcode(
+    IWineD3DBaseShaderImpl* This,
+    const SHADER_OPCODE* curOpcode,
+    DWORD opcode_token) {
+
+   /* Shaders >= 2.0 may contain address tokens, but fortunately they
+    * have a useful legnth mask - use it here. Shaders 1.0 contain no such tokens */
+
+    return (D3DSHADER_VERSION_MAJOR(This->baseShader.hex_version) >= 2)?
+        ((opcode_token & D3DSI_INSTLENGTH_MASK) >> D3DSI_INSTLENGTH_SHIFT):
+        curOpcode->num_params;
+}
+
 /* Note: For vertex shaders,
  * texUsed = addrUsed, and 
  * D3DSPR_TEXTURE = D3DSPR_ADDR. 
@@ -424,6 +438,7 @@ void generate_base_shader(
     IWineD3DBaseShaderImpl* This = (IWineD3DBaseShaderImpl*) iface;
     const DWORD *pToken = pFunction;
     const SHADER_OPCODE *curOpcode = NULL;
+    DWORD opcode_token;
     DWORD i;
 
     /* Initialize current parsing state */
@@ -465,8 +480,8 @@ void generate_base_shader(
             }
 
             /* Read opcode */
-            curOpcode = shader_get_opcode(iface, *pToken);
-            ++pToken;
+            opcode_token = *pToken++;
+            curOpcode = shader_get_opcode(iface, opcode_token);
 
             /* Unknown opcode and its parameters */
             if (NULL == curOpcode) {
@@ -479,14 +494,14 @@ void generate_base_shader(
             } else if (USING_GLSL && curOpcode->hw_glsl_fct == NULL) {
 
                 FIXME("Token %s is not yet implemented with GLSL\n", curOpcode->name);
-                pToken += curOpcode->num_params;
+                pToken += shader_skip_opcode(This, curOpcode, opcode_token);
 
             /* Unhandled opcode in ARB */
             } else if ( !USING_GLSL && GLNAME_REQUIRE_GLSL == curOpcode->glname) {
 
                 FIXME("Token %s requires greater functionality than "
                     "Vertex or Fragment_Program_ARB supports\n", curOpcode->name);
-                pToken += curOpcode->num_params;
+                pToken += shader_skip_opcode(This, curOpcode, opcode_token);
 
             /* If a generator function is set for current shader target, use it */
             } else if ((!USING_GLSL && curOpcode->hw_fct != NULL) ||
@@ -515,13 +530,10 @@ void generate_base_shader(
 
             } else {
 
-                TRACE("Found opcode D3D:%s GL:%s, PARAMS:%d,\n",
-                curOpcode->name, curOpcode->glname, curOpcode->num_params);
-
                 /* Unless we encounter a no-op command, this opcode is unrecognized */
                 if (curOpcode->opcode != D3DSIO_NOP) {
                     FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
-                    pToken += curOpcode->num_params;
+                    pToken += shader_skip_opcode(This, curOpcode, opcode_token);
                 }
             }
         }
-- 
1.3.1



More information about the wine-patches mailing list