[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