[9/18] d3dx9: Shader assembler VS 1.X support
Matteo Bruni
matteo.mystral at gmail.com
Sun Aug 16 12:52:41 CDT 2009
-------------- next part --------------
From eed13bf147915f8b2917c5d778846182046e0515 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Sun, 16 Aug 2009 01:02:16 +0200
Subject: d3dx9: Shader assembler VS 1.X support
---
dlls/d3dx9_36/asmparser.c | 109 ++++++++++++++++++++++++++
dlls/d3dx9_36/asmshader.y | 4 +-
dlls/d3dx9_36/bytecodewriter.c | 167 +++++++++++++++++++++++++++++++++++++++-
3 files changed, 276 insertions(+), 4 deletions(-)
diff --git a/dlls/d3dx9_36/asmparser.c b/dlls/d3dx9_36/asmparser.c
index c268a0a..2560c0b 100644
--- a/dlls/d3dx9_36/asmparser.c
+++ b/dlls/d3dx9_36/asmparser.c
@@ -311,6 +311,47 @@ static BOOL check_reg_type(const struct shader_reg *reg,
return FALSE;
}
+/* Native compiler doesn't make separate checks for src and dst registers */
+struct allowed_reg_type vs_1_reg_allowed[] = {
+ { BWRITERSPR_TEMP, 12 },
+ { BWRITERSPR_INPUT, 16 },
+ { BWRITERSPR_CONST, ~0U },
+ { BWRITERSPR_ADDR, 1 },
+ { BWRITERSPR_RASTOUT, 3 }, /* oPos, oFog and oPts */
+ { BWRITERSPR_ATTROUT, 2 },
+ { BWRITERSPR_TEXCRDOUT, 8 },
+ { ~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], ®, sizeof(reg));
+}
+
struct allowed_reg_type vs_2_reg_allowed[] = {
{ BWRITERSPR_TEMP, 12 },
{ BWRITERSPR_INPUT, 16 },
@@ -466,6 +507,22 @@ static void asmparser_srcreg_ps_3(struct asm_parser *This,
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);
+ }
+ reg = map_oldvs_register(dst);
+ memcpy(&instr->dst, ®, sizeof(reg));
+ instr->has_dst = TRUE;
+}
+
static void asmparser_dstreg_vs_2(struct asm_parser *This,
struct instruction *instr,
const struct shader_reg *dst) {
@@ -564,6 +621,26 @@ static void asmparser_coissue_unsupported(struct asm_parser *This) {
set_parse_status(This, PARSE_ERR);
}
+static 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 struct asmparser_backend parser_vs_2 = {
asmparser_constF,
asmparser_constI,
@@ -695,6 +772,38 @@ static void gen_oldps_input(struct bwriter_shader *shader, DWORD texcoords) {
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) {
TRACE_(parsed_shader)("vs_2_0\n");
diff --git a/dlls/d3dx9_36/asmshader.y b/dlls/d3dx9_36/asmshader.y
index 7e142ad..653d4e9 100644
--- a/dlls/d3dx9_36/asmshader.y
+++ b/dlls/d3dx9_36/asmshader.y
@@ -300,12 +300,12 @@ shader: version_marker instructions
version_marker: VER_VS10
{
TRACE("Vertex shader 1.0\n");
- /* TODO: create the appropriate parser context */
+ create_vs10_parser(ctx);
}
| VER_VS11
{
TRACE("Vertex shader 1.1\n");
- /* TODO: create the appropriate parser context */
+ create_vs11_parser(ctx);
}
| VER_VS20
{
diff --git a/dlls/d3dx9_36/bytecodewriter.c b/dlls/d3dx9_36/bytecodewriter.c
index a7d2322..1090bce 100644
--- a/dlls/d3dx9_36/bytecodewriter.c
+++ b/dlls/d3dx9_36/bytecodewriter.c
@@ -496,6 +496,31 @@ static HRESULT find_builtin_varyings(struct bc_writer *This, const struct bwrite
return S_OK;
}
+static void vs_1_x_header(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
+ HRESULT hr;
+
+ /* First check the constants and varyings, and complain if unsupported things are used */
+ 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 = 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 void ps_legacy_header(struct bc_writer *This, const struct bwriter_shader *shader,
struct bytecode_buffer *buffer, DWORD texcoords,
BOOL has_instr_len) {
@@ -706,6 +731,83 @@ static void vs_12_dstreg(struct bc_writer *This, const struct shader_reg *reg,
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:
+ /* The output register component is stored as a writemask, since that is the form most
+ * commonly used. If we're reading from it, we've got a swizzle. If this swizzle selects
+ * a single component, map it to a writemask selecting this component, otherwise
+ * 0 does the job. If a component is needed to identify the register, an unconvertible
+ * swizzle is an error anyway
+ */
+ if(reg->swizzle == BWRITERVS_SWIZZLE_X) {
+ component = BWRITERSP_WRITEMASK_0;
+ } else if(reg->swizzle == BWRITERVS_SWIZZLE_Y) {
+ component = BWRITERSP_WRITEMASK_1;
+ } else if(reg->swizzle == BWRITERVS_SWIZZLE_Z) {
+ component = BWRITERSP_WRITEMASK_2;
+ } else if(reg->swizzle == BWRITERVS_SWIZZLE_W) {
+ component = BWRITERSP_WRITEMASK_3;
+ } else {
+ component = 0;
+ }
+ token |= 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:
+ 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;
+
+ case BWRITERSPR_ADDR:
+ /* This is only supported for relative addressing or as a mov dest reg */
+ WARN("D3DSPR_ADDR is not valid as an src reg\n");
+ This->state = E_INVALIDARG;
+ return;
+
+ 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 */
+
+ if(reg->srcmod == BWRITERSPSM_DZ || reg->srcmod == BWRITERSPSM_DW ||
+ reg->srcmod == BWRITERSPSM_ABS || reg->srcmod == BWRITERSPSM_ABSNEG ||
+ reg->srcmod == BWRITERSPSM_NOT) {
+ WARN("Invalid source modifier %u for vs_1_x\n", reg->srcmod);
+ This->state = E_INVALIDARG;
+ return;
+ }
+ token |= d3d9_srcmod(reg->srcmod);
+ put_dword(buffer, token);
+}
+
static void write_srcregs(struct bc_writer *This, const struct instruction *instr,
struct bytecode_buffer *buffer){
unsigned int i;
@@ -778,6 +880,16 @@ static DWORD instrlen(const struct instruction *instr, unsigned int srcs, unsign
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,
const struct instruction *instr,
struct bytecode_buffer *buffer) {
@@ -789,6 +901,47 @@ static void instr_handler(struct bc_writer *This,
write_srcregs(This, instr, buffer);
}
+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 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) {
DWORD i;
DWORD instr_def = D3DSIO_DEFB;
@@ -1635,6 +1788,16 @@ static struct bytecode_backend ps_3_backend = {
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) {
TRACE("Creating DirectX9 vertex shader 2.0 writer\n");
writer->funcs = &vs_2_0_backend;
@@ -1679,14 +1842,14 @@ static struct bc_writer *create_writer(DWORD version, DWORD dxversion) {
WARN("Unsupported dxversion for vertex shader 1.0 requested: %u\n", dxversion);
goto fail;
}
- /* TODO: Set the appropriate writer backend */
+ init_vs10_dx9_writer(ret);
break;
case BWRITERVS_VERSION(1, 1):
if(dxversion != 9) {
WARN("Unsupported dxversion for vertex shader 1.1 requested: %u\n", dxversion);
goto fail;
}
- /* TODO: Set the appropriate writer backend */
+ init_vs11_dx9_writer(ret);
break;
case BWRITERVS_VERSION(2, 0):
if(dxversion != 9) {
--
1.6.3.3
More information about the wine-patches
mailing list