From 745b5fe8f1aa1de994a9fe0ce6084daf52e47314 Mon Sep 17 00:00:00 2001 From: Matteo Bruni Date: Thu, 13 May 2010 17:21:59 +0200 Subject: [PATCH] d3dx9: Add sampler dcl instruction support to the shader assembler. --- dlls/d3dx9_36/asmparser.c | 9 +++++ dlls/d3dx9_36/asmshader.l | 10 ++++++ dlls/d3dx9_36/asmshader.y | 44 ++++++++++++++++++++++++ dlls/d3dx9_36/asmutils.c | 11 ++++++ dlls/d3dx9_36/bytecodewriter.c | 59 ++++++++++++++++++++++++++++++++ dlls/d3dx9_36/d3dx9_36_private.h | 13 ++++++- dlls/d3dx9_36/tests/asm.c | 10 ++---- 7 files changed, 148 insertions(+), 8 deletions(-) diff --git a/dlls/d3dx9_36/asmparser.c b/dlls/d3dx9_36/asmparser.c index bee92f68319..6d0d31f065a 100644 --- a/dlls/d3dx9_36/asmparser.c +++ b/dlls/d3dx9_36/asmparser.c @@ -60,6 +60,14 @@ static void asmparser_dcl_input(struct asm_parser *This, DWORD usage, DWORD num, } } +static void asmparser_dcl_sampler(struct asm_parser *This, DWORD samptype, DWORD regnum, unsigned int line_no) { + if(!This->shader) return; + if(!record_sampler(This->shader, samptype, regnum)) { + 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, @@ -159,6 +167,7 @@ static const struct asmparser_backend parser_vs_3 = { asmparser_dcl_output, asmparser_dcl_input, + asmparser_dcl_sampler, asmparser_end, diff --git a/dlls/d3dx9_36/asmshader.l b/dlls/d3dx9_36/asmshader.l index b7835a81d11..9486b5333cf 100644 --- a/dlls/d3dx9_36/asmshader.l +++ b/dlls/d3dx9_36/asmshader.l @@ -81,6 +81,11 @@ DCL_FOG _fog[0-9]* DCL_DEPTH _depth[0-9]* DCL_SAMPLE _sample[0-9]* +DCL_SAMPLER1D _1d +DCL_SAMPLER2D _2d +DCL_SAMPLERCUBE _cube +DCL_SAMPLERVOLUME _volume + PREPROCESSORDIRECTIVE #[^\n]*\n /* Comments */ @@ -400,6 +405,11 @@ ps_3_0 {return VER_PS30; } return USAGE_SAMPLE; } +{DCL_SAMPLER1D} { return SAMPTYPE_1D; } +{DCL_SAMPLER2D} { return SAMPTYPE_2D; } +{DCL_SAMPLERCUBE} { return SAMPTYPE_CUBE; } +{DCL_SAMPLERVOLUME} { return SAMPTYPE_VOLUME; } + {PREPROCESSORDIRECTIVE} { /* TODO: update current line information */ TRACE("line info update: %s", yytext); diff --git a/dlls/d3dx9_36/asmshader.y b/dlls/d3dx9_36/asmshader.y index ca4d24caa5b..a6ab57e9db2 100644 --- a/dlls/d3dx9_36/asmshader.y +++ b/dlls/d3dx9_36/asmshader.y @@ -84,6 +84,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) { DWORD dclusage; unsigned int regnum; } declaration; + BWRITERSAMPLER_TEXTURE_TYPE samplertype; struct rel_reg rel_reg; struct src_regs sregs; } @@ -198,6 +199,12 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) { %token SMOD_ABS %token SMOD_NOT +/* Sampler types */ +%token SAMPTYPE_1D +%token SAMPTYPE_2D +%token SAMPTYPE_CUBE +%token SAMPTYPE_VOLUME + /* Usage declaration tokens */ %token USAGE_POSITION %token USAGE_BLENDWEIGHT @@ -232,6 +239,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) { %type omodifier %type comp %type dclusage +%type sampdcl %type rel_reg %type predicate %type immsum @@ -546,6 +554,25 @@ instruction: INSTR_ADD omods dreg ',' sregs reg.writemask = $4; asm_ctx.funcs->dcl_input(&asm_ctx, $2.dclusage, $2.regnum, ®); } + | INSTR_DCL sampdcl REG_SAMPLER + { + TRACE("Sampler declared\n"); + asm_ctx.funcs->dcl_sampler(&asm_ctx, $2, $3, asm_ctx.line_no); + } + | INSTR_DCL sampdcl REG_INPUT + { + TRACE("Error rule: sampler decl of input reg\n"); + asmparser_message(&asm_ctx, "Line %u: Sampler declarations of input regs is not valid\n", + asm_ctx.line_no); + set_parse_status(&asm_ctx, PARSE_WARN); + } + | INSTR_DCL sampdcl REG_OUTPUT + { + TRACE("Error rule: sampler decl of output reg\n"); + asmparser_message(&asm_ctx, "Line %u: Sampler declarations of output regs is not valid\n", + asm_ctx.line_no); + set_parse_status(&asm_ctx, PARSE_WARN); + } | INSTR_REP sregs { TRACE("REP\n"); @@ -1196,6 +1223,23 @@ dclusage: USAGE_POSITION $$.dclusage = BWRITERDECLUSAGE_SAMPLE; } +sampdcl: SAMPTYPE_1D + { + $$ = BWRITERSTT_1D; + } + | SAMPTYPE_2D + { + $$ = BWRITERSTT_2D; + } + | SAMPTYPE_CUBE + { + $$ = BWRITERSTT_CUBE; + } + | SAMPTYPE_VOLUME + { + $$ = BWRITERSTT_VOLUME; + } + predicate: '(' REG_PREDICATE swizzle ')' { $$.type = BWRITERSPR_PREDICATE; diff --git a/dlls/d3dx9_36/asmutils.c b/dlls/d3dx9_36/asmutils.c index c5098ca1aab..c34f5f5669a 100644 --- a/dlls/d3dx9_36/asmutils.c +++ b/dlls/d3dx9_36/asmutils.c @@ -105,6 +105,17 @@ DWORD d3d9_comparetype(DWORD asmshader_comparetype) { } } +DWORD d3d9_sampler(DWORD bwriter_sampler) { + if(bwriter_sampler == BWRITERSTT_UNKNOWN) return D3DSTT_UNKNOWN; + if(bwriter_sampler == BWRITERSTT_1D) return D3DSTT_1D; + if(bwriter_sampler == BWRITERSTT_2D) return D3DSTT_2D; + if(bwriter_sampler == BWRITERSTT_CUBE) return D3DSTT_CUBE; + if(bwriter_sampler == BWRITERSTT_VOLUME) return D3DSTT_VOLUME; + FIXME("Unexpected BWRITERSAMPLER_TEXTURE_TYPE type %u\n", bwriter_sampler); + + return 0; +} + DWORD d3d9_register(DWORD bwriter_register) { if(bwriter_register == BWRITERSPR_TEMP) return D3DSPR_TEMP; if(bwriter_register == BWRITERSPR_INPUT) return D3DSPR_INPUT; diff --git a/dlls/d3dx9_36/bytecodewriter.c b/dlls/d3dx9_36/bytecodewriter.c index 4d624651371..82a365537ba 100644 --- a/dlls/d3dx9_36/bytecodewriter.c +++ b/dlls/d3dx9_36/bytecodewriter.c @@ -151,6 +151,44 @@ BOOL record_declaration(struct bwriter_shader *shader, DWORD usage, DWORD usage_ return TRUE; } +BOOL record_sampler(struct bwriter_shader *shader, DWORD samptype, DWORD regnum) { + unsigned int i; + + if(!shader) return FALSE; + + if(shader->num_samplers == 0) { + shader->samplers = asm_alloc(sizeof(*shader->samplers)); + if(!shader->samplers) { + ERR("Error allocating samplers array\n"); + return FALSE; + } + } else { + struct samplerdecl *newarray; + + for(i = 0; i < shader->num_samplers; i++) { + if(shader->samplers[i].regnum == regnum) { + WARN("Sampler %u already declared\n", regnum); + /* This is not an error as far as the assembler is concerned. + * Direct3D might refuse to load the compiled shader though + */ + } + } + + newarray = asm_realloc(shader->samplers, + sizeof(*shader->samplers) * (shader->num_samplers + 1)); + if(!newarray) { + ERR("Error reallocating samplers array\n"); + return FALSE; + } + shader->samplers = newarray; + } + + shader->samplers[shader->num_samplers].type = samptype; + shader->samplers[shader->num_samplers].regnum = regnum; + shader->num_samplers++; + return TRUE; +} + /* shader bytecode buffer manipulation functions. * allocate_buffer creates a new buffer structure, put_dword adds a new @@ -280,12 +318,33 @@ static void sm_2_opcode(struct bc_writer *This, put_dword(buffer,token); } +static void write_samplers(const struct bwriter_shader *shader, struct bytecode_buffer *buffer) { + DWORD i; + DWORD instr_dcl = D3DSIO_DCL | (2 << D3DSI_INSTLENGTH_SHIFT); + DWORD token; + const DWORD reg = (1<<31) | + ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK) | + ((D3DSPR_SAMPLER << D3DSP_REGTYPE_SHIFT2) & D3DSP_REGTYPE_MASK2) | + D3DSP_WRITEMASK_ALL; + + for(i = 0; i < shader->num_samplers; i++) { + /* Write the DCL instruction */ + put_dword(buffer, instr_dcl); + token = (1<<31); + /* Already shifted */ + token |= (d3d9_sampler(shader->samplers[i].type)) & D3DSP_TEXTURETYPE_MASK; + put_dword(buffer, token); + put_dword(buffer, reg | (shader->samplers[i].regnum & D3DSP_REGNUM_MASK)); + } +} + 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); write_declarations(buffer, TRUE, shader->inputs, shader->num_inputs, D3DSPR_INPUT); write_declarations(buffer, TRUE, shader->outputs, shader->num_outputs, D3DSPR_OUTPUT); + write_samplers(shader, buffer); return; } diff --git a/dlls/d3dx9_36/d3dx9_36_private.h b/dlls/d3dx9_36/d3dx9_36_private.h index 344bdbfa33b..a102e65f749 100644 --- a/dlls/d3dx9_36/d3dx9_36_private.h +++ b/dlls/d3dx9_36/d3dx9_36_private.h @@ -179,7 +179,6 @@ struct declaration { struct samplerdecl { DWORD type; DWORD regnum; - unsigned int line_no; /* for error messages */ }; #define INSTRARRAY_INITIAL_SIZE 8 @@ -257,6 +256,8 @@ struct asmparser_backend { const struct shader_reg *reg); void (*dcl_input)(struct asm_parser *This, DWORD usage, DWORD num, const struct shader_reg *reg); + void (*dcl_sampler)(struct asm_parser *This, DWORD samptype, DWORD regnum, + unsigned int line_no); void (*end)(struct asm_parser *This); @@ -268,6 +269,7 @@ struct asmparser_backend { struct instruction *alloc_instr(unsigned int srcs); BOOL add_instruction(struct bwriter_shader *shader, struct instruction *instr); BOOL record_declaration(struct bwriter_shader *shader, DWORD usage, DWORD usage_idx, BOOL output, DWORD regnum, DWORD writemask); +BOOL record_sampler(struct bwriter_shader *shader, DWORD samptype, DWORD regnum); #define MESSAGEBUFFER_INITIAL_SIZE 256 @@ -366,6 +368,7 @@ DWORD d3d9_writemask(DWORD bwriter_writemask); DWORD d3d9_srcmod(DWORD bwriter_srcmod); DWORD d3d9_dstmod(DWORD bwriter_mod); DWORD d3d9_comparetype(DWORD bwriter_comparetype); +DWORD d3d9_sampler(DWORD bwriter_sampler); DWORD d3d9_register(DWORD bwriter_register); DWORD d3d9_opcode(DWORD bwriter_opcode); @@ -476,6 +479,14 @@ typedef enum _BWRITERSHADER_PARAM_DSTMOD_TYPE { BWRITERSPDM_MSAMPCENTROID = 4, } BWRITERSHADER_PARAM_DSTMOD_TYPE; +typedef enum _BWRITERSAMPLER_TEXTURE_TYPE { + BWRITERSTT_UNKNOWN = 0, + BWRITERSTT_1D = 1, + BWRITERSTT_2D = 2, + BWRITERSTT_CUBE = 3, + BWRITERSTT_VOLUME = 4, +} BWRITERSAMPLER_TEXTURE_TYPE; + typedef enum _BWRITERSHADER_PARAM_SRCMOD_TYPE { BWRITERSPSM_NONE = 0, BWRITERSPSM_NEG, diff --git a/dlls/d3dx9_36/tests/asm.c b/dlls/d3dx9_36/tests/asm.c index dd51a95471c..21adb8112be 100644 --- a/dlls/d3dx9_36/tests/asm.c +++ b/dlls/d3dx9_36/tests/asm.c @@ -1008,21 +1008,17 @@ static void ps_2_x_test(void) { } static void vs_3_0_test(void) { - /* FIXME: Some tests are temporarily commented out, because the - current implementation doesn't support the entire vs_3_0 syntax - and it is not trivial to remove todo_wine only from - a subset of the tests here */ struct shader_test tests[] = { { /* shader 0 */ "vs_3_0\n" "mov r0, c0\n", {0xfffe0300, 0x02000001, 0x800f0000, 0xa0e40000, 0x0000ffff} }, -/* {*/ /* shader 1 */ -/* "vs_3_0\n" + { /* shader 1 */ + "vs_3_0\n" "dcl_2d s0\n", {0xfffe0300, 0x0200001f, 0x90000000, 0xa00f0800, 0x0000ffff} - },*/ + }, { /* shader 2 */ "vs_3_0\n" "dcl_position o0\n",