wined3d: Add a function to read an opcode from SM1-3 bytecode.
Henri Verbeet
hverbeet at codeweavers.com
Fri Apr 24 02:17:58 CDT 2009
---
dlls/wined3d/baseshader.c | 246 ++++++++++++++++++++++++---------------------
1 files changed, 131 insertions(+), 115 deletions(-)
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index a7c2a50..db510bf 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -92,6 +92,120 @@ typedef enum _WINED3DSHADER_ADDRESSMODE_TYPE
static void shader_dump_param(const DWORD param, const DWORD addr_token, int input, DWORD shader_version);
+/* Read a parameter opcode from the input stream,
+ * and possibly a relative addressing token.
+ * Return the number of tokens read */
+static int shader_get_param(const DWORD *ptr, DWORD shader_version, DWORD *token, DWORD *addr_token)
+{
+ UINT count = 1;
+
+ *token = *ptr;
+
+ /* PS >= 3.0 have relative addressing (with token)
+ * VS >= 2.0 have relative addressing (with token)
+ * VS >= 1.0 < 2.0 have relative addressing (without token)
+ * The version check below should work in general */
+ if (*ptr & WINED3DSHADER_ADDRMODE_RELATIVE)
+ {
+ if (WINED3DSHADER_VERSION_MAJOR(shader_version) < 2)
+ {
+ *addr_token = (1 << 31)
+ | ((WINED3DSPR_ADDR << WINED3DSP_REGTYPE_SHIFT2) & WINED3DSP_REGTYPE_MASK2)
+ | ((WINED3DSPR_ADDR << WINED3DSP_REGTYPE_SHIFT) & WINED3DSP_REGTYPE_MASK)
+ | (WINED3DSP_NOSWIZZLE << WINED3DSP_SWIZZLE_SHIFT);
+ }
+ else
+ {
+ *addr_token = *(ptr + 1);
+ ++count;
+ }
+ }
+
+ return count;
+}
+
+static const SHADER_OPCODE *shader_get_opcode(const SHADER_OPCODE *opcode_table, DWORD shader_version, DWORD code)
+{
+ DWORD i = 0;
+
+ /** TODO: use dichotomic search */
+ while (opcode_table[i].name)
+ {
+ if ((code & WINED3DSI_OPCODE_MASK) == opcode_table[i].opcode
+ && shader_version >= opcode_table[i].min_version
+ && (!opcode_table[i].max_version || shader_version <= opcode_table[i].max_version))
+ {
+ return &opcode_table[i];
+ }
+ ++i;
+ }
+
+ FIXME("Unsupported opcode %#x(%d) masked %#x, shader version %#x\n",
+ code, code, code & WINED3DSI_OPCODE_MASK, shader_version);
+
+ return NULL;
+}
+
+/* Return the number of parameters to skip for an opcode */
+static inline int shader_skip_opcode(const SHADER_OPCODE *opcode_info, DWORD opcode_token, DWORD shader_version)
+{
+ /* Shaders >= 2.0 may contain address tokens, but fortunately they
+ * have a useful length mask - use it here. Shaders 1.0 contain no such tokens */
+ return (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 2)
+ ? ((opcode_token & WINED3DSI_INSTLENGTH_MASK) >> WINED3DSI_INSTLENGTH_SHIFT) : opcode_info->num_params;
+}
+
+/* Read the parameters of an unrecognized opcode from the input stream
+ * Return the number of tokens read.
+ *
+ * Note: This function assumes source or destination token format.
+ * It will not work with specially-formatted tokens like DEF or DCL,
+ * but hopefully those would be recognized */
+static int shader_skip_unrecognized(const DWORD *ptr, DWORD shader_version)
+{
+ int tokens_read = 0;
+ int i = 0;
+
+ /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
+ while (*ptr & 0x80000000)
+ {
+ DWORD token, addr_token = 0;
+ tokens_read += shader_get_param(ptr, shader_version, &token, &addr_token);
+ ptr += tokens_read;
+
+ FIXME("Unrecognized opcode param: token=0x%08x addr_token=0x%08x name=", token, addr_token);
+ shader_dump_param(token, addr_token, i, shader_version);
+ FIXME("\n");
+ ++i;
+ }
+ return tokens_read;
+}
+
+static void shader_sm1_read_opcode(const DWORD **ptr, struct wined3d_shader_instruction *ins, UINT *param_size,
+ const SHADER_OPCODE *opcode_table, DWORD shader_version)
+{
+ const SHADER_OPCODE *opcode_info;
+ DWORD opcode_token;
+
+ opcode_token = *(*ptr)++;
+ opcode_info = shader_get_opcode(opcode_table, shader_version, opcode_token);
+ if (!opcode_info)
+ {
+ FIXME("Unrecognized opcode: token=0x%08x\n", opcode_token);
+ ins->handler_idx = WINED3DSIH_TABLE_SIZE;
+ *param_size = shader_skip_unrecognized(*ptr, shader_version);
+ return;
+ }
+
+ ins->handler_idx = opcode_info->handler_idx;
+ ins->flags = (opcode_token & WINED3D_OPCODESPECIFICCONTROL_MASK) >> WINED3D_OPCODESPECIFICCONTROL_SHIFT;
+ ins->coissue = opcode_token & WINED3DSI_COISSUE;
+ ins->predicate = opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED;
+ ins->dst_count = opcode_info->dst_token ? 1 : 0;
+ ins->src_count = opcode_info->num_params - opcode_info->dst_token;
+ *param_size = shader_skip_opcode(opcode_info, opcode_token, shader_version);
+}
+
static inline BOOL shader_is_version_token(DWORD token) {
return shader_is_pshader_version(token) ||
shader_is_vshader_version(token);
@@ -179,96 +293,6 @@ static inline BOOL shader_is_comment(DWORD token)
return WINED3DSIO_COMMENT == (token & WINED3DSI_OPCODE_MASK);
}
-static const SHADER_OPCODE *shader_get_opcode(const SHADER_OPCODE *opcode_table, DWORD shader_version, DWORD code)
-{
- DWORD i = 0;
-
- /** TODO: use dichotomic search */
- while (opcode_table[i].name)
- {
- if ((code & WINED3DSI_OPCODE_MASK) == opcode_table[i].opcode
- && shader_version >= opcode_table[i].min_version
- && (!opcode_table[i].max_version || shader_version <= opcode_table[i].max_version))
- {
- return &opcode_table[i];
- }
- ++i;
- }
-
- FIXME("Unsupported opcode %#x(%d) masked %#x, shader version %#x\n",
- code, code, code & WINED3DSI_OPCODE_MASK, shader_version);
-
- return NULL;
-}
-
-/* Read a parameter opcode from the input stream,
- * and possibly a relative addressing token.
- * Return the number of tokens read */
-static int shader_get_param(const DWORD *pToken, DWORD shader_version, DWORD *param, DWORD *addr_token)
-{
- UINT count = 1;
-
- *param = *pToken;
-
- /* PS >= 3.0 have relative addressing (with token)
- * VS >= 2.0 have relative addressing (with token)
- * VS >= 1.0 < 2.0 have relative addressing (without token)
- * The version check below should work in general */
- if (*pToken & WINED3DSHADER_ADDRMODE_RELATIVE)
- {
- if (WINED3DSHADER_VERSION_MAJOR(shader_version) < 2)
- {
- *addr_token = (1 << 31)
- | ((WINED3DSPR_ADDR << WINED3DSP_REGTYPE_SHIFT2) & WINED3DSP_REGTYPE_MASK2)
- | ((WINED3DSPR_ADDR << WINED3DSP_REGTYPE_SHIFT) & WINED3DSP_REGTYPE_MASK)
- | (WINED3DSP_NOSWIZZLE << WINED3DSP_SWIZZLE_SHIFT);
- }
- else
- {
- *addr_token = *(pToken + 1);
- ++count;
- }
- }
-
- return count;
-}
-
-/* Return the number of parameters to skip for an opcode */
-static inline int shader_skip_opcode(const SHADER_OPCODE *curOpcode, DWORD opcode_token, DWORD shader_version)
-{
- /* Shaders >= 2.0 may contain address tokens, but fortunately they
- * have a useful length mask - use it here. Shaders 1.0 contain no such tokens */
- return (WINED3DSHADER_VERSION_MAJOR(shader_version) >= 2)
- ? ((opcode_token & WINED3DSI_INSTLENGTH_MASK) >> WINED3DSI_INSTLENGTH_SHIFT) : curOpcode->num_params;
-}
-
-/* Read the parameters of an unrecognized opcode from the input stream
- * Return the number of tokens read.
- *
- * Note: This function assumes source or destination token format.
- * It will not work with specially-formatted tokens like DEF or DCL,
- * but hopefully those would be recognized */
-static int shader_skip_unrecognized(const DWORD *pToken, DWORD shader_version)
-{
- int tokens_read = 0;
- int i = 0;
-
- /* TODO: Think of a good name for 0x80000000 and replace it with a constant */
- while (*pToken & 0x80000000) {
-
- DWORD param, addr_token = 0;
- tokens_read += shader_get_param(pToken, shader_version, ¶m, &addr_token);
- pToken += tokens_read;
-
- FIXME("Unrecognized opcode param: token=0x%08x "
- "addr_token=0x%08x name=", param, addr_token);
- shader_dump_param(param, addr_token, i, shader_version);
- FIXME("\n");
- ++i;
- }
- return tokens_read;
-}
-
/* Convert floating point offset relative
* to a register file to an absolute offset for float constants */
static unsigned int shader_get_float_offset(const DWORD reg)
@@ -897,7 +921,6 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
struct wined3d_shader_instruction ins;
struct wined3d_shader_context ctx;
const DWORD *pToken = pFunction;
- const SHADER_OPCODE *curOpcode;
SHADER_HANDLER hw_fct;
DWORD i;
@@ -919,7 +942,7 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
while (WINED3DPS_END() != *pToken)
{
- DWORD opcode_token;
+ UINT param_size;
/* Skip comment tokens */
if (shader_is_comment(*pToken))
@@ -930,47 +953,41 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
}
/* Read opcode */
- opcode_token = *pToken++;
- curOpcode = shader_get_opcode(opcode_table, shader_version, opcode_token);
+ shader_sm1_read_opcode(&pToken, &ins, ¶m_size, opcode_table, shader_version);
/* Unknown opcode and its parameters */
- if (!curOpcode)
+ if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
{
- FIXME("Unrecognized opcode: token=0x%08x\n", opcode_token);
- pToken += shader_skip_unrecognized(pToken, shader_version);
+ TRACE("Skipping unrecognized instruction.\n");
+ pToken += param_size;
continue;
}
/* Nothing to do */
- if (WINED3DSIO_DCL == curOpcode->opcode
- || WINED3DSIO_NOP == curOpcode->opcode
- || WINED3DSIO_DEF == curOpcode->opcode
- || WINED3DSIO_DEFI == curOpcode->opcode
- || WINED3DSIO_DEFB == curOpcode->opcode
- || WINED3DSIO_PHASE == curOpcode->opcode
- || WINED3DSIO_RET == curOpcode->opcode)
+ if (ins.handler_idx == WINED3DSIH_DCL
+ || ins.handler_idx == WINED3DSIH_NOP
+ || ins.handler_idx == WINED3DSIH_DEF
+ || ins.handler_idx == WINED3DSIH_DEFI
+ || ins.handler_idx == WINED3DSIH_DEFB
+ || ins.handler_idx == WINED3DSIH_PHASE
+ || ins.handler_idx == WINED3DSIH_RET)
{
- pToken += shader_skip_opcode(curOpcode, opcode_token, shader_version);
+ pToken += param_size;
continue;
}
/* Select handler */
- hw_fct = handler_table[curOpcode->handler_idx];
+ hw_fct = handler_table[ins.handler_idx];
/* Unhandled opcode */
if (!hw_fct)
{
- FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
- pToken += shader_skip_opcode(curOpcode, opcode_token, shader_version);
+ FIXME("Backend can't handle opcode %#x\n", ins.handler_idx);
+ pToken += param_size;
continue;
}
- ins.handler_idx = curOpcode->handler_idx;
- ins.flags = (opcode_token & WINED3D_OPCODESPECIFICCONTROL_MASK) >> WINED3D_OPCODESPECIFICCONTROL_SHIFT;
- ins.coissue = opcode_token & WINED3DSI_COISSUE;
-
/* Destination token */
- ins.dst_count = curOpcode->dst_token ? 1 : 0;
if (ins.dst_count)
{
DWORD param, addr_param;
@@ -988,10 +1005,9 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
}
/* Predication token */
- if (opcode_token & WINED3DSHADER_INSTRUCTION_PREDICATED) ins.predicate = *pToken++;
+ if (ins.predicate) ins.predicate = *pToken++;
/* Other source tokens */
- ins.src_count = curOpcode->num_params - curOpcode->dst_token;
for (i = 0; i < ins.src_count; ++i)
{
DWORD param, addr_param;
--
1.6.0.6
--------------060001020802040502080706--
More information about the wine-patches
mailing list