d3dx9: Shader assembler vs_2_x support.
This commit is contained in:
parent
961db7964d
commit
5050f7c8d2
|
@ -30,6 +30,30 @@ WINE_DEFAULT_DEBUG_CHANNEL(asmshader);
|
|||
WINE_DECLARE_DEBUG_CHANNEL(parsed_shader);
|
||||
|
||||
|
||||
/* How to map vs 1.0 and 2.0 varyings to 3.0 ones
|
||||
* oTx is mapped to ox, which happens to be an
|
||||
* identical mapping since BWRITERSPR_TEXCRDOUT == BWRITERSPR_OUTPUT
|
||||
* oPos, oFog and point size are mapped to general output regs as well.
|
||||
* the vs 1.x and 2.x parser functions add varying declarations
|
||||
* to the shader, and the 1.x and 2.x output functions check those varyings
|
||||
*/
|
||||
#define OT0_REG 0
|
||||
#define OT1_REG 1
|
||||
#define OT2_REG 2
|
||||
#define OT3_REG 3
|
||||
#define OT4_REG 4
|
||||
#define OT5_REG 5
|
||||
#define OT6_REG 6
|
||||
#define OT7_REG 7
|
||||
#define OPOS_REG 8
|
||||
#define OFOG_REG 9
|
||||
#define OFOG_WRITEMASK BWRITERSP_WRITEMASK_0
|
||||
#define OPTS_REG 9
|
||||
#define OPTS_WRITEMASK BWRITERSP_WRITEMASK_1
|
||||
#define OD0_REG 10
|
||||
#define OD1_REG 11
|
||||
|
||||
|
||||
/****************************************************************
|
||||
* Common(non-version specific) shader parser control code *
|
||||
****************************************************************/
|
||||
|
@ -98,6 +122,40 @@ static void asmparser_dcl_sampler(struct asm_parser *This, DWORD samptype, DWORD
|
|||
}
|
||||
}
|
||||
|
||||
static void asmparser_sincos(struct asm_parser *This, DWORD mod, DWORD shift,
|
||||
const struct shader_reg *dst,
|
||||
const struct src_regs *srcs) {
|
||||
struct instruction *instr;
|
||||
|
||||
if(!srcs || srcs->count != 3) {
|
||||
asmparser_message(This, "Line %u: sincos (vs 2) has an incorrect number of source registers\n", This->line_no);
|
||||
set_parse_status(This, PARSE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
instr = alloc_instr(3);
|
||||
if(!instr) {
|
||||
ERR("Error allocating memory for the instruction\n");
|
||||
set_parse_status(This, PARSE_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
instr->opcode = BWRITERSIO_SINCOS;
|
||||
instr->dstmod = mod;
|
||||
instr->shift = shift;
|
||||
instr->comptype = 0;
|
||||
|
||||
This->funcs->dstreg(This, instr, dst);
|
||||
This->funcs->srcreg(This, instr, 0, &srcs->reg[0]);
|
||||
This->funcs->srcreg(This, instr, 1, &srcs->reg[1]);
|
||||
This->funcs->srcreg(This, instr, 2, &srcs->reg[2]);
|
||||
|
||||
if(!add_instruction(This->shader, instr)) {
|
||||
ERR("Out of memory\n");
|
||||
set_parse_status(This, PARSE_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
static void asmparser_instr(struct asm_parser *This, DWORD opcode,
|
||||
DWORD mod, DWORD shift,
|
||||
BWRITER_COMPARISON_TYPE comp,
|
||||
|
@ -125,6 +183,20 @@ static void asmparser_instr(struct asm_parser *This, DWORD opcode,
|
|||
}
|
||||
TRACE_(parsed_shader)("\n");
|
||||
|
||||
/* Check for instructions with different syntaxes in different shader versio
|
||||
ns */
|
||||
switch(opcode) {
|
||||
case BWRITERSIO_SINCOS:
|
||||
/* The syntax changes between vs 2 and the other shader versions */
|
||||
if(This->shader->version == BWRITERVS_VERSION(2, 0) ||
|
||||
This->shader->version == BWRITERVS_VERSION(2, 1)) {
|
||||
asmparser_sincos(This, mod, shift, dst, srcs);
|
||||
return;
|
||||
}
|
||||
/* Use the default handling */
|
||||
break;
|
||||
}
|
||||
|
||||
if(src_count != expectednsrcs) {
|
||||
asmparser_message(This, "Line %u: Wrong number of source registers\n", This->line_no);
|
||||
set_parse_status(This, PARSE_ERR);
|
||||
|
@ -153,6 +225,64 @@ static void asmparser_instr(struct asm_parser *This, DWORD opcode,
|
|||
}
|
||||
}
|
||||
|
||||
static struct shader_reg map_oldvs_register(const struct shader_reg *reg) {
|
||||
struct shader_reg ret;
|
||||
switch(reg->type) {
|
||||
case BWRITERSPR_RASTOUT:
|
||||
ret = *reg;
|
||||
ret.type = BWRITERSPR_OUTPUT;
|
||||
switch(reg->regnum) {
|
||||
case BWRITERSRO_POSITION:
|
||||
ret.regnum = OPOS_REG;
|
||||
break;
|
||||
case BWRITERSRO_FOG:
|
||||
ret.regnum = OFOG_REG;
|
||||
ret.writemask = OFOG_WRITEMASK;
|
||||
break;
|
||||
case BWRITERSRO_POINT_SIZE:
|
||||
ret.regnum = OPTS_REG;
|
||||
ret.writemask = OPTS_WRITEMASK;
|
||||
break;
|
||||
default:
|
||||
FIXME("Unhandled RASTOUT register %u\n", reg->regnum);
|
||||
return *reg;
|
||||
}
|
||||
return ret;
|
||||
|
||||
case BWRITERSPR_TEXCRDOUT:
|
||||
ret = *reg;
|
||||
ret.type = BWRITERSPR_OUTPUT;
|
||||
switch(reg->regnum) {
|
||||
case 0: ret.regnum = OT0_REG; break;
|
||||
case 1: ret.regnum = OT1_REG; break;
|
||||
case 2: ret.regnum = OT2_REG; break;
|
||||
case 3: ret.regnum = OT3_REG; break;
|
||||
case 4: ret.regnum = OT4_REG; break;
|
||||
case 5: ret.regnum = OT5_REG; break;
|
||||
case 6: ret.regnum = OT6_REG; break;
|
||||
case 7: ret.regnum = OT7_REG; break;
|
||||
default:
|
||||
FIXME("Unhandled TEXCRDOUT regnum %u\n", reg->regnum);
|
||||
return *reg;
|
||||
}
|
||||
return ret;
|
||||
|
||||
case BWRITERSPR_ATTROUT:
|
||||
ret = *reg;
|
||||
ret.type = BWRITERSPR_OUTPUT;
|
||||
switch(reg->regnum) {
|
||||
case 0: ret.regnum = OD0_REG; break;
|
||||
case 1: ret.regnum = OD1_REG; break;
|
||||
default:
|
||||
FIXME("Unhandled ATTROUT regnum %u\n", reg->regnum);
|
||||
return *reg;
|
||||
}
|
||||
return ret;
|
||||
|
||||
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) {
|
||||
|
@ -168,6 +298,15 @@ static void check_legacy_srcmod(struct asm_parser *This, DWORD srcmod) {
|
|||
}
|
||||
}
|
||||
|
||||
static void check_abs_srcmod(struct asm_parser *This, DWORD srcmod) {
|
||||
if(srcmod == BWRITERSPSM_ABS || srcmod == BWRITERSPSM_ABSNEG) {
|
||||
asmparser_message(This, "Line %u: Source modifier %s not supported in this shader version\n",
|
||||
This->line_no,
|
||||
debug_print_srcmod(srcmod));
|
||||
set_parse_status(This, PARSE_ERR);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_loop_swizzle(struct asm_parser *This,
|
||||
const struct shader_reg *src) {
|
||||
if((src->type == BWRITERSPR_LOOP && src->swizzle != BWRITERVS_NOSWIZZLE) ||
|
||||
|
@ -219,6 +358,40 @@ static BOOL check_reg_type(const struct shader_reg *reg,
|
|||
}
|
||||
|
||||
/* Native assembler doesn't do separate checks for src and dst registers */
|
||||
static const struct allowed_reg_type vs_2_reg_allowed[] = {
|
||||
{ BWRITERSPR_TEMP, 12 },
|
||||
{ BWRITERSPR_INPUT, 16 },
|
||||
{ BWRITERSPR_CONST, ~0U },
|
||||
{ BWRITERSPR_ADDR, 1 },
|
||||
{ BWRITERSPR_CONSTBOOL, 16 },
|
||||
{ BWRITERSPR_CONSTINT, 16 },
|
||||
{ BWRITERSPR_LOOP, 1 },
|
||||
{ BWRITERSPR_LABEL, 2048 },
|
||||
{ BWRITERSPR_PREDICATE, 1 },
|
||||
{ BWRITERSPR_RASTOUT, 3 }, /* oPos, oFog and oPts */
|
||||
{ BWRITERSPR_ATTROUT, 2 },
|
||||
{ BWRITERSPR_TEXCRDOUT, 8 },
|
||||
{ ~0U, 0 } /* End tag */
|
||||
};
|
||||
|
||||
static void asmparser_srcreg_vs_2(struct asm_parser *This,
|
||||
struct instruction *instr, int num,
|
||||
const struct shader_reg *src) {
|
||||
struct shader_reg reg;
|
||||
|
||||
if(!check_reg_type(src, vs_2_reg_allowed)) {
|
||||
asmparser_message(This, "Line %u: Source register %s not supported in VS 2\n",
|
||||
This->line_no,
|
||||
debug_print_srcreg(src, ST_VERTEX));
|
||||
set_parse_status(This, PARSE_ERR);
|
||||
}
|
||||
check_loop_swizzle(This, src);
|
||||
check_legacy_srcmod(This, src->srcmod);
|
||||
check_abs_srcmod(This, src->srcmod);
|
||||
reg = map_oldvs_register(src);
|
||||
memcpy(&instr->src[num], ®, sizeof(reg));
|
||||
}
|
||||
|
||||
static const struct allowed_reg_type vs_3_reg_allowed[] = {
|
||||
{ BWRITERSPR_TEMP, 32 },
|
||||
{ BWRITERSPR_INPUT, 16 },
|
||||
|
@ -278,6 +451,24 @@ static void asmparser_srcreg_ps_3(struct asm_parser *This,
|
|||
memcpy(&instr->src[num], src, sizeof(*src));
|
||||
}
|
||||
|
||||
static void asmparser_dstreg_vs_2(struct asm_parser *This,
|
||||
struct instruction *instr,
|
||||
const struct shader_reg *dst) {
|
||||
struct shader_reg reg;
|
||||
|
||||
if(!check_reg_type(dst, vs_2_reg_allowed)) {
|
||||
asmparser_message(This, "Line %u: Destination register %s not supported in VS 2.0\n",
|
||||
This->line_no,
|
||||
debug_print_dstreg(dst, ST_VERTEX));
|
||||
set_parse_status(This, PARSE_ERR);
|
||||
}
|
||||
check_ps_dstmod(This, instr->dstmod);
|
||||
check_shift_dstmod(This, instr->shift);
|
||||
reg = map_oldvs_register(dst);
|
||||
memcpy(&instr->dst, ®, sizeof(reg));
|
||||
instr->has_dst = TRUE;
|
||||
}
|
||||
|
||||
static void asmparser_dstreg_vs_3(struct asm_parser *This,
|
||||
struct instruction *instr,
|
||||
const struct shader_reg *dst) {
|
||||
|
@ -329,6 +520,26 @@ static void asmparser_coissue_unsupported(struct asm_parser *This) {
|
|||
set_parse_status(This, PARSE_ERR);
|
||||
}
|
||||
|
||||
static const struct asmparser_backend parser_vs_2 = {
|
||||
asmparser_constF,
|
||||
asmparser_constI,
|
||||
asmparser_constB,
|
||||
|
||||
asmparser_dstreg_vs_2,
|
||||
asmparser_srcreg_vs_2,
|
||||
|
||||
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_vs_3 = {
|
||||
asmparser_constF,
|
||||
asmparser_constI,
|
||||
|
@ -369,6 +580,54 @@ static const struct asmparser_backend parser_ps_3 = {
|
|||
asmparser_instr,
|
||||
};
|
||||
|
||||
static void gen_oldvs_output(struct bwriter_shader *shader) {
|
||||
record_declaration(shader, BWRITERDECLUSAGE_POSITION, 0, TRUE, OPOS_REG, BWRITERSP_WRITEMASK_ALL);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 0, TRUE, OT0_REG, BWRITERSP_WRITEMASK_ALL);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 1, TRUE, OT1_REG, BWRITERSP_WRITEMASK_ALL);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 2, TRUE, OT2_REG, BWRITERSP_WRITEMASK_ALL);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 3, TRUE, OT3_REG, BWRITERSP_WRITEMASK_ALL);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 4, TRUE, OT4_REG, BWRITERSP_WRITEMASK_ALL);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 5, TRUE, OT5_REG, BWRITERSP_WRITEMASK_ALL);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 6, TRUE, OT6_REG, BWRITERSP_WRITEMASK_ALL);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_TEXCOORD, 7, TRUE, OT7_REG, BWRITERSP_WRITEMASK_ALL);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_FOG, 0, TRUE, OFOG_REG, OFOG_WRITEMASK);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_PSIZE, 0, TRUE, OPTS_REG, OPTS_WRITEMASK);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_COLOR, 0, TRUE, OD0_REG, BWRITERSP_WRITEMASK_ALL);
|
||||
record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, TRUE, OD1_REG, BWRITERSP_WRITEMASK_ALL);
|
||||
}
|
||||
|
||||
void create_vs20_parser(struct asm_parser *ret) {
|
||||
TRACE_(parsed_shader)("vs_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_VERTEX;
|
||||
ret->shader->version = BWRITERVS_VERSION(2, 0);
|
||||
ret->funcs = &parser_vs_2;
|
||||
gen_oldvs_output(ret->shader);
|
||||
}
|
||||
|
||||
void create_vs2x_parser(struct asm_parser *ret) {
|
||||
TRACE_(parsed_shader)("vs_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_VERTEX;
|
||||
ret->shader->version = BWRITERVS_VERSION(2, 1);
|
||||
ret->funcs = &parser_vs_2;
|
||||
gen_oldvs_output(ret->shader);
|
||||
}
|
||||
|
||||
void create_vs30_parser(struct asm_parser *ret) {
|
||||
TRACE_(parsed_shader)("vs_3_0\n");
|
||||
|
||||
|
|
|
@ -283,14 +283,12 @@ version_marker: VER_VS10
|
|||
| VER_VS20
|
||||
{
|
||||
TRACE("Vertex shader 2.0\n");
|
||||
set_parse_status(&asm_ctx, PARSE_ERR);
|
||||
YYABORT;
|
||||
create_vs20_parser(&asm_ctx);
|
||||
}
|
||||
| VER_VS2X
|
||||
{
|
||||
TRACE("Vertex shader 2.x\n");
|
||||
set_parse_status(&asm_ctx, PARSE_ERR);
|
||||
YYABORT;
|
||||
create_vs2x_parser(&asm_ctx);
|
||||
}
|
||||
| VER_VS30
|
||||
{
|
||||
|
|
|
@ -400,10 +400,220 @@ static void write_constF(const struct bwriter_shader *shader, struct bytecode_bu
|
|||
write_const(shader->constF, shader->num_cf, D3DSIO_DEF, D3DSPR_CONST, buffer, len);
|
||||
}
|
||||
|
||||
static HRESULT vs_find_builtin_varyings(struct bc_writer *This, const struct bwriter_shader *shader) {
|
||||
DWORD i;
|
||||
DWORD usage, usage_idx, writemask, regnum;
|
||||
|
||||
for(i = 0; i < shader->num_outputs; i++) {
|
||||
usage = shader->outputs[i].usage;
|
||||
usage_idx = shader->outputs[i].usage_idx;
|
||||
writemask = shader->outputs[i].writemask;
|
||||
regnum = shader->outputs[i].regnum;
|
||||
|
||||
switch(usage) {
|
||||
case BWRITERDECLUSAGE_POSITION:
|
||||
case BWRITERDECLUSAGE_POSITIONT:
|
||||
if(usage_idx > 0) {
|
||||
WARN("dcl_position%u not supported in sm 1/2 shaders\n", usage_idx);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
TRACE("o%u is oPos\n", regnum);
|
||||
This->oPos_regnum = regnum;
|
||||
break;
|
||||
|
||||
case BWRITERDECLUSAGE_COLOR:
|
||||
if(usage_idx > 1) {
|
||||
WARN("dcl_color%u not supported in sm 1/2 shaders\n", usage_idx);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if(writemask != BWRITERSP_WRITEMASK_ALL) {
|
||||
WARN("Only WRITEMASK_ALL is supported on color in sm 1/2\n");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
TRACE("o%u is oD%u\n", regnum, usage_idx);
|
||||
This->oD_regnum[usage_idx] = regnum;
|
||||
break;
|
||||
|
||||
case BWRITERDECLUSAGE_TEXCOORD:
|
||||
if(usage_idx > 8) {
|
||||
WARN("dcl_color%u not supported in sm 1/2 shaders\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");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
TRACE("o%u is oT%u\n", regnum, usage_idx);
|
||||
This->oT_regnum[usage_idx] = regnum;
|
||||
break;
|
||||
|
||||
case BWRITERDECLUSAGE_PSIZE:
|
||||
if(usage_idx > 0) {
|
||||
WARN("dcl_psize%u not supported in sm 1/2 shaders\n", usage_idx);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
TRACE("o%u writemask 0x%08x is oPts\n", regnum, writemask);
|
||||
This->oPts_regnum = regnum;
|
||||
This->oPts_mask = writemask;
|
||||
break;
|
||||
|
||||
case BWRITERDECLUSAGE_FOG:
|
||||
if(usage_idx > 0) {
|
||||
WARN("dcl_fog%u not supported in sm 1 shaders\n", usage_idx);
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
if(writemask != BWRITERSP_WRITEMASK_0 && writemask != BWRITERSP_WRITEMASK_1 &&
|
||||
writemask != BWRITERSP_WRITEMASK_2 && writemask != BWRITERSP_WRITEMASK_3) {
|
||||
WARN("Unsupported fog writemask\n");
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
TRACE("o%u writemask 0x%08x is oFog\n", regnum, writemask);
|
||||
This->oFog_regnum = regnum;
|
||||
This->oFog_mask = writemask;
|
||||
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);
|
||||
}
|
||||
|
||||
static DWORD map_vs_output(struct bc_writer *This, DWORD regnum, DWORD mask, DWORD *has_components) {
|
||||
DWORD token = 0;
|
||||
DWORD i;
|
||||
|
||||
*has_components = TRUE;
|
||||
if(regnum == This->oPos_regnum) {
|
||||
token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
|
||||
token |= D3DSRO_POSITION & D3DSP_REGNUM_MASK; /* No shift */
|
||||
return token;
|
||||
}
|
||||
if(regnum == This->oFog_regnum && mask == This->oFog_mask) {
|
||||
token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
|
||||
token |= D3DSRO_FOG & D3DSP_REGNUM_MASK; /* No shift */
|
||||
token |= D3DSP_WRITEMASK_ALL;
|
||||
*has_components = FALSE;
|
||||
return token;
|
||||
}
|
||||
if(regnum == This->oPts_regnum && mask == This->oPts_mask) {
|
||||
token |= (D3DSPR_RASTOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
|
||||
token |= D3DSRO_POINT_SIZE & D3DSP_REGNUM_MASK; /* No shift */
|
||||
token |= D3DSP_WRITEMASK_ALL;
|
||||
*has_components = FALSE;
|
||||
return token;
|
||||
}
|
||||
for(i = 0; i < 2; i++) {
|
||||
if(regnum == This->oD_regnum[i]) {
|
||||
token |= (D3DSPR_ATTROUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
|
||||
token |= i & D3DSP_REGNUM_MASK; /* No shift */
|
||||
return token;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < 8; i++) {
|
||||
if(regnum == This->oT_regnum[i]) {
|
||||
token |= (D3DSPR_TEXCRDOUT << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
|
||||
token |= i & D3DSP_REGNUM_MASK; /* No shift */
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
/* The varying must be undeclared - if an unsupported varying was declared,
|
||||
* the vs_find_builtin_varyings function would have caught it and this code
|
||||
* would not run */
|
||||
WARN("Undeclared varying %u\n", regnum);
|
||||
This->state = E_INVALIDARG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void vs_12_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 has_wmask;
|
||||
|
||||
if(reg->rel_reg) {
|
||||
WARN("Relative addressing not supported for destination registers\n");
|
||||
This->state = E_INVALIDARG;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(reg->type) {
|
||||
case BWRITERSPR_OUTPUT:
|
||||
token |= map_vs_output(This, reg->regnum, reg->writemask, &has_wmask);
|
||||
break;
|
||||
|
||||
case BWRITERSPR_RASTOUT:
|
||||
case BWRITERSPR_ATTROUT:
|
||||
/* These registers are mapped to input and output regs. They can be encoded in the bytecode,
|
||||
* but are unexpected. If we hit this path it might be due to an error.
|
||||
*/
|
||||
FIXME("Unexpected register type %u\n", reg->type);
|
||||
/* drop through */
|
||||
case BWRITERSPR_INPUT:
|
||||
case BWRITERSPR_TEMP:
|
||||
case BWRITERSPR_CONST:
|
||||
token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
|
||||
token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
|
||||
has_wmask = TRUE;
|
||||
break;
|
||||
|
||||
case BWRITERSPR_ADDR:
|
||||
if(reg->regnum != 0) {
|
||||
WARN("Only a0 exists\n");
|
||||
This->state = E_INVALIDARG;
|
||||
return;
|
||||
}
|
||||
token |= (D3DSPR_ADDR << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
|
||||
token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
|
||||
has_wmask = TRUE;
|
||||
break;
|
||||
|
||||
case BWRITERSPR_PREDICATE:
|
||||
if(This->version != BWRITERVS_VERSION(2, 1)){
|
||||
WARN("Predicate register is allowed only in vs_2_x\n");
|
||||
This->state = E_INVALIDARG;
|
||||
return;
|
||||
}
|
||||
if(reg->regnum != 0) {
|
||||
WARN("Only predicate register p0 exists\n");
|
||||
This->state = E_INVALIDARG;
|
||||
return;
|
||||
}
|
||||
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 */
|
||||
has_wmask = TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN("Invalid register type for 1.x-2.x vertex shader\n");
|
||||
This->state = E_INVALIDARG;
|
||||
return;
|
||||
}
|
||||
|
||||
/* strictly speaking there are no modifiers in vs_2_0 and vs_1_x, but they can be written
|
||||
* into the bytecode and since the compiler doesn't do such checks write them
|
||||
* (the checks are done by the undocumented shader validator)
|
||||
*/
|
||||
token |= (shift << D3DSP_DSTSHIFT_SHIFT) & D3DSP_DSTSHIFT_MASK;
|
||||
token |= d3d9_dstmod(mod);
|
||||
|
||||
if(has_wmask) {
|
||||
token |= d3d9_writemask(reg->writemask);
|
||||
}
|
||||
put_dword(buffer, token);
|
||||
}
|
||||
|
||||
static void write_srcregs(struct bc_writer *This, const struct instruction *instr,
|
||||
struct bytecode_buffer *buffer){
|
||||
unsigned int i;
|
||||
|
@ -451,6 +661,129 @@ static void write_constI(const struct bwriter_shader *shader, struct bytecode_bu
|
|||
write_const(shader->constI, shader->num_ci, D3DSIO_DEFI, D3DSPR_CONSTINT, buffer, len);
|
||||
}
|
||||
|
||||
static void vs_2_header(struct bc_writer *This,
|
||||
const struct bwriter_shader *shader,
|
||||
struct bytecode_buffer *buffer) {
|
||||
HRESULT hr;
|
||||
|
||||
hr = vs_find_builtin_varyings(This, shader);
|
||||
if(FAILED(hr)) {
|
||||
This->state = hr;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Declare the shader type and version */
|
||||
put_dword(buffer, This->version);
|
||||
|
||||
write_declarations(buffer, TRUE, shader->inputs, shader->num_inputs, D3DSPR_INPUT);
|
||||
write_constF(shader, buffer, TRUE);
|
||||
write_constB(shader, buffer, TRUE);
|
||||
write_constI(shader, buffer, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
static void vs_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 has_swizzle;
|
||||
DWORD component;
|
||||
DWORD d3d9reg;
|
||||
|
||||
switch(reg->type) {
|
||||
case BWRITERSPR_OUTPUT:
|
||||
/* Map the swizzle to a writemask, the format expected
|
||||
by map_vs_output
|
||||
*/
|
||||
switch(reg->swizzle) {
|
||||
case BWRITERVS_SWIZZLE_X:
|
||||
component = BWRITERSP_WRITEMASK_0;
|
||||
break;
|
||||
case BWRITERVS_SWIZZLE_Y:
|
||||
component = BWRITERSP_WRITEMASK_1;
|
||||
break;
|
||||
case BWRITERVS_SWIZZLE_Z:
|
||||
component = BWRITERSP_WRITEMASK_2;
|
||||
break;
|
||||
case BWRITERVS_SWIZZLE_W:
|
||||
component = BWRITERSP_WRITEMASK_3;
|
||||
break;
|
||||
default:
|
||||
component = 0;
|
||||
}
|
||||
token |= map_vs_output(This, reg->regnum, component, &has_swizzle);
|
||||
break;
|
||||
|
||||
case BWRITERSPR_RASTOUT:
|
||||
case BWRITERSPR_ATTROUT:
|
||||
/* These registers are mapped to input and output regs. They can be encoded in the bytecode,
|
||||
* but are unexpected. If we hit this path it might be due to an error.
|
||||
*/
|
||||
FIXME("Unexpected register type %u\n", reg->type);
|
||||
/* drop through */
|
||||
case BWRITERSPR_INPUT:
|
||||
case BWRITERSPR_TEMP:
|
||||
case BWRITERSPR_CONST:
|
||||
case BWRITERSPR_ADDR:
|
||||
case BWRITERSPR_CONSTINT:
|
||||
case BWRITERSPR_CONSTBOOL:
|
||||
case BWRITERSPR_LABEL:
|
||||
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_LOOP:
|
||||
if(reg->regnum != 0) {
|
||||
WARN("Only regnum 0 is supported for the loop index register in vs_2_0\n");
|
||||
This->state = E_INVALIDARG;
|
||||
return;
|
||||
}
|
||||
token |= (D3DSPR_LOOP << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
|
||||
token |= (D3DSPR_LOOP << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2;
|
||||
token |= 0 & D3DSP_REGNUM_MASK; /* No shift */
|
||||
break;
|
||||
|
||||
case BWRITERSPR_PREDICATE:
|
||||
if(This->version != BWRITERVS_VERSION(2, 1)){
|
||||
WARN("Predicate register is allowed only in vs_2_x\n");
|
||||
This->state = E_INVALIDARG;
|
||||
return;
|
||||
}
|
||||
if(reg->regnum > 0) {
|
||||
WARN("Only predicate register 0 is supported\n");
|
||||
This->state = E_INVALIDARG;
|
||||
return;
|
||||
}
|
||||
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 2.0 vshader\n");
|
||||
This->state = E_INVALIDARG;
|
||||
return;
|
||||
}
|
||||
|
||||
token |= d3d9_swizzle(reg->swizzle) & D3DVS_SWIZZLE_MASK; /* already shifted */
|
||||
|
||||
token |= d3d9_srcmod(reg->srcmod);
|
||||
|
||||
if(reg->rel_reg)
|
||||
token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
|
||||
|
||||
put_dword(buffer, token);
|
||||
|
||||
/* vs_2_0 and newer write the register containing the index explicitly in the
|
||||
* binary code
|
||||
*/
|
||||
if(token & D3DVS_ADDRMODE_RELATIVE)
|
||||
vs_2_srcreg(This, reg->rel_reg, buffer);
|
||||
}
|
||||
|
||||
static void sm_2_opcode(struct bc_writer *This,
|
||||
const struct instruction *instr,
|
||||
DWORD token, struct bytecode_buffer *buffer) {
|
||||
|
@ -464,6 +797,132 @@ static void sm_2_opcode(struct bc_writer *This,
|
|||
put_dword(buffer,token);
|
||||
}
|
||||
|
||||
static const struct instr_handler_table vs_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_SLT, instr_handler},
|
||||
{BWRITERSIO_SGE, instr_handler},
|
||||
{BWRITERSIO_ABS, instr_handler},
|
||||
{BWRITERSIO_EXP, instr_handler},
|
||||
{BWRITERSIO_LOG, instr_handler},
|
||||
{BWRITERSIO_EXPP, instr_handler},
|
||||
{BWRITERSIO_LOGP, instr_handler},
|
||||
{BWRITERSIO_DST, instr_handler},
|
||||
{BWRITERSIO_LRP, instr_handler},
|
||||
{BWRITERSIO_FRC, instr_handler},
|
||||
{BWRITERSIO_CRS, instr_handler},
|
||||
{BWRITERSIO_SGN, 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_LIT, instr_handler},
|
||||
{BWRITERSIO_POW, instr_handler},
|
||||
{BWRITERSIO_MOVA, 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_ELSE, instr_handler},
|
||||
{BWRITERSIO_ENDIF, instr_handler},
|
||||
{BWRITERSIO_LOOP, instr_handler},
|
||||
{BWRITERSIO_RET, instr_handler},
|
||||
{BWRITERSIO_ENDLOOP, instr_handler},
|
||||
|
||||
{BWRITERSIO_END, NULL},
|
||||
};
|
||||
|
||||
static const struct bytecode_backend vs_2_0_backend = {
|
||||
vs_2_header,
|
||||
end,
|
||||
vs_2_srcreg,
|
||||
vs_12_dstreg,
|
||||
sm_2_opcode,
|
||||
vs_2_0_handlers
|
||||
};
|
||||
|
||||
static const struct instr_handler_table vs_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_SLT, instr_handler},
|
||||
{BWRITERSIO_SGE, instr_handler},
|
||||
{BWRITERSIO_ABS, instr_handler},
|
||||
{BWRITERSIO_EXP, instr_handler},
|
||||
{BWRITERSIO_LOG, instr_handler},
|
||||
{BWRITERSIO_EXPP, instr_handler},
|
||||
{BWRITERSIO_LOGP, instr_handler},
|
||||
{BWRITERSIO_DST, instr_handler},
|
||||
{BWRITERSIO_LRP, instr_handler},
|
||||
{BWRITERSIO_FRC, instr_handler},
|
||||
{BWRITERSIO_CRS, instr_handler},
|
||||
{BWRITERSIO_SGN, 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_LIT, instr_handler},
|
||||
{BWRITERSIO_POW, instr_handler},
|
||||
{BWRITERSIO_MOVA, 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_LOOP, instr_handler},
|
||||
{BWRITERSIO_RET, instr_handler},
|
||||
{BWRITERSIO_ENDLOOP, instr_handler},
|
||||
|
||||
{BWRITERSIO_SETP, instr_handler},
|
||||
{BWRITERSIO_BREAKP, instr_handler},
|
||||
|
||||
{BWRITERSIO_END, NULL},
|
||||
};
|
||||
|
||||
static const struct bytecode_backend vs_2_x_backend = {
|
||||
vs_2_header,
|
||||
end,
|
||||
vs_2_srcreg,
|
||||
vs_12_dstreg,
|
||||
sm_2_opcode,
|
||||
vs_2_x_handlers
|
||||
};
|
||||
|
||||
static void write_samplers(const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
|
||||
DWORD i;
|
||||
DWORD instr_dcl = D3DSIO_DCL | (2 << D3DSI_INSTLENGTH_SHIFT);
|
||||
|
@ -712,6 +1171,16 @@ static const struct bytecode_backend ps_3_backend = {
|
|||
ps_3_handlers
|
||||
};
|
||||
|
||||
static void init_vs20_dx9_writer(struct bc_writer *writer) {
|
||||
TRACE("Creating DirectX9 vertex shader 2.0 writer\n");
|
||||
writer->funcs = &vs_2_0_backend;
|
||||
}
|
||||
|
||||
static void init_vs2x_dx9_writer(struct bc_writer *writer) {
|
||||
TRACE("Creating DirectX9 vertex shader 2.x writer\n");
|
||||
writer->funcs = &vs_2_x_backend;
|
||||
}
|
||||
|
||||
static void init_vs30_dx9_writer(struct bc_writer *writer) {
|
||||
TRACE("Creating DirectX9 vertex shader 3.0 writer\n");
|
||||
writer->funcs = &vs_3_backend;
|
||||
|
@ -750,14 +1219,14 @@ static struct bc_writer *create_writer(DWORD version, DWORD dxversion) {
|
|||
WARN("Unsupported dxversion for vertex shader 2.0 requested: %u\n", dxversion);
|
||||
goto fail;
|
||||
}
|
||||
/* TODO: Set the appropriate writer backend */
|
||||
init_vs20_dx9_writer(ret);
|
||||
break;
|
||||
case BWRITERVS_VERSION(2, 1):
|
||||
if(dxversion != 9) {
|
||||
WARN("Unsupported dxversion for vertex shader 2.x requested: %u\n", dxversion);
|
||||
goto fail;
|
||||
}
|
||||
/* TODO: Set the appropriate writer backend */
|
||||
init_vs2x_dx9_writer(ret);
|
||||
break;
|
||||
case BWRITERVS_VERSION(3, 0):
|
||||
if(dxversion != 9) {
|
||||
|
|
|
@ -311,6 +311,8 @@ struct asm_parser {
|
|||
|
||||
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_ps30_parser(struct asm_parser *ret);
|
||||
|
||||
|
@ -369,6 +371,15 @@ struct bc_writer {
|
|||
HRESULT state;
|
||||
|
||||
DWORD version;
|
||||
|
||||
/* Vertex shader varying mapping */
|
||||
DWORD oPos_regnum;
|
||||
DWORD oD_regnum[2];
|
||||
DWORD oT_regnum[8];
|
||||
DWORD oFog_regnum;
|
||||
DWORD oFog_mask;
|
||||
DWORD oPts_regnum;
|
||||
DWORD oPts_mask;
|
||||
};
|
||||
|
||||
/* Debug utility routines */
|
||||
|
|
|
@ -739,6 +739,14 @@ static void vs_2_0_test(void) {
|
|||
"endif\n",
|
||||
{0xfffe0200, 0x01000028, 0xede40800, 0x0000002a, 0x0000002b, 0x0000ffff}
|
||||
},
|
||||
{ /* shader 28 */
|
||||
"vs_2_0\n"
|
||||
"call l3\n"
|
||||
"ret\n"
|
||||
"label l3\n"
|
||||
"ret\n",
|
||||
{0xfffe0200, 0x01000019, 0xa0e41003, 0x0000001c, 0x0100001e, 0xa0e41003, 0x0000001c, 0x0000ffff}
|
||||
},
|
||||
};
|
||||
|
||||
exec_tests("vs_2_0", tests, sizeof(tests) / sizeof(tests[0]));
|
||||
|
@ -1467,8 +1475,8 @@ START_TEST(asm)
|
|||
todo_wine vs_1_1_test();
|
||||
todo_wine ps_1_3_test();
|
||||
todo_wine ps_1_4_test();
|
||||
todo_wine vs_2_0_test();
|
||||
todo_wine vs_2_x_test();
|
||||
vs_2_0_test();
|
||||
vs_2_x_test();
|
||||
todo_wine ps_2_0_test();
|
||||
todo_wine ps_2_x_test();
|
||||
vs_3_0_test();
|
||||
|
|
Loading…
Reference in New Issue