[PATCH 1/3] wined3d: Read complete shader instructions at a time.
Henri Verbeet
hverbeet at codeweavers.com
Tue Sep 4 13:15:08 CDT 2012
---
dlls/wined3d/shader.c | 235 ++++++++++++----------------------------
dlls/wined3d/shader_sm1.c | 126 +++++++++++++++------
dlls/wined3d/shader_sm4.c | 99 ++++++++++--------
dlls/wined3d/wined3d_private.h | 26 ++---
4 files changed, 224 insertions(+), 262 deletions(-)
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index 8b9b81c..d19b575 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -483,69 +483,57 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
struct wined3d_shader_instruction ins;
const char *comment;
UINT comment_size;
- UINT param_size;
/* Skip comments. */
fe->shader_read_comment(&ptr, &comment, &comment_size);
if (comment) continue;
/* Fetch opcode. */
- fe->shader_read_opcode(fe_data, &ptr, &ins, ¶m_size);
+ fe->shader_read_instruction(fe_data, &ptr, &ins);
/* Unhandled opcode, and its parameters. */
if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
{
TRACE("Skipping unrecognized instruction.\n");
- ptr += param_size;
continue;
}
/* Handle declarations. */
if (ins.handler_idx == WINED3DSIH_DCL)
{
- struct wined3d_shader_semantic semantic;
-
- fe->shader_read_semantic(&ptr, &semantic);
-
- switch (semantic.reg.reg.type)
+ switch (ins.semantic.reg.reg.type)
{
/* Mark input registers used. */
case WINED3DSPR_INPUT:
- reg_maps->input_registers |= 1 << semantic.reg.reg.idx;
- shader_signature_from_semantic(&input_signature[semantic.reg.reg.idx], &semantic);
+ reg_maps->input_registers |= 1 << ins.semantic.reg.reg.idx;
+ shader_signature_from_semantic(&input_signature[ins.semantic.reg.reg.idx], &ins.semantic);
break;
/* Vertex shader: mark 3.0 output registers used, save token. */
case WINED3DSPR_OUTPUT:
- reg_maps->output_registers |= 1 << semantic.reg.reg.idx;
- shader_signature_from_semantic(&output_signature[semantic.reg.reg.idx], &semantic);
- if (semantic.usage == WINED3D_DECL_USAGE_FOG)
+ reg_maps->output_registers |= 1 << ins.semantic.reg.reg.idx;
+ shader_signature_from_semantic(&output_signature[ins.semantic.reg.reg.idx], &ins.semantic);
+ if (ins.semantic.usage == WINED3D_DECL_USAGE_FOG)
reg_maps->fog = 1;
break;
/* Save sampler usage token. */
case WINED3DSPR_SAMPLER:
- reg_maps->sampler_type[semantic.reg.reg.idx] = semantic.sampler_type;
+ reg_maps->sampler_type[ins.semantic.reg.reg.idx] = ins.semantic.sampler_type;
break;
default:
- TRACE("Not recording DCL register type %#x.\n", semantic.reg.reg.type);
+ TRACE("Not recording DCL register type %#x.\n", ins.semantic.reg.reg.type);
break;
}
}
else if (ins.handler_idx == WINED3DSIH_DEF)
{
- struct wined3d_shader_src_param rel_addr;
- struct wined3d_shader_dst_param dst;
-
struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
if (!lconst) return E_OUTOFMEMORY;
- fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
- lconst->idx = dst.reg.idx;
-
- memcpy(lconst->value, ptr, 4 * sizeof(DWORD));
- ptr += 4;
+ lconst->idx = ins.dst[0].reg.idx;
+ memcpy(lconst->value, ins.src[0].reg.immconst_data, 4 * sizeof(DWORD));
/* In pixel shader 1.X shaders, the constants are clamped between [-1;1] */
if (shader_version.major == 1 && shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
@@ -565,51 +553,36 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
}
else if (ins.handler_idx == WINED3DSIH_DEFI)
{
- struct wined3d_shader_src_param rel_addr;
- struct wined3d_shader_dst_param dst;
-
struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
if (!lconst) return E_OUTOFMEMORY;
- fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
- lconst->idx = dst.reg.idx;
-
- memcpy(lconst->value, ptr, 4 * sizeof(DWORD));
- ptr += 4;
+ lconst->idx = ins.dst[0].reg.idx;
+ memcpy(lconst->value, ins.src[0].reg.immconst_data, 4 * sizeof(DWORD));
list_add_head(&shader->constantsI, &lconst->entry);
- reg_maps->local_int_consts |= (1 << dst.reg.idx);
+ reg_maps->local_int_consts |= (1 << lconst->idx);
}
else if (ins.handler_idx == WINED3DSIH_DEFB)
{
- struct wined3d_shader_src_param rel_addr;
- struct wined3d_shader_dst_param dst;
-
struct wined3d_shader_lconst *lconst = HeapAlloc(GetProcessHeap(), 0, sizeof(*lconst));
if (!lconst) return E_OUTOFMEMORY;
- fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
- lconst->idx = dst.reg.idx;
-
- memcpy(lconst->value, ptr, sizeof(DWORD));
- ++ptr;
+ lconst->idx = ins.dst[0].reg.idx;
+ memcpy(lconst->value, ins.src[0].reg.immconst_data, sizeof(DWORD));
list_add_head(&shader->constantsB, &lconst->entry);
- reg_maps->local_bool_consts |= (1 << dst.reg.idx);
+ reg_maps->local_bool_consts |= (1 << lconst->idx);
}
/* For subroutine prototypes. */
else if (ins.handler_idx == WINED3DSIH_LABEL)
{
- struct wined3d_shader_src_param src, rel_addr;
-
- fe->shader_read_src_param(fe_data, &ptr, &src, &rel_addr);
- reg_maps->labels |= 1 << src.reg.idx;
+ reg_maps->labels |= 1 << ins.src[0].reg.idx;
}
/* Set texture, address, temporary registers. */
else
{
BOOL color0_mov = FALSE;
- unsigned int i, limit;
+ unsigned int i;
/* This will loop over all the registers and try to
* make a bitmask of the ones we're interested in.
@@ -619,21 +592,16 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
* they are initialized (required by spec). */
for (i = 0; i < ins.dst_count; ++i)
{
- struct wined3d_shader_src_param dst_rel_addr;
- struct wined3d_shader_dst_param dst_param;
-
- fe->shader_read_dst_param(fe_data, &ptr, &dst_param, &dst_rel_addr);
-
- shader_record_register_usage(shader, reg_maps, &dst_param.reg, shader_version.type);
+ shader_record_register_usage(shader, reg_maps, &ins.dst[i].reg, shader_version.type);
/* WINED3DSPR_TEXCRDOUT is the same as WINED3DSPR_OUTPUT. _OUTPUT can be > MAX_REG_TEXCRD and
* is used in >= 3.0 shaders. Filter 3.0 shaders to prevent overflows, and also filter pixel
* shaders because TECRDOUT isn't used in them, but future register types might cause issues */
if (shader_version.type == WINED3D_SHADER_TYPE_VERTEX && shader_version.major < 3)
{
- UINT idx = dst_param.reg.idx;
+ UINT idx = ins.dst[i].reg.idx;
- switch (dst_param.reg.type)
+ switch (ins.dst[i].reg.type)
{
case WINED3DSPR_RASTOUT:
switch (idx)
@@ -664,29 +632,29 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
idx += 8;
if (reg_maps->output_registers & (1 << idx))
{
- output_signature[idx].mask |= dst_param.write_mask;
+ output_signature[idx].mask |= ins.dst[i].write_mask;
}
else
{
reg_maps->output_registers |= 1 << idx;
shader_signature_from_usage(&output_signature[idx],
- WINED3D_DECL_USAGE_COLOR, idx - 8, idx, dst_param.write_mask);
+ WINED3D_DECL_USAGE_COLOR, idx - 8, idx, ins.dst[i].write_mask);
}
}
break;
case WINED3DSPR_TEXCRDOUT:
- reg_maps->texcoord_mask[idx] |= dst_param.write_mask;
+ reg_maps->texcoord_mask[idx] |= ins.dst[i].write_mask;
if (reg_maps->output_registers & (1 << idx))
{
- output_signature[idx].mask |= dst_param.write_mask;
+ output_signature[idx].mask |= ins.dst[i].write_mask;
}
else
{
reg_maps->output_registers |= 1 << idx;
shader_signature_from_usage(&output_signature[idx],
- WINED3D_DECL_USAGE_TEXCOORD, idx, idx, dst_param.write_mask);
+ WINED3D_DECL_USAGE_TEXCOORD, idx, idx, ins.dst[i].write_mask);
}
break;
@@ -697,7 +665,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
if (shader_version.type == WINED3D_SHADER_TYPE_PIXEL)
{
- if (dst_param.reg.type == WINED3DSPR_COLOROUT && !dst_param.reg.idx)
+ if (ins.dst[i].reg.type == WINED3DSPR_COLOROUT && !ins.dst[i].reg.idx)
{
/* Many 2.0 and 3.0 pixel shaders end with a MOV from a temp register to
* COLOROUT 0. If we know this in advance, the ARB shader backend can skip
@@ -708,7 +676,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
* COLOROUT 0 is overwritten partially later, the marker is dropped again. */
shader->u.ps.color0_mov = FALSE;
if (ins.handler_idx == WINED3DSIH_MOV
- && dst_param.write_mask == WINED3DSP_WRITEMASK_ALL)
+ && ins.dst[i].write_mask == WINED3DSP_WRITEMASK_ALL)
{
/* Used later when the source register is read. */
color0_mov = TRUE;
@@ -717,8 +685,8 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
/* Also drop the MOV marker if the source register is overwritten prior to the shader
* end
*/
- else if (dst_param.reg.type == WINED3DSPR_TEMP
- && dst_param.reg.idx == shader->u.ps.color0_reg)
+ else if (ins.dst[i].reg.type == WINED3DSPR_TEMP
+ && ins.dst[i].reg.idx == shader->u.ps.color0_reg)
{
shader->u.ps.color0_mov = FALSE;
}
@@ -739,7 +707,7 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
|| ins.handler_idx == WINED3DSIH_TEXREG2RGB))
{
/* Fake sampler usage, only set reserved bit and type. */
- DWORD sampler_code = dst_param.reg.idx;
+ DWORD sampler_code = ins.dst[i].reg.idx;
TRACE("Setting fake 2D sampler for 1.x pixelshader.\n");
reg_maps->sampler_type[sampler_code] = WINED3DSTT_2D;
@@ -748,16 +716,16 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
if (ins.handler_idx == WINED3DSIH_TEXBEM
|| ins.handler_idx == WINED3DSIH_TEXBEML)
{
- reg_maps->bumpmat |= 1 << dst_param.reg.idx;
+ reg_maps->bumpmat |= 1 << ins.dst[i].reg.idx;
if (ins.handler_idx == WINED3DSIH_TEXBEML)
{
- reg_maps->luminanceparams |= 1 << dst_param.reg.idx;
+ reg_maps->luminanceparams |= 1 << ins.dst[i].reg.idx;
}
}
}
else if (ins.handler_idx == WINED3DSIH_BEM)
{
- reg_maps->bumpmat |= 1 << dst_param.reg.idx;
+ reg_maps->bumpmat |= 1 << ins.dst[i].reg.idx;
}
}
@@ -781,30 +749,29 @@ static HRESULT shader_get_registers_used(struct wined3d_shader *shader, const st
|| ins.handler_idx == WINED3DSIH_ENDREP)
--cur_loop_depth;
- limit = ins.src_count + (ins.predicate ? 1 : 0);
- for (i = 0; i < limit; ++i)
- {
- struct wined3d_shader_src_param src_param, src_rel_addr;
- unsigned int count;
+ if (ins.predicate)
+ shader_record_register_usage(shader, reg_maps, &ins.predicate->reg, shader_version.type);
- fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
- count = get_instr_extra_regcount(ins.handler_idx, i);
+ for (i = 0; i < ins.src_count; ++i)
+ {
+ unsigned int count = get_instr_extra_regcount(ins.handler_idx, i);
+ struct wined3d_shader_register reg = ins.src[i].reg;
- shader_record_register_usage(shader, reg_maps, &src_param.reg, shader_version.type);
+ shader_record_register_usage(shader, reg_maps, &ins.src[i].reg, shader_version.type);
while (count)
{
- ++src_param.reg.idx;
- shader_record_register_usage(shader, reg_maps, &src_param.reg, shader_version.type);
+ ++reg.idx;
+ shader_record_register_usage(shader, reg_maps, ®, shader_version.type);
--count;
}
if (color0_mov)
{
- if (src_param.reg.type == WINED3DSPR_TEMP
- && src_param.swizzle == WINED3DSP_NOSWIZZLE)
+ if (ins.src[i].reg.type == WINED3DSPR_TEMP
+ && ins.src[i].swizzle == WINED3DSP_NOSWIZZLE)
{
shader->u.ps.color0_mov = TRUE;
- shader->u.ps.color0_reg = src_param.reg.idx;
+ shader->u.ps.color0_reg = ins.src[i].reg.idx;
}
}
}
@@ -1161,17 +1128,12 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_sh
struct wined3d_device *device = shader->device;
const struct wined3d_shader_frontend *fe = shader->frontend;
void *fe_data = shader->frontend_data;
- struct wined3d_shader_src_param dst_rel_addr[2];
- struct wined3d_shader_src_param src_rel_addr[4];
- struct wined3d_shader_dst_param dst_param[2];
- struct wined3d_shader_src_param src_param[4];
struct wined3d_shader_version shader_version;
struct wined3d_shader_loop_state loop_state;
struct wined3d_shader_instruction ins;
struct wined3d_shader_tex_mx tex_mx;
struct wined3d_shader_context ctx;
const DWORD *ptr = byte_code;
- DWORD i;
/* Initialize current parsing state. */
tex_mx.current_row = 0;
@@ -1185,10 +1147,7 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_sh
ctx.tex_mx = &tex_mx;
ctx.loop_state = &loop_state;
ctx.backend_data = backend_ctx;
-
ins.ctx = &ctx;
- ins.dst = dst_param;
- ins.src = src_param;
fe->shader_read_header(fe_data, &ptr, &shader_version);
@@ -1196,20 +1155,18 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_sh
{
const char *comment;
UINT comment_size;
- UINT param_size;
/* Skip comment tokens. */
fe->shader_read_comment(&ptr, &comment, &comment_size);
if (comment) continue;
/* Read opcode. */
- fe->shader_read_opcode(fe_data, &ptr, &ins, ¶m_size);
+ fe->shader_read_instruction(fe_data, &ptr, &ins);
/* Unknown opcode and its parameters. */
if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
{
TRACE("Skipping unrecognized instruction.\n");
- ptr += param_size;
continue;
}
@@ -1220,29 +1177,10 @@ void shader_generate_main(const struct wined3d_shader *shader, struct wined3d_sh
|| ins.handler_idx == WINED3DSIH_DEFI
|| ins.handler_idx == WINED3DSIH_DEFB
|| ins.handler_idx == WINED3DSIH_PHASE)
- {
- ptr += param_size;
continue;
- }
- /* Destination tokens */
- for (i = 0; i < ins.dst_count; ++i)
- {
- fe->shader_read_dst_param(fe_data, &ptr, &dst_param[i], &dst_rel_addr[i]);
- }
-
- /* Predication token */
if (ins.predicate)
- {
FIXME("Predicates not implemented.\n");
- ins.predicate = *ptr++;
- }
-
- /* Other source tokens */
- for (i = 0; i < ins.src_count; ++i)
- {
- fe->shader_read_src_param(fe_data, &ptr, &src_param[i], &src_rel_addr[i]);
- }
/* Call appropriate function for output target */
device->shader_backend->shader_handle_instruction(&ins);
@@ -1311,7 +1249,6 @@ static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe
struct wined3d_shader_instruction ins;
const char *comment;
UINT comment_size;
- UINT param_size;
/* comment */
fe->shader_read_comment(&ptr, &comment, &comment_size);
@@ -1341,82 +1278,46 @@ static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe
continue;
}
- fe->shader_read_opcode(fe_data, &ptr, &ins, ¶m_size);
+ fe->shader_read_instruction(fe_data, &ptr, &ins);
if (ins.handler_idx == WINED3DSIH_TABLE_SIZE)
{
TRACE("Skipping unrecognized instruction.\n");
- ptr += param_size;
continue;
}
if (ins.handler_idx == WINED3DSIH_DCL)
{
- struct wined3d_shader_semantic semantic;
-
- fe->shader_read_semantic(&ptr, &semantic);
-
- shader_dump_decl_usage(&semantic, &shader_version);
- shader_dump_ins_modifiers(&semantic.reg);
+ shader_dump_decl_usage(&ins.semantic, &shader_version);
+ shader_dump_ins_modifiers(&ins.semantic.reg);
TRACE(" ");
- shader_dump_dst_param(&semantic.reg, &shader_version);
+ shader_dump_dst_param(&ins.semantic.reg, &shader_version);
}
else if (ins.handler_idx == WINED3DSIH_DEF)
{
- struct wined3d_shader_src_param rel_addr;
- struct wined3d_shader_dst_param dst;
-
- fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
-
- TRACE("def c%u = %f, %f, %f, %f", shader_get_float_offset(dst.reg.type, dst.reg.idx),
- *(const float *)(ptr),
- *(const float *)(ptr + 1),
- *(const float *)(ptr + 2),
- *(const float *)(ptr + 3));
- ptr += 4;
+ TRACE("def c%u = %f, %f, %f, %f", shader_get_float_offset(ins.dst[0].reg.type, ins.dst[0].reg.idx),
+ *(const float *)&ins.src[0].reg.immconst_data[0],
+ *(const float *)&ins.src[0].reg.immconst_data[1],
+ *(const float *)&ins.src[0].reg.immconst_data[2],
+ *(const float *)&ins.src[0].reg.immconst_data[3]);
}
else if (ins.handler_idx == WINED3DSIH_DEFI)
{
- struct wined3d_shader_src_param rel_addr;
- struct wined3d_shader_dst_param dst;
-
- fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
-
- TRACE("defi i%u = %d, %d, %d, %d", dst.reg.idx,
- *(ptr),
- *(ptr + 1),
- *(ptr + 2),
- *(ptr + 3));
- ptr += 4;
+ TRACE("defi i%u = %d, %d, %d, %d", ins.dst[0].reg.idx,
+ ins.src[0].reg.immconst_data[0],
+ ins.src[0].reg.immconst_data[1],
+ ins.src[0].reg.immconst_data[2],
+ ins.src[0].reg.immconst_data[3]);
}
else if (ins.handler_idx == WINED3DSIH_DEFB)
{
- struct wined3d_shader_src_param rel_addr;
- struct wined3d_shader_dst_param dst;
-
- fe->shader_read_dst_param(fe_data, &ptr, &dst, &rel_addr);
-
- TRACE("defb b%u = %s", dst.reg.idx, *ptr ? "true" : "false");
- ++ptr;
+ TRACE("defb b%u = %s", ins.dst[0].reg.idx, ins.src[0].reg.immconst_data[0] ? "true" : "false");
}
else
{
- struct wined3d_shader_src_param dst_rel_addr[2];
- struct wined3d_shader_src_param src_rel_addr;
- struct wined3d_shader_dst_param dst_param[2];
- struct wined3d_shader_src_param src_param;
-
- for (i = 0; i < ins.dst_count; ++i)
- {
- fe->shader_read_dst_param(fe_data, &ptr, &dst_param[i], &dst_rel_addr[i]);
- }
-
- /* Print out predication source token first - it follows
- * the destination token. */
if (ins.predicate)
{
- fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
TRACE("(");
- shader_dump_src_param(&src_param, &shader_version);
+ shader_dump_src_param(ins.predicate, &shader_version);
TRACE(") ");
}
@@ -1446,20 +1347,18 @@ static void shader_trace_init(const struct wined3d_shader_frontend *fe, void *fe
TRACE("p");
}
- /* We already read the destination tokens, print them. */
for (i = 0; i < ins.dst_count; ++i)
{
- shader_dump_ins_modifiers(&dst_param[i]);
+ shader_dump_ins_modifiers(&ins.dst[i]);
TRACE(!i ? " " : ", ");
- shader_dump_dst_param(&dst_param[i], &shader_version);
+ shader_dump_dst_param(&ins.dst[i], &shader_version);
}
/* Other source tokens */
for (i = ins.dst_count; i < (ins.dst_count + ins.src_count); ++i)
{
- fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
TRACE(!i ? " " : ", ");
- shader_dump_src_param(&src_param, &shader_version);
+ shader_dump_src_param(&ins.src[i - ins.dst_count], &shader_version);
}
}
TRACE("\n");
diff --git a/dlls/wined3d/shader_sm1.c b/dlls/wined3d/shader_sm1.c
index aa1da56..bba65dd 100644
--- a/dlls/wined3d/shader_sm1.c
+++ b/dlls/wined3d/shader_sm1.c
@@ -204,6 +204,13 @@ struct wined3d_sm1_data
{
struct wined3d_shader_version shader_version;
const struct wined3d_sm1_opcode_info *opcode_table;
+
+ struct wined3d_shader_src_param src_rel_addr[4];
+ struct wined3d_shader_src_param pred_rel_addr;
+ struct wined3d_shader_src_param dst_rel_addr;
+ struct wined3d_shader_src_param src_param[4];
+ struct wined3d_shader_src_param pred_param;
+ struct wined3d_shader_dst_param dst_param;
};
/* This table is not order or position dependent. */
@@ -568,36 +575,9 @@ static void shader_sm1_read_header(void *data, const DWORD **ptr, struct wined3d
*shader_version = priv->shader_version;
}
-static void shader_sm1_read_opcode(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins,
- UINT *param_size)
+static void shader_sm1_read_src_param(struct wined3d_sm1_data *priv, const DWORD **ptr,
+ struct wined3d_shader_src_param *src_param, struct wined3d_shader_src_param *src_rel_addr)
{
- struct wined3d_sm1_data *priv = data;
- const struct wined3d_sm1_opcode_info *opcode_info;
- DWORD opcode_token;
-
- opcode_token = *(*ptr)++;
- opcode_info = shader_get_opcode(priv, 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(priv, *ptr);
- 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_count ? 1 : 0;
- ins->src_count = opcode_info->param_count - opcode_info->dst_count;
- *param_size = shader_skip_opcode(priv, opcode_info, opcode_token);
-}
-
-static void shader_sm1_read_src_param(void *data, const DWORD **ptr, struct wined3d_shader_src_param *src_param,
- struct wined3d_shader_src_param *src_rel_addr)
-{
- struct wined3d_sm1_data *priv = data;
DWORD token, addr_token;
*ptr += shader_get_param(priv, *ptr, &token, &addr_token);
@@ -612,10 +592,9 @@ static void shader_sm1_read_src_param(void *data, const DWORD **ptr, struct wine
}
}
-static void shader_sm1_read_dst_param(void *data, const DWORD **ptr, struct wined3d_shader_dst_param *dst_param,
- struct wined3d_shader_src_param *dst_rel_addr)
+static void shader_sm1_read_dst_param(struct wined3d_sm1_data *priv, const DWORD **ptr,
+ struct wined3d_shader_dst_param *dst_param, struct wined3d_shader_src_param *dst_rel_addr)
{
- struct wined3d_sm1_data *priv = data;
DWORD token, addr_token;
*ptr += shader_get_param(priv, *ptr, &token, &addr_token);
@@ -641,6 +620,84 @@ static void shader_sm1_read_semantic(const DWORD **ptr, struct wined3d_shader_se
shader_parse_dst_param(dst_token, NULL, &semantic->reg);
}
+static void shader_sm1_read_immconst(const DWORD **ptr, struct wined3d_shader_src_param *src_param,
+ enum wined3d_immconst_type type)
+{
+ UINT count = type == WINED3D_IMMCONST_VEC4 ? 4 : 1;
+ src_param->reg.type = WINED3DSPR_IMMCONST;
+ src_param->reg.idx = ~0U;
+ src_param->reg.array_idx = ~0U;
+ src_param->reg.rel_addr = NULL;
+ src_param->reg.immconst_type = type;
+ memcpy(src_param->reg.immconst_data, *ptr, count * sizeof(DWORD));
+ src_param->swizzle = WINED3DSP_NOSWIZZLE;
+ src_param->modifiers = 0;
+
+ *ptr += count;
+}
+
+static void shader_sm1_read_instruction(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins)
+{
+ const struct wined3d_sm1_opcode_info *opcode_info;
+ struct wined3d_sm1_data *priv = data;
+ DWORD opcode_token;
+ unsigned int i;
+ const DWORD *p;
+
+ opcode_token = *(*ptr)++;
+ if (!(opcode_info = shader_get_opcode(priv, opcode_token)))
+ {
+ FIXME("Unrecognized opcode: token=0x%08x.\n", opcode_token);
+ ins->handler_idx = WINED3DSIH_TABLE_SIZE;
+ *ptr += shader_skip_unrecognized(priv, *ptr);
+ 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 ? &priv->pred_param : NULL;
+ ins->dst_count = opcode_info->dst_count ? 1 : 0;
+ ins->dst = &priv->dst_param;
+ ins->src_count = opcode_info->param_count - opcode_info->dst_count;
+ ins->src = priv->src_param;
+
+ p = *ptr;
+ *ptr += shader_skip_opcode(priv, opcode_info, opcode_token);
+
+ if (ins->handler_idx == WINED3DSIH_DCL)
+ {
+ shader_sm1_read_semantic(&p, &ins->semantic);
+ }
+ else if (ins->handler_idx == WINED3DSIH_DEF
+ || ins->handler_idx == WINED3DSIH_DEFI)
+ {
+ shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
+ shader_sm1_read_immconst(&p, &priv->src_param[0], WINED3D_IMMCONST_VEC4);
+ }
+ else if (ins->handler_idx == WINED3DSIH_DEFB)
+ {
+ shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
+ shader_sm1_read_immconst(&p, &priv->src_param[0], WINED3D_IMMCONST_SCALAR);
+ }
+ else
+ {
+ /* Destination token */
+ if (ins->dst_count)
+ shader_sm1_read_dst_param(priv, &p, &priv->dst_param, &priv->dst_rel_addr);
+
+ /* Predication token */
+ if (ins->predicate)
+ shader_sm1_read_src_param(priv, &p, &priv->pred_param, &priv->pred_rel_addr);
+
+ /* Other source tokens */
+ for (i = 0; i < ins->src_count; ++i)
+ {
+ shader_sm1_read_src_param(priv, &p, &priv->src_param[i], &priv->src_rel_addr[i]);
+ }
+ }
+}
+
static void shader_sm1_read_comment(const DWORD **ptr, const char **comment, UINT *comment_size)
{
DWORD token = **ptr;
@@ -674,10 +731,7 @@ const struct wined3d_shader_frontend sm1_shader_frontend =
shader_sm1_init,
shader_sm1_free,
shader_sm1_read_header,
- shader_sm1_read_opcode,
- shader_sm1_read_src_param,
- shader_sm1_read_dst_param,
- shader_sm1_read_semantic,
+ shader_sm1_read_instruction,
shader_sm1_read_comment,
shader_sm1_is_end,
};
diff --git a/dlls/wined3d/shader_sm4.c b/dlls/wined3d/shader_sm4.c
index 25bb72a..778c924 100644
--- a/dlls/wined3d/shader_sm4.c
+++ b/dlls/wined3d/shader_sm4.c
@@ -122,6 +122,11 @@ struct wined3d_sm4_data
struct wined3d_shader_version shader_version;
const DWORD *end;
const struct wined3d_shader_signature *output_signature;
+
+ struct wined3d_shader_src_param src_rel_addr[5];
+ struct wined3d_shader_src_param dst_rel_addr[2];
+ struct wined3d_shader_src_param src_param[5];
+ struct wined3d_shader_dst_param dst_param[2];
};
struct wined3d_sm4_opcode_info
@@ -333,41 +338,9 @@ static void shader_sm4_read_header(void *data, const DWORD **ptr, struct wined3d
*shader_version = priv->shader_version;
}
-static void shader_sm4_read_opcode(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins,
- UINT *param_size)
+static void shader_sm4_read_src_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
+ struct wined3d_shader_src_param *src_param, struct wined3d_shader_src_param *src_rel_addr)
{
- const struct wined3d_sm4_opcode_info *opcode_info;
- DWORD token = *(*ptr)++;
- DWORD opcode = token & WINED3D_SM4_OPCODE_MASK;
-
- *param_size = ((token & WINED3D_SM4_INSTRUCTION_LENGTH_MASK) >> WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT) - 1;
-
- opcode_info = get_opcode_info(opcode);
- if (!opcode_info)
- {
- FIXME("Unrecognized opcode %#x, token 0x%08x\n", opcode, token);
- ins->handler_idx = WINED3DSIH_TABLE_SIZE;
- return;
- }
-
- ins->handler_idx = opcode_info->handler_idx;
- ins->flags = 0;
- ins->coissue = 0;
- ins->predicate = 0;
- ins->dst_count = opcode_info->dst_count;
- ins->src_count = opcode_info->src_count;
-
- if (token & WINED3D_SM4_INSTRUCTION_MODIFIER)
- {
- DWORD modifier = *(*ptr)++;
- FIXME("Skipping modifier 0x%08x.\n", modifier);
- }
-}
-
-static void shader_sm4_read_src_param(void *data, const DWORD **ptr, struct wined3d_shader_src_param *src_param,
- struct wined3d_shader_src_param *src_rel_addr)
-{
- struct wined3d_sm4_data *priv = data;
DWORD token = *(*ptr)++;
enum wined3d_sm4_register_type register_type;
DWORD order;
@@ -456,10 +429,9 @@ static void shader_sm4_read_src_param(void *data, const DWORD **ptr, struct wine
map_register(priv, &src_param->reg);
}
-static void shader_sm4_read_dst_param(void *data, const DWORD **ptr, struct wined3d_shader_dst_param *dst_param,
- struct wined3d_shader_src_param *dst_rel_addr)
+static void shader_sm4_read_dst_param(struct wined3d_sm4_data *priv, const DWORD **ptr,
+ struct wined3d_shader_dst_param *dst_param, struct wined3d_shader_src_param *dst_rel_addr)
{
- struct wined3d_sm4_data *priv = data;
DWORD token = *(*ptr)++;
enum wined3d_sm4_register_type register_type;
DWORD order;
@@ -493,9 +465,53 @@ static void shader_sm4_read_dst_param(void *data, const DWORD **ptr, struct wine
map_register(priv, &dst_param->reg);
}
-static void shader_sm4_read_semantic(const DWORD **ptr, struct wined3d_shader_semantic *semantic)
+static void shader_sm4_read_instruction(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins)
{
- FIXME("ptr %p, semantic %p stub!\n", ptr, semantic);
+ const struct wined3d_sm4_opcode_info *opcode_info;
+ struct wined3d_sm4_data *priv = data;
+ DWORD opcode_token, opcode;
+ const DWORD *p;
+ UINT i, len;
+
+ opcode_token = *(*ptr)++;
+ opcode = opcode_token & WINED3D_SM4_OPCODE_MASK;
+ len = ((opcode_token & WINED3D_SM4_INSTRUCTION_LENGTH_MASK) >> WINED3D_SM4_INSTRUCTION_LENGTH_SHIFT) - 1;
+
+ if (!(opcode_info = get_opcode_info(opcode)))
+ {
+ FIXME("Unrecognized opcode %#x, opcode_token 0x%08x.\n", opcode, opcode_token);
+ ins->handler_idx = WINED3DSIH_TABLE_SIZE;
+ *ptr += len;
+ return;
+ }
+
+ ins->handler_idx = opcode_info->handler_idx;
+ ins->flags = 0;
+ ins->coissue = 0;
+ ins->predicate = NULL;
+ ins->dst_count = opcode_info->dst_count;
+ ins->dst = priv->dst_param;
+ ins->src_count = opcode_info->src_count;
+ ins->src = priv->src_param;
+
+ p = *ptr;
+ *ptr += len;
+
+ if (opcode_token & WINED3D_SM4_INSTRUCTION_MODIFIER)
+ {
+ DWORD modifier = *p++;
+ FIXME("Skipping modifier 0x%08x.\n", modifier);
+ }
+
+ for (i = 0; i < ins->dst_count; ++i)
+ {
+ shader_sm4_read_dst_param(priv, &p, &priv->dst_param[i], &priv->dst_rel_addr[i]);
+ }
+
+ for (i = 0; i < ins->src_count; ++i)
+ {
+ shader_sm4_read_src_param(priv, &p, &priv->src_param[i], &priv->src_rel_addr[i]);
+ }
}
static void shader_sm4_read_comment(const DWORD **ptr, const char **comment, UINT *comment_size)
@@ -515,10 +531,7 @@ const struct wined3d_shader_frontend sm4_shader_frontend =
shader_sm4_init,
shader_sm4_free,
shader_sm4_read_header,
- shader_sm4_read_opcode,
- shader_sm4_read_src_param,
- shader_sm4_read_dst_param,
- shader_sm4_read_semantic,
+ shader_sm4_read_instruction,
shader_sm4_read_comment,
shader_sm4_is_end,
};
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 1bc28c6..e0e8c0d 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -634,25 +634,26 @@ struct wined3d_shader_src_param
enum wined3d_shader_src_modifier modifiers;
};
+struct wined3d_shader_semantic
+{
+ enum wined3d_decl_usage usage;
+ UINT usage_idx;
+ enum wined3d_sampler_texture_type sampler_type;
+ struct wined3d_shader_dst_param reg;
+};
+
struct wined3d_shader_instruction
{
const struct wined3d_shader_context *ctx;
enum WINED3D_SHADER_INSTRUCTION_HANDLER handler_idx;
DWORD flags;
BOOL coissue;
- DWORD predicate;
+ const struct wined3d_shader_src_param *predicate;
UINT dst_count;
const struct wined3d_shader_dst_param *dst;
UINT src_count;
const struct wined3d_shader_src_param *src;
-};
-
-struct wined3d_shader_semantic
-{
- enum wined3d_decl_usage usage;
- UINT usage_idx;
- enum wined3d_sampler_texture_type sampler_type;
- struct wined3d_shader_dst_param reg;
+ struct wined3d_shader_semantic semantic;
};
struct wined3d_shader_attribute
@@ -673,12 +674,7 @@ struct wined3d_shader_frontend
void *(*shader_init)(const DWORD *ptr, const struct wined3d_shader_signature *output_signature);
void (*shader_free)(void *data);
void (*shader_read_header)(void *data, const DWORD **ptr, struct wined3d_shader_version *shader_version);
- void (*shader_read_opcode)(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins, UINT *param_size);
- void (*shader_read_src_param)(void *data, const DWORD **ptr, struct wined3d_shader_src_param *src_param,
- struct wined3d_shader_src_param *src_rel_addr);
- void (*shader_read_dst_param)(void *data, const DWORD **ptr, struct wined3d_shader_dst_param *dst_param,
- struct wined3d_shader_src_param *dst_rel_addr);
- void (*shader_read_semantic)(const DWORD **ptr, struct wined3d_shader_semantic *semantic);
+ void (*shader_read_instruction)(void *data, const DWORD **ptr, struct wined3d_shader_instruction *ins);
void (*shader_read_comment)(const DWORD **ptr, const char **comment, UINT *comment_size);
BOOL (*shader_is_end)(void *data, const DWORD **ptr);
};
--
1.7.8.6
More information about the wine-patches
mailing list