diff --git a/dlls/d3dx9_36/asmparser.c b/dlls/d3dx9_36/asmparser.c index bcdc85a241a..3062639f427 100644 --- a/dlls/d3dx9_36/asmparser.c +++ b/dlls/d3dx9_36/asmparser.c @@ -248,6 +248,36 @@ static void asmparser_srcreg_vs_3(struct asm_parser *This, memcpy(&instr->src[num], src, sizeof(*src)); } +static const struct allowed_reg_type ps_3_reg_allowed[] = { + { BWRITERSPR_INPUT, 10 }, + { BWRITERSPR_TEMP, 32 }, + { BWRITERSPR_CONST, 224 }, + { BWRITERSPR_CONSTINT, 16 }, + { BWRITERSPR_CONSTBOOL, 16 }, + { BWRITERSPR_PREDICATE, 1 }, + { BWRITERSPR_SAMPLER, 16 }, + { BWRITERSPR_MISCTYPE, 2 }, /* vPos and vFace */ + { BWRITERSPR_LOOP, 1 }, + { BWRITERSPR_LABEL, 2048 }, + { BWRITERSPR_COLOROUT, ~0U }, + { BWRITERSPR_DEPTHOUT, 1 }, + { ~0U, 0 } /* End tag */ +}; + +static void asmparser_srcreg_ps_3(struct asm_parser *This, + struct instruction *instr, int num, + const struct shader_reg *src) { + if(!check_reg_type(src, ps_3_reg_allowed)) { + asmparser_message(This, "Line %u: Source register %s not supported in PS 3.0\n", + This->line_no, + debug_print_srcreg(src, ST_PIXEL)); + set_parse_status(This, PARSE_ERR); + } + check_loop_swizzle(This, src); + check_legacy_srcmod(This, src->srcmod); + memcpy(&instr->src[num], src, sizeof(*src)); +} + static void asmparser_dstreg_vs_3(struct asm_parser *This, struct instruction *instr, const struct shader_reg *dst) { @@ -263,6 +293,20 @@ static void asmparser_dstreg_vs_3(struct asm_parser *This, instr->has_dst = TRUE; } +static void asmparser_dstreg_ps_3(struct asm_parser *This, + struct instruction *instr, + const struct shader_reg *dst) { + if(!check_reg_type(dst, ps_3_reg_allowed)) { + asmparser_message(This, "Line %u: Destination register %s not supported in PS 3.0\n", + This->line_no, + debug_print_dstreg(dst, ST_PIXEL)); + set_parse_status(This, PARSE_ERR); + } + check_shift_dstmod(This, instr->shift); + memcpy(&instr->dst, dst, sizeof(*dst)); + instr->has_dst = TRUE; +} + static void asmparser_predicate_supported(struct asm_parser *This, const struct shader_reg *predicate) { /* this sets the predicate of the last instruction added to the shader */ @@ -305,6 +349,26 @@ static const struct asmparser_backend parser_vs_3 = { asmparser_instr, }; +static const struct asmparser_backend parser_ps_3 = { + asmparser_constF, + asmparser_constI, + asmparser_constB, + + asmparser_dstreg_ps_3, + asmparser_srcreg_ps_3, + + asmparser_predicate_supported, + asmparser_coissue_unsupported, + + asmparser_dcl_output, + asmparser_dcl_input, + asmparser_dcl_sampler, + + asmparser_end, + + asmparser_instr, +}; + void create_vs30_parser(struct asm_parser *ret) { TRACE_(parsed_shader)("vs_3_0\n"); @@ -319,3 +383,18 @@ void create_vs30_parser(struct asm_parser *ret) { ret->shader->version = BWRITERVS_VERSION(3, 0); ret->funcs = &parser_vs_3; } + +void create_ps30_parser(struct asm_parser *ret) { + TRACE_(parsed_shader)("ps_3_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(3, 0); + ret->funcs = &parser_ps_3; +} diff --git a/dlls/d3dx9_36/asmshader.y b/dlls/d3dx9_36/asmshader.y index 657ce3c6c89..06a6825bb74 100644 --- a/dlls/d3dx9_36/asmshader.y +++ b/dlls/d3dx9_36/asmshader.y @@ -342,8 +342,7 @@ version_marker: VER_VS10 | VER_PS30 { TRACE("Pixel shader 3.0\n"); - set_parse_status(&asm_ctx, PARSE_ERR); - YYABORT; + create_ps30_parser(&asm_ctx); } instructions: /* empty */ diff --git a/dlls/d3dx9_36/bytecodewriter.c b/dlls/d3dx9_36/bytecodewriter.c index 087422f45e3..464ec521bcd 100644 --- a/dlls/d3dx9_36/bytecodewriter.c +++ b/dlls/d3dx9_36/bytecodewriter.c @@ -641,11 +641,87 @@ static const struct bytecode_backend vs_3_backend = { vs_3_handlers }; +static const struct instr_handler_table ps_3_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_LOOP, instr_handler}, + {BWRITERSIO_RET, instr_handler}, + {BWRITERSIO_ENDLOOP, instr_handler}, + + {BWRITERSIO_SETP, instr_handler}, + {BWRITERSIO_BREAKP, instr_handler}, + {BWRITERSIO_TEXLDL, instr_handler}, + + {BWRITERSIO_TEX, instr_handler}, + {BWRITERSIO_TEX | ( BWRITERSI_TEXLD_PROJECT << BWRITER_OPCODESPECIFICCONTROL_SHIFT ), instr_handler}, + {BWRITERSIO_TEX | ( BWRITERSI_TEXLD_BIAS << BWRITER_OPCODESPECIFICCONTROL_SHIFT ), instr_handler}, + {BWRITERSIO_TEXKILL, instr_handler}, + {BWRITERSIO_DSX, instr_handler}, + {BWRITERSIO_DSY, instr_handler}, + {BWRITERSIO_TEXLDD, instr_handler}, + + {BWRITERSIO_END, NULL}, +}; + +static const struct bytecode_backend ps_3_backend = { + sm_3_header, + end, + sm_3_srcreg, + sm_3_dstreg, + sm_2_opcode, + ps_3_handlers +}; + static void init_vs30_dx9_writer(struct bc_writer *writer) { TRACE("Creating DirectX9 vertex shader 3.0 writer\n"); writer->funcs = &vs_3_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; +} + static struct bc_writer *create_writer(DWORD version, DWORD dxversion) { struct bc_writer *ret = asm_alloc(sizeof(*ret)); @@ -748,7 +824,7 @@ static struct bc_writer *create_writer(DWORD version, DWORD dxversion) { WARN("Unsupported dxversion for pixel shader 3.0 requested: %u\n", dxversion); goto fail; } - /* TODO: Set the appropriate writer backend */ + init_ps30_dx9_writer(ret); break; default: diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h index e5816b335ce..923a0df25b1 100644 --- a/dlls/d3dx9_36/d3dx9_36_private.h +++ b/dlls/d3dx9_36/d3dx9_36_private.h @@ -312,6 +312,7 @@ struct asm_parser { extern struct asm_parser asm_ctx; void create_vs30_parser(struct asm_parser *ret); +void create_ps30_parser(struct asm_parser *ret); struct bwriter_shader *parse_asm_shader(char **messages); diff --git a/dlls/d3dx9_36/tests/asm.c b/dlls/d3dx9_36/tests/asm.c index b4e0ee57b58..54894df36d6 100644 --- a/dlls/d3dx9_36/tests/asm.c +++ b/dlls/d3dx9_36/tests/asm.c @@ -1125,6 +1125,22 @@ static void ps_3_0_test(void) { "texldl r0, v0, s0\n", {0xffff0300, 0x0300005f, 0x800f0000, 0x90e40000, 0xa0e40800, 0x0000ffff} }, + { /* shader 7 */ + "ps_3_0\n" + "add_pp r0, r0, r1\n", + {0xffff0300, 0x03000002, 0x802f0000, 0x80e40000, 0x80e40001, 0x0000ffff} + }, + { /* shader 8 */ + "ps_3_0\n" + "dsx_sat r0, r1\n", + {0xffff0300, 0x0200005b, 0x801f0000, 0x80e40001, 0x0000ffff} + }, + { /* shader 9 */ + "ps_3_0\n" + "texldd_pp r0, r1, r2, r3, r4\n", + {0xffff0300, 0x0500005d, 0x802f0000, 0x80e40001, 0x80e40002, 0x80e40003, + 0x80e40004, 0x0000ffff} + }, }; exec_tests("ps_3_0", tests, sizeof(tests) / sizeof(tests[0])); @@ -1212,6 +1228,9 @@ static void failure_test(void) { /* shader 24: _pp instruction modifier not allowed in vertex shaders */ "vs_3_0\n" "add_pp r0, r0, r1\n", + /* shader 25: _x4 instruction modified not allowed in > ps_1_x */ + "ps_3_0\n" + "add_x4 r0, r0, r1\n", }; HRESULT hr; unsigned int i; @@ -1437,7 +1456,7 @@ START_TEST(asm) todo_wine ps_2_0_test(); todo_wine ps_2_x_test(); vs_3_0_test(); - todo_wine ps_3_0_test(); + ps_3_0_test(); failure_test();