Commit b627d13e authored by Matteo Bruni's avatar Matteo Bruni Committed by Alexandre Julliard

d3dx9: Add output dcl instruction partial support to the shader assembler.

parent c79be420
......@@ -38,6 +38,19 @@ static void asmparser_end(struct asm_parser *This) {
TRACE("Finalizing shader\n");
}
static void asmparser_dcl_output(struct asm_parser *This, DWORD usage, DWORD num,
const struct shader_reg *reg) {
if(!This->shader) return;
if(This->shader->type == ST_PIXEL) {
asmparser_message(This, "Line %u: Output register declared in a pixel shader\n", This->line_no);
set_parse_status(This, PARSE_ERR);
}
if(!record_declaration(This->shader, usage, num, TRUE, reg->regnum, reg->writemask)) {
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,
......@@ -135,6 +148,8 @@ static const struct asmparser_backend parser_vs_3 = {
asmparser_predicate_supported,
asmparser_coissue_unsupported,
asmparser_dcl_output,
asmparser_end,
asmparser_instr,
......
......@@ -66,6 +66,8 @@ REG_PREDICATE p0
/* Not really a register, but it is considered as such */
REG_LABEL l[0-9]+
DCL_POSITION _position[0-9]*
PREPROCESSORDIRECTIVE #[^\n]*\n
/* Comments */
......@@ -117,6 +119,7 @@ m4x3 {return INSTR_M4x3; }
m3x4 {return INSTR_M3x4; }
m3x3 {return INSTR_M3x3; }
m3x2 {return INSTR_M3x2; }
dcl {return INSTR_DCL; }
rep {return INSTR_REP; }
endrep {return INSTR_ENDREP; }
if {return INSTR_IF; }
......@@ -271,6 +274,15 @@ ps_3_0 {return VER_PS30; }
! {return SMOD_NOT; }
{DCL_POSITION} {
if(yytext[strlen("_position")] == '\0') {
asmshader_lval.regnum = 0;
} else {
asmshader_lval.regnum = atoi(yytext + strlen("_position"));
}
return USAGE_POSITION;
}
{PREPROCESSORDIRECTIVE} {
/* TODO: update current line information */
TRACE("line info update: %s", yytext);
......
......@@ -80,6 +80,10 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
DWORD shift;
} modshift;
BWRITER_COMPARISON_TYPE comptype;
struct {
DWORD dclusage;
unsigned int regnum;
} declaration;
struct rel_reg rel_reg;
struct src_regs sregs;
}
......@@ -117,6 +121,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
%token INSTR_M3x4
%token INSTR_M3x3
%token INSTR_M3x2
%token INSTR_DCL
%token INSTR_REP
%token INSTR_ENDREP
%token INSTR_IF
......@@ -193,6 +198,9 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
%token SMOD_ABS
%token SMOD_NOT
/* Usage declaration tokens */
%token <regnum> USAGE_POSITION
/* Misc stuff */
%token <component> COMPONENT
%token <immval> IMMVAL
......@@ -210,6 +218,7 @@ void set_rel_reg(struct shader_reg *reg, struct rel_reg *rel) {
%type <modshift> omods
%type <modshift> omodifier
%type <comptype> comp
%type <declaration> dclusage
%type <rel_reg> rel_reg
%type <reg> predicate
%type <immval> immsum
......@@ -476,6 +485,30 @@ instruction: INSTR_ADD omods dreg ',' sregs
TRACE("M3x2\n");
asm_ctx.funcs->instr(&asm_ctx, BWRITERSIO_M3x2, $2.mod, $2.shift, 0, &$3, &$5, 2);
}
| INSTR_DCL dclusage REG_OUTPUT
{
struct shader_reg reg;
TRACE("Output reg declaration\n");
ZeroMemory(&reg, sizeof(reg));
reg.type = BWRITERSPR_OUTPUT;
reg.regnum = $3;
reg.rel_reg = NULL;
reg.srcmod = 0;
reg.writemask = BWRITERSP_WRITEMASK_ALL;
asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
}
| INSTR_DCL dclusage REG_OUTPUT writemask
{
struct shader_reg reg;
TRACE("Output reg declaration\n");
ZeroMemory(&reg, sizeof(reg));
reg.type = BWRITERSPR_OUTPUT;
reg.regnum = $3;
reg.rel_reg = NULL;
reg.srcmod = 0;
reg.writemask = $4;
asm_ctx.funcs->dcl_output(&asm_ctx, $2.dclusage, $2.regnum, &reg);
}
| INSTR_REP sregs
{
TRACE("REP\n");
......@@ -1041,6 +1074,13 @@ comp: COMP_GT { $$ = BWRITER_COMPARISON_GT; }
| COMP_EQ { $$ = BWRITER_COMPARISON_EQ; }
| COMP_NE { $$ = BWRITER_COMPARISON_NE; }
dclusage: USAGE_POSITION
{
TRACE("dcl_position%u\n", $1);
$$.regnum = $1;
$$.dclusage = BWRITERDECLUSAGE_POSITION;
}
predicate: '(' REG_PREDICATE swizzle ')'
{
$$.type = BWRITERSPR_PREDICATE;
......
......@@ -162,6 +162,7 @@ DWORD d3d9_opcode(DWORD bwriter_opcode) {
case BWRITERSIO_RET: return D3DSIO_RET;
case BWRITERSIO_ENDLOOP: return D3DSIO_ENDLOOP;
case BWRITERSIO_LABEL: return D3DSIO_LABEL;
case BWRITERSIO_DCL: return D3DSIO_DCL;
case BWRITERSIO_POW: return D3DSIO_POW;
case BWRITERSIO_CRS: return D3DSIO_CRS;
case BWRITERSIO_SGN: return D3DSIO_SGN;
......@@ -426,6 +427,7 @@ const char *debug_print_opcode(DWORD opcode) {
case BWRITERSIO_RET: return "ret";
case BWRITERSIO_ENDLOOP: return "endloop";
case BWRITERSIO_LABEL: return "label";
case BWRITERSIO_DCL: return "dcl";
case BWRITERSIO_POW: return "pow";
case BWRITERSIO_CRS: return "crs";
case BWRITERSIO_SGN: return "sgn";
......
......@@ -104,6 +104,54 @@ BOOL add_instruction(struct bwriter_shader *shader, struct instruction *instr) {
return TRUE;
}
BOOL record_declaration(struct bwriter_shader *shader, DWORD usage, DWORD usage_idx, BOOL output, DWORD regnum, DWORD writemask) {
unsigned int *num;
struct declaration **decl;
unsigned int i;
if(!shader) return FALSE;
if(output) {
num = &shader->num_outputs;
decl = &shader->outputs;
} else {
num = &shader->num_inputs;
decl = &shader->inputs;
}
if(*num == 0) {
*decl = asm_alloc(sizeof(**decl));
if(!*decl) {
ERR("Error allocating declarations array\n");
return FALSE;
}
} else {
struct declaration *newdecl;
for(i = 0; i < *num; i++) {
if((*decl)[i].regnum == regnum && ((*decl)[i].writemask & writemask)) {
WARN("Declaration of register %u already exists, writemask match 0x%x\n",
regnum, (*decl)[i].writemask & writemask);
}
}
newdecl = asm_realloc(*decl,
sizeof(**decl) * ((*num) + 1));
if(!newdecl) {
ERR("Error reallocating declarations array\n");
return FALSE;
}
*decl = newdecl;
}
(*decl)[*num].usage = usage;
(*decl)[*num].usage_idx = usage_idx;
(*decl)[*num].regnum = regnum;
(*decl)[*num].writemask = writemask;
(*num)++;
return TRUE;
}
/* shader bytecode buffer manipulation functions.
* allocate_buffer creates a new buffer structure, put_dword adds a new
* DWORD to the buffer. In the rare case of a memory allocation failure
......@@ -147,6 +195,35 @@ static void put_dword(struct bytecode_buffer *buffer, DWORD value) {
/******************************************************
* Implementation of the writer functions starts here *
******************************************************/
static void write_declarations(struct bytecode_buffer *buffer, BOOL len,
const struct declaration *decls, unsigned int num, DWORD type) {
DWORD i;
DWORD instr_dcl = D3DSIO_DCL;
DWORD token;
if(len) {
instr_dcl |= 2 << D3DSI_INSTLENGTH_SHIFT;
}
for(i = 0; i < num; i++) {
/* Write the DCL instruction */
put_dword(buffer, instr_dcl);
/* Write the usage and index */
token = (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
token |= (decls[i].usage << D3DSP_DCL_USAGE_SHIFT) & D3DSP_DCL_USAGE_MASK;
token |= (decls[i].usage_idx << D3DSP_DCL_USAGEINDEX_SHIFT) & D3DSP_DCL_USAGEINDEX_MASK;
put_dword(buffer, token);
/* Write the dest register */
token = (1 << 31); /* Bit 31 of non-instruction opcodes is 1 */
token |= (type << D3DSP_REGTYPE_SHIFT) & D3DSP_REGTYPE_MASK;
token |= (d3d9_writemask(decls[i].writemask)) & D3DSP_WRITEMASK_ALL;
token |= decls[i].regnum & D3DSP_REGNUM_MASK;
put_dword(buffer, token);
}
}
static void end(struct bc_writer *This, const struct bwriter_shader *shader, struct bytecode_buffer *buffer) {
put_dword(buffer, D3DSIO_END);
}
......@@ -206,6 +283,8 @@ static void sm_2_opcode(struct bc_writer *This,
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->outputs, shader->num_outputs, D3DSPR_OUTPUT);
return;
}
......
......@@ -253,6 +253,9 @@ struct asmparser_backend {
const struct shader_reg *predicate);
void (*coissue)(struct asm_parser *This);
void (*dcl_output)(struct asm_parser *This, DWORD usage, DWORD num,
const struct shader_reg *reg);
void (*end)(struct asm_parser *This);
void (*instr)(struct asm_parser *This, DWORD opcode, DWORD mod, DWORD shift,
......@@ -262,6 +265,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);
#define MESSAGEBUFFER_INITIAL_SIZE 256
......@@ -402,6 +406,7 @@ typedef enum _BWRITERSHADER_INSTRUCTION_OPCODE_TYPE {
BWRITERSIO_RET,
BWRITERSIO_ENDLOOP,
BWRITERSIO_LABEL,
BWRITERSIO_DCL,
BWRITERSIO_POW,
BWRITERSIO_CRS,
BWRITERSIO_SGN,
......@@ -513,6 +518,10 @@ typedef enum _BWRITERSHADER_PARAM_SRCMOD_TYPE {
#define BWRITERVS_SWIZZLE_Z (BWRITERVS_X_Z | BWRITERVS_Y_Z | BWRITERVS_Z_Z | BWRITERVS_W_Z)
#define BWRITERVS_SWIZZLE_W (BWRITERVS_X_W | BWRITERVS_Y_W | BWRITERVS_Z_W | BWRITERVS_W_W)
typedef enum _BWRITERDECLUSAGE {
BWRITERDECLUSAGE_POSITION,
} BWRITERDECLUSAGE;
struct bwriter_shader *SlAssembleShader(const char *text, char **messages);
DWORD SlWriteBytecode(const struct bwriter_shader *shader, int dxversion, DWORD **result);
void SlDeleteShader(struct bwriter_shader *shader);
......
......@@ -1023,11 +1023,11 @@ static void vs_3_0_test(void) {
"dcl_2d s0\n",
{0xfffe0300, 0x0200001f, 0x90000000, 0xa00f0800, 0x0000ffff}
},*/
/* {*/ /* shader 2 */
/* "vs_3_0\n"
{ /* shader 2 */
"vs_3_0\n"
"dcl_position o0\n",
{0xfffe0300, 0x0200001f, 0x80000000, 0xe00f0000, 0x0000ffff}
},*/
},
/* {*/ /* shader 3 */
/* "vs_3_0\n"
"dcl_texcoord12 o11\n",
......
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