Commit 5786d3a0 authored by Matteo Bruni's avatar Matteo Bruni Committed by Alexandre Julliard

d3dx9: Shader assembler ps_2_x support.

parent ce3e846f
......@@ -53,6 +53,17 @@ WINE_DECLARE_DEBUG_CHANNEL(parsed_shader);
#define OD0_REG 10
#define OD1_REG 11
/* Input color registers 0-1 are identically mapped */
#define C0_VARYING 0
#define C1_VARYING 1
#define T0_VARYING 2
#define T1_VARYING 3
#define T2_VARYING 4
#define T3_VARYING 5
#define T4_VARYING 6
#define T5_VARYING 7
#define T6_VARYING 8
#define T7_VARYING 9
/****************************************************************
* Common(non-version specific) shader parser control code *
......@@ -283,6 +294,39 @@ static struct shader_reg map_oldvs_register(const struct shader_reg *reg) {
}
}
static struct shader_reg map_oldps_register(const struct shader_reg *reg, BOOL tex_varying) {
struct shader_reg ret;
switch(reg->type) {
case BWRITERSPR_TEXTURE:
if(tex_varying) {
ret = *reg;
ret.type = BWRITERSPR_INPUT;
switch(reg->regnum) {
case 0: ret.regnum = T0_VARYING; break;
case 1: ret.regnum = T1_VARYING; break;
case 2: ret.regnum = T2_VARYING; break;
case 3: ret.regnum = T3_VARYING; break;
case 4: ret.regnum = T4_VARYING; break;
case 5: ret.regnum = T5_VARYING; break;
case 6: ret.regnum = T6_VARYING; break;
case 7: ret.regnum = T7_VARYING; break;
default:
FIXME("Unexpected TEXTURE register t%u\n", reg->regnum);
return *reg;
}
return ret;
} else {
FIXME("TODO: ps_1_x texture register mapping\n");
return *reg;
}
/* case BWRITERSPR_INPUT - Identical mapping of 1.x/2.0 color varyings
to 3.0 ones */
default: return *reg;
}
}
/* Checks for unsupported source modifiers in VS (all versions) or
PS 2.0 and newer */
static void check_legacy_srcmod(struct asm_parser *This, DWORD srcmod) {
......@@ -421,6 +465,68 @@ static void asmparser_srcreg_vs_3(struct asm_parser *This,
memcpy(&instr->src[num], src, sizeof(*src));
}
static const struct allowed_reg_type ps_2_0_reg_allowed[] = {
{ BWRITERSPR_INPUT, 2 },
{ BWRITERSPR_TEMP, 32 },
{ BWRITERSPR_CONST, 32 },
{ BWRITERSPR_CONSTINT, 16 },
{ BWRITERSPR_CONSTBOOL, 16 },
{ BWRITERSPR_SAMPLER, 16 },
{ BWRITERSPR_TEXTURE, 8 },
{ BWRITERSPR_COLOROUT, 4 },
{ BWRITERSPR_DEPTHOUT, 1 },
{ ~0U, 0 } /* End tag */
};
static void asmparser_srcreg_ps_2(struct asm_parser *This,
struct instruction *instr, int num,
const struct shader_reg *src) {
struct shader_reg reg;
if(!check_reg_type(src, ps_2_0_reg_allowed)) {
asmparser_message(This, "Line %u: Source register %s not supported in PS 2.0\n",
This->line_no,
debug_print_srcreg(src, ST_PIXEL));
set_parse_status(This, PARSE_ERR);
}
check_legacy_srcmod(This, src->srcmod);
check_abs_srcmod(This, src->srcmod);
reg = map_oldps_register(src, TRUE);
memcpy(&instr->src[num], &reg, sizeof(reg));
}
static const struct allowed_reg_type ps_2_x_reg_allowed[] = {
{ BWRITERSPR_INPUT, 2 },
{ BWRITERSPR_TEMP, 32 },
{ BWRITERSPR_CONST, 32 },
{ BWRITERSPR_CONSTINT, 16 },
{ BWRITERSPR_CONSTBOOL, 16 },
{ BWRITERSPR_PREDICATE, 1 },
{ BWRITERSPR_SAMPLER, 16 },
{ BWRITERSPR_TEXTURE, 8 },
{ BWRITERSPR_LABEL, 2048 },
{ BWRITERSPR_COLOROUT, 4 },
{ BWRITERSPR_DEPTHOUT, 1 },
{ ~0U, 0 } /* End tag */
};
static void asmparser_srcreg_ps_2_x(struct asm_parser *This,
struct instruction *instr, int num,
const struct shader_reg *src) {
struct shader_reg reg;
if(!check_reg_type(src, ps_2_x_reg_allowed)) {
asmparser_message(This, "Line %u: Source register %s not supported in PS 2.x\n",
This->line_no,
debug_print_srcreg(src, ST_PIXEL));
set_parse_status(This, PARSE_ERR);
}
check_legacy_srcmod(This, src->srcmod);
check_abs_srcmod(This, src->srcmod);
reg = map_oldps_register(src, TRUE);
memcpy(&instr->src[num], &reg, sizeof(reg));
}
static const struct allowed_reg_type ps_3_reg_allowed[] = {
{ BWRITERSPR_INPUT, 10 },
{ BWRITERSPR_TEMP, 32 },
......@@ -484,6 +590,40 @@ static void asmparser_dstreg_vs_3(struct asm_parser *This,
instr->has_dst = TRUE;
}
static void asmparser_dstreg_ps_2(struct asm_parser *This,
struct instruction *instr,
const struct shader_reg *dst) {
struct shader_reg reg;
if(!check_reg_type(dst, ps_2_0_reg_allowed)) {
asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.0\n",
This->line_no,
debug_print_dstreg(dst, ST_PIXEL));
set_parse_status(This, PARSE_ERR);
}
check_shift_dstmod(This, instr->shift);
reg = map_oldps_register(dst, TRUE);
memcpy(&instr->dst, &reg, sizeof(reg));
instr->has_dst = TRUE;
}
static void asmparser_dstreg_ps_2_x(struct asm_parser *This,
struct instruction *instr,
const struct shader_reg *dst) {
struct shader_reg reg;
if(!check_reg_type(dst, ps_2_x_reg_allowed)) {
asmparser_message(This, "Line %u: Destination register %s not supported in PS 2.x\n",
This->line_no,
debug_print_dstreg(dst, ST_PIXEL));
set_parse_status(This, PARSE_ERR);
}
check_shift_dstmod(This, instr->shift);
reg = map_oldps_register(dst, TRUE);
memcpy(&instr->dst, &reg, sizeof(reg));
instr->has_dst = TRUE;
}
static void asmparser_dstreg_ps_3(struct asm_parser *This,
struct instruction *instr,
const struct shader_reg *dst) {
......@@ -507,13 +647,11 @@ static void asmparser_predicate_supported(struct asm_parser *This,
memcpy(&This->shader->instr[This->shader->num_instrs - 1]->predicate, predicate, sizeof(*predicate));
}
#if 0
static void asmparser_predicate_unsupported(struct asm_parser *This,
const struct shader_reg *predicate) {
asmparser_message(This, "Line %u: Predicate not supported in < VS 2.0 or PS 2.x\n", This->line_no);
set_parse_status(This, PARSE_ERR);
}
#endif
static void asmparser_coissue_unsupported(struct asm_parser *This) {
asmparser_message(This, "Line %u: Coissue is only supported in pixel shaders versions <= 1.4\n", This->line_no);
......@@ -560,6 +698,46 @@ static const struct asmparser_backend parser_vs_3 = {
asmparser_instr,
};
static const struct asmparser_backend parser_ps_2 = {
asmparser_constF,
asmparser_constI,
asmparser_constB,
asmparser_dstreg_ps_2,
asmparser_srcreg_ps_2,
asmparser_predicate_unsupported,
asmparser_coissue_unsupported,
asmparser_dcl_output,
asmparser_dcl_input,
asmparser_dcl_sampler,
asmparser_end,
asmparser_instr,
};
static const struct asmparser_backend parser_ps_2_x = {
asmparser_constF,
asmparser_constI,
asmparser_constB,
asmparser_dstreg_ps_2_x,
asmparser_srcreg_ps_2_x,
asmparser_predicate_supported,
asmparser_coissue_unsupported,
asmparser_dcl_output,
asmparser_dcl_input,
asmparser_dcl_sampler,
asmparser_end,
asmparser_instr,
};
static const struct asmparser_backend parser_ps_3 = {
asmparser_constF,
asmparser_constI,
......@@ -596,6 +774,21 @@ static void gen_oldvs_output(struct bwriter_shader *shader) {
record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, TRUE, OD1_REG, BWRITERSP_WRITEMASK_ALL);
}
static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) {
switch(texcoords) {
case 8: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, FALSE, T7_VARYING, BWRITERSP_WRITEMASK_ALL);
case 7: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, FALSE, T6_VARYING, BWRITERSP_WRITEMASK_ALL);
case 6: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, FALSE, T5_VARYING, BWRITERSP_WRITEMASK_ALL);
case 5: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, FALSE, T4_VARYING, BWRITERSP_WRITEMASK_ALL);
case 4: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, FALSE, T3_VARYING, BWRITERSP_WRITEMASK_ALL);
case 3: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, FALSE, T2_VARYING, BWRITERSP_WRITEMASK_ALL);
case 2: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, FALSE, T1_VARYING, BWRITERSP_WRITEMASK_ALL);
case 1: record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, FALSE, T0_VARYING, BWRITERSP_WRITEMASK_ALL);
};
record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, FALSE, C0_VARYING, BWRITERSP_WRITEMASK_ALL);
record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL);
}
void create_vs20_parser(struct asm_parser *ret) {
TRACE_(parsed_shader)("vs_2_0\n");
......@@ -643,6 +836,38 @@ void create_vs30_parser(struct asm_parser *ret) {
ret->funcs = &parser_vs_3;
}
void create_ps20_parser(struct asm_parser *ret) {
TRACE_(parsed_shader)("ps_2_0\n");
ret->shader = asm_alloc(sizeof(*ret->shader));
if(!ret->shader) {
ERR("Failed to allocate memory for the shader\n");
set_parse_status(ret, PARSE_ERR);
return;
}
ret->shader->type = ST_PIXEL;
ret->shader->version = BWRITERPS_VERSION(2, 0);
ret->funcs = &parser_ps_2;
gen_oldps_input(ret->shader, 8);
}
void create_ps2x_parser(struct asm_parser *ret) {
TRACE_(parsed_shader)("ps_2_x\n");
ret->shader = asm_alloc(sizeof(*ret->shader));
if(!ret->shader) {
ERR("Failed to allocate memory for the shader\n");
set_parse_status(ret, PARSE_ERR);
return;
}
ret->shader->type = ST_PIXEL;
ret->shader->version = BWRITERPS_VERSION(2, 1);
ret->funcs = &parser_ps_2_x;
gen_oldps_input(ret->shader, 8);
}
void create_ps30_parser(struct asm_parser *ret) {
TRACE_(parsed_shader)("ps_3_0\n");
......
......@@ -328,14 +328,12 @@ version_marker: VER_VS10
| VER_PS20
{
TRACE("Pixel shader 2.0\n");
set_parse_status(&asm_ctx, PARSE_ERR);
YYABORT;
create_ps20_parser(&asm_ctx);
}
| VER_PS2X
{
TRACE("Pixel shader 2.x\n");
set_parse_status(&asm_ctx, PARSE_ERR);
YYABORT;
create_ps2x_parser(&asm_ctx);
}
| VER_PS30
{
......
......@@ -484,6 +484,61 @@ static HRESULT vs_find_builtin_varyings(struct bc_writer *This, const struct bwr
return S_OK;
}
static HRESULT find_ps_builtin_semantics(struct bc_writer *This,
const struct bwriter_shader *shader,
DWORD texcoords) {
DWORD i;
DWORD usage, usage_idx, writemask, regnum;
This->v_regnum[0] = -1; This->v_regnum[1] = -1;
for(i = 0; i < 8; i++) This->t_regnum[i] = -1;
for(i = 0; i < shader->num_inputs; i++) {
usage = shader->inputs[i].usage;
usage_idx = shader->inputs[i].usage_idx;
writemask = shader->inputs[i].writemask;
regnum = shader->inputs[i].regnum;
switch(usage) {
case BWRITERDECLUSAGE_COLOR:
if(usage_idx > 1) {
WARN("dcl_color%u not supported in sm 1 shaders\n", usage_idx);
return E_INVALIDARG;
}
if(writemask != BWRITERSP_WRITEMASK_ALL) {
WARN("Only WRITEMASK_ALL is supported on color in sm 1\n");
return E_INVALIDARG;
}
TRACE("v%u is v%u\n", regnum, usage_idx);
This->v_regnum[usage_idx] = regnum;
break;
case BWRITERDECLUSAGE_TEXCOORD:
if(usage_idx > texcoords) {
WARN("dcl_texcoord%u not supported in this shader version\n", usage_idx);
return E_INVALIDARG;
}
if(writemask != (BWRITERSP_WRITEMASK_0) &&
writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1) &&
writemask != (BWRITERSP_WRITEMASK_0 | BWRITERSP_WRITEMASK_1 | BWRITERSP_WRITEMASK_2) &&
writemask != (BWRITERSP_WRITEMASK_ALL)) {
WARN("Partial writemasks not supported on texture coordinates in sm 1 and 2\n");
} else {
writemask = BWRITERSP_WRITEMASK_ALL;
}
TRACE("v%u is t%u\n", regnum, usage_idx);
This->t_regnum[usage_idx] = regnum;
break;
default:
WARN("Varying type %u is not supported in shader model 1.x\n", usage);
return E_INVALIDARG;
}
}
return S_OK;
}
static void end(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
put_dword(buffer, D3DSIO_END);
}
......@@ -625,6 +680,30 @@ static void write_srcregs(struct bc_writer *This, const struct instruction *inst
}
}
static DWORD map_ps_input(struct bc_writer *This,
const struct shader_reg *reg) {
DWORD i, token = 0;
/* Map color interpolators */
for(i = 0; i < 2; i++) {
if(reg->regnum == This->v_regnum[i]) {
token |= (D3DSPR_INPUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
token |= i & D3DSP_REGNUM_MASK; /* No shift */
return token;
}
}
for(i = 0; i < 8; i++) {
if(reg->regnum == This->t_regnum[i]) {
token |= (D3DSPR_TEXTURE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
token |= i & D3DSP_REGNUM_MASK; /* No shift */
return token;
}
}
WARN("Invalid ps 1/2 varying\n");
This->state = E_INVALIDARG;
return token;
}
/* The length of an instruction consists of the destination register (if any),
* the number of source registers, the number of address registers used for
* indirect addressing, and optionally the predicate register
......@@ -943,6 +1022,248 @@ static void write_samplers(const struct bwriter_shader *shader, struct bytecode_
}
}
static void ps_2_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
HRESULT hr = find_ps_builtin_semantics(This, shader, 8);
if(FAILED(hr)) {
This->state = hr;
return;
}
/* Declare the shader type and version */
put_dword(buffer, This->version);
write_samplers(shader, buffer);
write_constF(shader, buffer, TRUE);
write_constB(shader, buffer, TRUE);
write_constI(shader, buffer, TRUE);
}
static void ps_2_srcreg(struct bc_writer *This,
const struct shader_reg *reg,
struct bytecode_buffer *buffer) {
DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
DWORD d3d9reg;
if(reg->rel_reg) {
WARN("Relative addressing not supported in <= ps_3_0\n");
This->state = E_INVALIDARG;
return;
}
switch(reg->type) {
case BWRITERSPR_INPUT:
token |= map_ps_input(This, reg);
break;
/* Can be mapped 1:1 */
case BWRITERSPR_TEMP:
case BWRITERSPR_CONST:
case BWRITERSPR_COLOROUT:
case BWRITERSPR_CONSTBOOL:
case BWRITERSPR_CONSTINT:
case BWRITERSPR_SAMPLER:
case BWRITERSPR_LABEL:
case BWRITERSPR_DEPTHOUT:
d3d9reg = d3d9_register(reg->type);
token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
break;
case BWRITERSPR_PREDICATE:
if(This->version != BWRITERPS_VERSION(2, 1)){
WARN("Predicate register not supported in ps_2_0\n");
This->state = E_INVALIDARG;
}
if(reg->regnum) {
WARN("Predicate register with regnum %u not supported\n",
reg->regnum);
This->state = E_INVALIDARG;
}
token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
break;
default:
WARN("Invalid register type for ps_2_0 shader\n");
This->state = E_INVALIDARG;
return;
}
token |= d3d9_swizzle(reg->swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
token |= d3d9_srcmod(reg->srcmod);
put_dword(buffer, token);
}
static void ps_2_0_dstreg(struct bc_writer *This,
const struct shader_reg *reg,
struct bytecode_buffer *buffer,
DWORD shift, DWORD mod) {
DWORD token = (1 << 31); /* Bit 31 of registers is 1 */
DWORD d3d9reg;
if(reg->rel_reg) {
WARN("Relative addressing not supported for destination registers\n");
This->state = E_INVALIDARG;
return;
}
switch(reg->type) {
case BWRITERSPR_TEMP: /* 1:1 mapping */
case BWRITERSPR_COLOROUT:
case BWRITERSPR_DEPTHOUT:
d3d9reg = d3d9_register(reg->type);
token |= (d3d9reg << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
token |= (d3d9reg << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
break;
case BWRITERSPR_PREDICATE:
if(This->version != BWRITERPS_VERSION(2, 1)){
WARN("Predicate register not supported in ps_2_0\n");
This->state = E_INVALIDARG;
}
token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
token |= (D3DSPR_PREDICATE << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
break;
/* texkill uses the input register as a destination parameter */
case BWRITERSPR_INPUT:
token |= map_ps_input(This, reg);
break;
default:
WARN("Invalid dest register type for 2.x pshader\n");
This->state = E_INVALIDARG;
return;
}
token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
token |= d3d9_dstmod(mod);
token |= d3d9_writemask(reg->writemask);
put_dword(buffer, token);
}
static const struct instr_handler_table ps_2_0_handlers[] = {
{BWRITERSIO_ADD, instr_handler},
{BWRITERSIO_NOP, instr_handler},
{BWRITERSIO_MOV, instr_handler},
{BWRITERSIO_SUB, instr_handler},
{BWRITERSIO_MAD, instr_handler},
{BWRITERSIO_MUL, instr_handler},
{BWRITERSIO_RCP, instr_handler},
{BWRITERSIO_RSQ, instr_handler},
{BWRITERSIO_DP3, instr_handler},
{BWRITERSIO_DP4, instr_handler},
{BWRITERSIO_MIN, instr_handler},
{BWRITERSIO_MAX, instr_handler},
{BWRITERSIO_ABS, instr_handler},
{BWRITERSIO_EXP, instr_handler},
{BWRITERSIO_LOG, instr_handler},
{BWRITERSIO_EXPP, instr_handler},
{BWRITERSIO_LOGP, instr_handler},
{BWRITERSIO_LRP, instr_handler},
{BWRITERSIO_FRC, instr_handler},
{BWRITERSIO_CRS, instr_handler},
{BWRITERSIO_NRM, instr_handler},
{BWRITERSIO_SINCOS, instr_handler},
{BWRITERSIO_M4x4, instr_handler},
{BWRITERSIO_M4x3, instr_handler},
{BWRITERSIO_M3x4, instr_handler},
{BWRITERSIO_M3x3, instr_handler},
{BWRITERSIO_M3x2, instr_handler},
{BWRITERSIO_POW, instr_handler},
{BWRITERSIO_DP2ADD, instr_handler},
{BWRITERSIO_CMP, instr_handler},
{BWRITERSIO_TEX, instr_handler},
{BWRITERSIO_TEXLDP, instr_handler},
{BWRITERSIO_TEXLDB, instr_handler},
{BWRITERSIO_TEXKILL, instr_handler},
{BWRITERSIO_END, NULL},
};
static const struct bytecode_backend ps_2_0_backend = {
ps_2_header,
end,
ps_2_srcreg,
ps_2_0_dstreg,
sm_2_opcode,
ps_2_0_handlers
};
static const struct instr_handler_table ps_2_x_handlers[] = {
{BWRITERSIO_ADD, instr_handler},
{BWRITERSIO_NOP, instr_handler},
{BWRITERSIO_MOV, instr_handler},
{BWRITERSIO_SUB, instr_handler},
{BWRITERSIO_MAD, instr_handler},
{BWRITERSIO_MUL, instr_handler},
{BWRITERSIO_RCP, instr_handler},
{BWRITERSIO_RSQ, instr_handler},
{BWRITERSIO_DP3, instr_handler},
{BWRITERSIO_DP4, instr_handler},
{BWRITERSIO_MIN, instr_handler},
{BWRITERSIO_MAX, instr_handler},
{BWRITERSIO_ABS, instr_handler},
{BWRITERSIO_EXP, instr_handler},
{BWRITERSIO_LOG, instr_handler},
{BWRITERSIO_EXPP, instr_handler},
{BWRITERSIO_LOGP, instr_handler},
{BWRITERSIO_LRP, instr_handler},
{BWRITERSIO_FRC, instr_handler},
{BWRITERSIO_CRS, instr_handler},
{BWRITERSIO_NRM, instr_handler},
{BWRITERSIO_SINCOS, instr_handler},
{BWRITERSIO_M4x4, instr_handler},
{BWRITERSIO_M4x3, instr_handler},
{BWRITERSIO_M3x4, instr_handler},
{BWRITERSIO_M3x3, instr_handler},
{BWRITERSIO_M3x2, instr_handler},
{BWRITERSIO_POW, instr_handler},
{BWRITERSIO_DP2ADD, instr_handler},
{BWRITERSIO_CMP, instr_handler},
{BWRITERSIO_CALL, instr_handler},
{BWRITERSIO_CALLNZ, instr_handler},
{BWRITERSIO_REP, instr_handler},
{BWRITERSIO_ENDREP, instr_handler},
{BWRITERSIO_IF, instr_handler},
{BWRITERSIO_LABEL, instr_handler},
{BWRITERSIO_IFC, instr_handler},
{BWRITERSIO_ELSE, instr_handler},
{BWRITERSIO_ENDIF, instr_handler},
{BWRITERSIO_BREAK, instr_handler},
{BWRITERSIO_BREAKC, instr_handler},
{BWRITERSIO_RET, instr_handler},
{BWRITERSIO_TEX, instr_handler},
{BWRITERSIO_TEXLDP, instr_handler},
{BWRITERSIO_TEXLDB, instr_handler},
{BWRITERSIO_TEXKILL, instr_handler},
{BWRITERSIO_DSX, instr_handler},
{BWRITERSIO_DSY, instr_handler},
{BWRITERSIO_SETP, instr_handler},
{BWRITERSIO_BREAKP, instr_handler},
{BWRITERSIO_TEXLDD, instr_handler},
{BWRITERSIO_END, NULL},
};
static const struct bytecode_backend ps_2_x_backend = {
ps_2_header,
end,
ps_2_srcreg,
ps_2_0_dstreg,
sm_2_opcode,
ps_2_x_handlers
};
static void sm_3_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
/* Declare the shader type and version */
put_dword(buffer, This->version);
......@@ -1186,6 +1507,16 @@ static void init_vs30_dx9_writer(struct bc_writer *writer) {
writer->funcs = &vs_3_backend;
}
static void init_ps20_dx9_writer(struct bc_writer *writer) {
TRACE("Creating DirectX9 pixel shader 2.0 writer\n");
writer->funcs = &ps_2_0_backend;
}
static void init_ps2x_dx9_writer(struct bc_writer *writer) {
TRACE("Creating DirectX9 pixel shader 2.x writer\n");
writer->funcs = &ps_2_x_backend;
}
static void init_ps30_dx9_writer(struct bc_writer *writer) {
TRACE("Creating DirectX9 pixel shader 3.0 writer\n");
writer->funcs = &ps_3_backend;
......@@ -1277,7 +1608,7 @@ static struct bc_writer *create_writer(DWORD version, DWORD dxversion) {
WARN("Unsupported dxversion for pixel shader 2.0 requested: %u\n", dxversion);
goto fail;
}
/* TODO: Set the appropriate writer backend */
init_ps20_dx9_writer(ret);
break;
case BWRITERPS_VERSION(2, 1):
......@@ -1285,7 +1616,7 @@ static struct bc_writer *create_writer(DWORD version, DWORD dxversion) {
WARN("Unsupported dxversion for pixel shader 2.x requested: %u\n", dxversion);
goto fail;
}
/* TODO: Set the appropriate writer backend */
init_ps2x_dx9_writer(ret);
break;
case BWRITERPS_VERSION(3, 0):
......
......@@ -314,6 +314,8 @@ extern struct asm_parser asm_ctx;
void create_vs20_parser(struct asm_parser *ret);
void create_vs2x_parser(struct asm_parser *ret);
void create_vs30_parser(struct asm_parser *ret);
void create_ps20_parser(struct asm_parser *ret);
void create_ps2x_parser(struct asm_parser *ret);
void create_ps30_parser(struct asm_parser *ret);
struct bwriter_shader *parse_asm_shader(char **messages);
......@@ -380,6 +382,10 @@ struct bc_writer {
DWORD oFog_mask;
DWORD oPts_regnum;
DWORD oPts_mask;
/* Pixel shader specific members */
DWORD t_regnum[8];
DWORD v_regnum[2];
};
/* Debug utility routines */
......
......@@ -1015,6 +1015,15 @@ static void ps_2_x_test(void) {
{0xffff0201, 0x01000026, 0xf0e40000, 0x01000060, 0xb0ff1000,
0x00000027, 0x0000ffff}
},
{ /* shader 16 */
"ps_2_x\n"
"call l2047\n"
"ret\n"
"label l2047\n"
"ret\n",
{0xffff0201, 0x01000019, 0xa0e417ff, 0x0000001c, 0x0100001e, 0xa0e417ff,
0x0000001c, 0x0000ffff}
},
};
exec_tests("ps_2_x", tests, sizeof(tests) / sizeof(tests[0]));
......@@ -1504,8 +1513,8 @@ START_TEST(asm)
todo_wine ps_1_4_test();
vs_2_0_test();
vs_2_x_test();
todo_wine ps_2_0_test();
todo_wine ps_2_x_test();
ps_2_0_test();
ps_2_x_test();
vs_3_0_test();
ps_3_0_test();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment