wined3d: Read complete shader instructions at a time.

This commit is contained in:
Henri Verbeet 2012-09-04 20:15:08 +02:00 committed by Alexandre Julliard
parent f2437c2b32
commit 42582ada00
4 changed files with 228 additions and 266 deletions

View File

@ -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, &param_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)
if (ins.predicate)
shader_record_register_usage(shader, reg_maps, &ins.predicate->reg, shader_version.type);
for (i = 0; i < ins.src_count; ++i)
{
struct wined3d_shader_src_param src_param, src_rel_addr;
unsigned int count;
unsigned int count = get_instr_extra_regcount(ins.handler_idx, i);
struct wined3d_shader_register reg = ins.src[i].reg;
fe->shader_read_src_param(fe_data, &ptr, &src_param, &src_rel_addr);
count = get_instr_extra_regcount(ins.handler_idx, i);
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, &reg, 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, &param_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, &param_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");

View File

@ -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,
};

View File

@ -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,
};

View File

@ -634,19 +634,6 @@ struct wined3d_shader_src_param
enum wined3d_shader_src_modifier modifiers;
};
struct wined3d_shader_instruction
{
const struct wined3d_shader_context *ctx;
enum WINED3D_SHADER_INSTRUCTION_HANDLER handler_idx;
DWORD flags;
BOOL coissue;
DWORD 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;
@ -655,6 +642,20 @@ struct wined3d_shader_semantic
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;
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 semantic;
};
struct wined3d_shader_attribute
{
enum wined3d_decl_usage usage;
@ -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);
};