Commit 913278c5 authored by Matteo Bruni's avatar Matteo Bruni Committed by Alexandre Julliard

d3dx9: Shader assembler vs_1_0 and vs_1_1 support.

parent 7f19bda6
...@@ -407,6 +407,46 @@ static BOOL check_reg_type(const struct shader_reg *reg, ...@@ -407,6 +407,46 @@ static BOOL check_reg_type(const struct shader_reg *reg,
} }
/* Native assembler doesn't do separate checks for src and dst registers */ /* Native assembler doesn't do separate checks for src and dst registers */
static const struct allowed_reg_type vs_1_reg_allowed[] = {
{ BWRITERSPR_TEMP, 12, FALSE },
{ BWRITERSPR_INPUT, 16, FALSE },
{ BWRITERSPR_CONST, ~0U, TRUE },
{ BWRITERSPR_ADDR, 1, FALSE },
{ BWRITERSPR_RASTOUT, 3, FALSE }, /* oPos, oFog and oPts */
{ BWRITERSPR_ATTROUT, 2, FALSE },
{ BWRITERSPR_TEXCRDOUT, 8, FALSE },
{ ~0U, 0 } /* End tag */
};
/* struct instruction *asmparser_srcreg
*
* Records a source register in the instruction and does shader version
* specific checks and modifications on it
*
* Parameters:
* This: Shader parser instance
* instr: instruction to store the register in
* num: Number of source register
* src: Pointer to source the register structure. The caller can free
* it afterwards
*/
static void asmparser_srcreg_vs_1(struct asm_parser *This,
struct instruction *instr, int num,
const struct shader_reg *src) {
struct shader_reg reg;
if(!check_reg_type(src, vs_1_reg_allowed)) {
asmparser_message(This, "Line %u: Source register %s not supported in VS 1\n",
This->line_no,
debug_print_srcreg(src, ST_VERTEX));
set_parse_status(This, PARSE_ERR);
}
check_legacy_srcmod(This, src->srcmod);
check_abs_srcmod(This, src->srcmod);
reg = map_oldvs_register(src);
memcpy(&instr->src[num], &reg, sizeof(reg));
}
static const struct allowed_reg_type vs_2_reg_allowed[] = { static const struct allowed_reg_type vs_2_reg_allowed[] = {
{ BWRITERSPR_TEMP, 12, FALSE }, { BWRITERSPR_TEMP, 12, FALSE },
{ BWRITERSPR_INPUT, 16, FALSE }, { BWRITERSPR_INPUT, 16, FALSE },
...@@ -562,6 +602,24 @@ static void asmparser_srcreg_ps_3(struct asm_parser *This, ...@@ -562,6 +602,24 @@ static void asmparser_srcreg_ps_3(struct asm_parser *This,
memcpy(&instr->src[num], src, sizeof(*src)); memcpy(&instr->src[num], src, sizeof(*src));
} }
static void asmparser_dstreg_vs_1(struct asm_parser *This,
struct instruction *instr,
const struct shader_reg *dst) {
struct shader_reg reg;
if(!check_reg_type(dst, vs_1_reg_allowed)) {
asmparser_message(This, "Line %u: Destination register %s not supported in VS 1\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, &reg, sizeof(reg));
instr->has_dst = TRUE;
}
static void asmparser_dstreg_vs_2(struct asm_parser *This, static void asmparser_dstreg_vs_2(struct asm_parser *This,
struct instruction *instr, struct instruction *instr,
const struct shader_reg *dst) { const struct shader_reg *dst) {
...@@ -663,6 +721,26 @@ static void asmparser_coissue_unsupported(struct asm_parser *This) { ...@@ -663,6 +721,26 @@ static void asmparser_coissue_unsupported(struct asm_parser *This) {
set_parse_status(This, PARSE_ERR); set_parse_status(This, PARSE_ERR);
} }
static const struct asmparser_backend parser_vs_1 = {
asmparser_constF,
asmparser_constI,
asmparser_constB,
asmparser_dstreg_vs_1,
asmparser_srcreg_vs_1,
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_vs_2 = { static const struct asmparser_backend parser_vs_2 = {
asmparser_constF, asmparser_constF,
asmparser_constI, asmparser_constI,
...@@ -794,6 +872,38 @@ static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) { ...@@ -794,6 +872,38 @@ static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) {
record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL); record_declaration(shader, BWRITERDECLUSAGE_COLOR, 1, FALSE, C1_VARYING, BWRITERSP_WRITEMASK_ALL);
} }
void create_vs10_parser(struct asm_parser *ret) {
TRACE_(parsed_shader)("vs_1_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(1, 0);
ret->funcs = &parser_vs_1;
gen_oldvs_output(ret->shader);
}
void create_vs11_parser(struct asm_parser *ret) {
TRACE_(parsed_shader)("vs_1_1\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(1, 1);
ret->funcs = &parser_vs_1;
gen_oldvs_output(ret->shader);
}
void create_vs20_parser(struct asm_parser *ret) { void create_vs20_parser(struct asm_parser *ret) {
TRACE_(parsed_shader)("vs_2_0\n"); TRACE_(parsed_shader)("vs_2_0\n");
......
...@@ -271,14 +271,12 @@ shader: version_marker instructions ...@@ -271,14 +271,12 @@ shader: version_marker instructions
version_marker: VER_VS10 version_marker: VER_VS10
{ {
TRACE("Vertex shader 1.0\n"); TRACE("Vertex shader 1.0\n");
set_parse_status(&asm_ctx, PARSE_ERR); create_vs10_parser(&asm_ctx);
YYABORT;
} }
| VER_VS11 | VER_VS11
{ {
TRACE("Vertex shader 1.1\n"); TRACE("Vertex shader 1.1\n");
set_parse_status(&asm_ctx, PARSE_ERR); create_vs11_parser(&asm_ctx);
YYABORT;
} }
| VER_VS20 | VER_VS20
{ {
......
...@@ -484,6 +484,30 @@ static HRESULT vs_find_builtin_varyings(struct bc_writer *This, const struct bwr ...@@ -484,6 +484,30 @@ static HRESULT vs_find_builtin_varyings(struct bc_writer *This, const struct bwr
return S_OK; return S_OK;
} }
static void vs_1_x_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
HRESULT hr;
if(shader->num_ci || shader->num_cb) {
WARN("Int and bool constants are not supported in shader model 1 shaders\n");
WARN("Got %u int and %u boolean constants\n", shader->num_ci, shader->num_cb);
This->state = E_INVALIDARG;
return;
}
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, FALSE, shader->inputs, shader->num_inputs, D3DSPR_INPUT);
write_constF(shader, buffer, FALSE);
return;
}
static HRESULT find_ps_builtin_semantics(struct bc_writer *This, static HRESULT find_ps_builtin_semantics(struct bc_writer *This,
const struct bwriter_shader *shader, const struct bwriter_shader *shader,
DWORD texcoords) { DWORD texcoords) {
...@@ -669,6 +693,73 @@ static void vs_12_dstreg(struct bc_writer *This, const struct shader_reg *reg, ...@@ -669,6 +693,73 @@ static void vs_12_dstreg(struct bc_writer *This, const struct shader_reg *reg,
put_dword(buffer, token); put_dword(buffer, token);
} }
static void vs_1_x_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;
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:
token |= (reg->type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
token |= reg->regnum & D3DSP_REGNUM_MASK; /* No shift */
if(reg->rel_reg) {
if(reg->rel_reg->type != BWRITERSPR_ADDR ||
reg->rel_reg->regnum != 0 ||
reg->rel_reg->swizzle != BWRITERVS_SWIZZLE_X) {
WARN("Relative addressing in vs_1_x is only allowed with a0.x\n");
This->state = E_INVALIDARG;
return;
}
token |= D3DVS_ADDRMODE_RELATIVE & D3DVS_ADDRESSMODE_MASK;
}
break;
default:
WARN("Invalid register type for 1.x vshader\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 write_srcregs(struct bc_writer *This, const struct instruction *instr, static void write_srcregs(struct bc_writer *This, const struct instruction *instr,
struct bytecode_buffer *buffer){ struct bytecode_buffer *buffer){
unsigned int i; unsigned int i;
...@@ -721,6 +812,16 @@ static DWORD instrlen(const struct instruction *instr, unsigned int srcs, unsign ...@@ -721,6 +812,16 @@ static DWORD instrlen(const struct instruction *instr, unsigned int srcs, unsign
return ret; return ret;
} }
static void sm_1_x_opcode(struct bc_writer *This,
const struct instruction *instr,
DWORD token, struct bytecode_buffer *buffer) {
/* In sm_1_x instruction length isn't encoded */
if(instr->coissue){
token |= D3DSI_COISSUE;
}
put_dword(buffer, token);
}
static void instr_handler(struct bc_writer *This, static void instr_handler(struct bc_writer *This,
const struct instruction *instr, const struct instruction *instr,
struct bytecode_buffer *buffer) { struct bytecode_buffer *buffer) {
...@@ -732,6 +833,47 @@ static void instr_handler(struct bc_writer *This, ...@@ -732,6 +833,47 @@ static void instr_handler(struct bc_writer *This,
write_srcregs(This, instr, buffer); write_srcregs(This, instr, buffer);
} }
static const struct instr_handler_table vs_1_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_EXP, instr_handler},
{BWRITERSIO_LOG, instr_handler},
{BWRITERSIO_EXPP, instr_handler},
{BWRITERSIO_LOGP, instr_handler},
{BWRITERSIO_DST, instr_handler},
{BWRITERSIO_FRC, 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_END, NULL}, /* Sentinel value, it signals
the end of the list */
};
static const struct bytecode_backend vs_1_x_backend = {
vs_1_x_header,
end,
vs_1_x_srcreg,
vs_12_dstreg,
sm_1_x_opcode,
vs_1_x_handlers
};
static void write_constB(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) { static void write_constB(const struct bwriter_shader *shader, struct bytecode_buffer *buffer, BOOL len) {
write_const(shader->constB, shader->num_cb, D3DSIO_DEFB, D3DSPR_CONSTBOOL, buffer, len); write_const(shader->constB, shader->num_cb, D3DSIO_DEFB, D3DSPR_CONSTBOOL, buffer, len);
} }
...@@ -1492,6 +1634,16 @@ static const struct bytecode_backend ps_3_backend = { ...@@ -1492,6 +1634,16 @@ static const struct bytecode_backend ps_3_backend = {
ps_3_handlers ps_3_handlers
}; };
static void init_vs10_dx9_writer(struct bc_writer *writer) {
TRACE("Creating DirectX9 vertex shader 1.0 writer\n");
writer->funcs = &vs_1_x_backend;
}
static void init_vs11_dx9_writer(struct bc_writer *writer) {
TRACE("Creating DirectX9 vertex shader 1.1 writer\n");
writer->funcs = &vs_1_x_backend;
}
static void init_vs20_dx9_writer(struct bc_writer *writer) { static void init_vs20_dx9_writer(struct bc_writer *writer) {
TRACE("Creating DirectX9 vertex shader 2.0 writer\n"); TRACE("Creating DirectX9 vertex shader 2.0 writer\n");
writer->funcs = &vs_2_0_backend; writer->funcs = &vs_2_0_backend;
...@@ -1536,14 +1688,14 @@ static struct bc_writer *create_writer(DWORD version, DWORD dxversion) { ...@@ -1536,14 +1688,14 @@ static struct bc_writer *create_writer(DWORD version, DWORD dxversion) {
WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion); WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion);
goto fail; goto fail;
} }
/* TODO: Set the appropriate writer backend */ init_vs10_dx9_writer(ret);
break; break;
case BWRITERVS_VERSION(1, 1): case BWRITERVS_VERSION(1, 1):
if(dxversion != 9) { if(dxversion != 9) {
WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion); WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion);
goto fail; goto fail;
} }
/* TODO: Set the appropriate writer backend */ init_vs11_dx9_writer(ret);
break; break;
case BWRITERVS_VERSION(2, 0): case BWRITERVS_VERSION(2, 0):
if(dxversion != 9) { if(dxversion != 9) {
......
...@@ -178,6 +178,7 @@ struct instruction { ...@@ -178,6 +178,7 @@ struct instruction {
unsigned int num_srcs; /* For freeing the rel_regs */ unsigned int num_srcs; /* For freeing the rel_regs */
BOOL has_predicate; BOOL has_predicate;
struct shader_reg predicate; struct shader_reg predicate;
BOOL coissue;
}; };
struct declaration { struct declaration {
...@@ -311,6 +312,8 @@ struct asm_parser { ...@@ -311,6 +312,8 @@ struct asm_parser {
extern struct asm_parser asm_ctx; extern struct asm_parser asm_ctx;
void create_vs10_parser(struct asm_parser *ret);
void create_vs11_parser(struct asm_parser *ret);
void create_vs20_parser(struct asm_parser *ret); void create_vs20_parser(struct asm_parser *ret);
void create_vs2x_parser(struct asm_parser *ret); void create_vs2x_parser(struct asm_parser *ret);
void create_vs30_parser(struct asm_parser *ret); void create_vs30_parser(struct asm_parser *ret);
......
...@@ -1306,6 +1306,9 @@ static void failure_test(void) { ...@@ -1306,6 +1306,9 @@ static void failure_test(void) {
/* shader 37: no a0 register in ps_3_0 */ /* shader 37: no a0 register in ps_3_0 */
"ps_3_0\n" "ps_3_0\n"
"add r0, v[ a0.x ], r1\n", "add r0, v[ a0.x ], r1\n",
/* shader 38: only a0.x accepted in vs_1_1 */
"vs_1_1\n"
"mov r0, c0[ a0 ]\n",
}; };
HRESULT hr; HRESULT hr;
unsigned int i; unsigned int i;
...@@ -1392,8 +1395,6 @@ static void assembleshader_test(void) { ...@@ -1392,8 +1395,6 @@ static void assembleshader_test(void) {
struct D3DXIncludeImpl include; struct D3DXIncludeImpl include;
HRESULT shader_vsh_res, incl_vsh_res; HRESULT shader_vsh_res, incl_vsh_res;
todo_wine {
/* pDefines test */ /* pDefines test */
shader = NULL; shader = NULL;
messages = NULL; messages = NULL;
...@@ -1421,6 +1422,8 @@ static void assembleshader_test(void) { ...@@ -1421,6 +1422,8 @@ static void assembleshader_test(void) {
} }
if(shader) ID3DXBuffer_Release(shader); if(shader) ID3DXBuffer_Release(shader);
todo_wine {
shader_vsh_res = create_file("shader.vsh", testshader, sizeof(testshader)); shader_vsh_res = create_file("shader.vsh", testshader, sizeof(testshader));
if(SUCCEEDED(shader_vsh_res)) { if(SUCCEEDED(shader_vsh_res)) {
incl_vsh_res = create_file("incl.vsh", testincl, sizeof(testincl)); incl_vsh_res = create_file("incl.vsh", testincl, sizeof(testincl));
...@@ -1484,6 +1487,8 @@ static void assembleshader_test(void) { ...@@ -1484,6 +1487,8 @@ static void assembleshader_test(void) {
} }
if(shader) ID3DXBuffer_Release(shader); if(shader) ID3DXBuffer_Release(shader);
} /* end of todo_wine */
/* D3DXAssembleShaderFromResource test */ /* D3DXAssembleShaderFromResource test */
shader = NULL; shader = NULL;
messages = NULL; messages = NULL;
...@@ -1497,8 +1502,6 @@ static void assembleshader_test(void) { ...@@ -1497,8 +1502,6 @@ static void assembleshader_test(void) {
} }
if(shader) ID3DXBuffer_Release(shader); if(shader) ID3DXBuffer_Release(shader);
} /* end of todo_wine */
/* D3DXAssembleShaderFromResource with missing shader resource test */ /* D3DXAssembleShaderFromResource with missing shader resource test */
shader = NULL; shader = NULL;
messages = NULL; messages = NULL;
...@@ -1521,9 +1524,9 @@ static void assembleshader_test(void) { ...@@ -1521,9 +1524,9 @@ static void assembleshader_test(void) {
START_TEST(asm) START_TEST(asm)
{ {
todo_wine preproc_test(); preproc_test();
todo_wine ps_1_1_test(); todo_wine ps_1_1_test();
todo_wine vs_1_1_test(); vs_1_1_test();
todo_wine ps_1_3_test(); todo_wine ps_1_3_test();
todo_wine ps_1_4_test(); todo_wine ps_1_4_test();
vs_2_0_test(); vs_2_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