wined3d: More flow control instructions

- Implement if, else, endif, rep, endrep, break
- Implement ifc, breakc, using undocumented comparison bits in the instruction token
- Fix bug in main loop processing of codes with no dst token
- Fix bug in GLSL output modifier processing of codes with no dst token
- Fix bug in loop implementation (src1 contains the integer data, src0 is aL)
- Add versioning for all the instructions above, and remove
  GLSL_REQUIRED thing, which is useless and should be removed from all
  opcodes in general.
This commit is contained in:
Ivan Gyurdiev 2006-07-10 03:11:35 -06:00 committed by Alexandre Julliard
parent 345dd49eda
commit 6ede56495a
5 changed files with 148 additions and 46 deletions

View file

@ -273,7 +273,8 @@ HRESULT shader_get_registers_used(
pToken += curOpcode->num_params;
/* If there's a loop in the shader */
} else if (D3DSIO_LOOP == curOpcode->opcode) {
} else if (D3DSIO_LOOP == curOpcode->opcode ||
D3DSIO_REP == curOpcode->opcode) {
reg_maps->loop = 1;
pToken += curOpcode->num_params;
@ -632,7 +633,6 @@ void shader_generate_main(
const DWORD *pToken = pFunction;
const SHADER_OPCODE *curOpcode = NULL;
SHADER_HANDLER hw_fct = NULL;
DWORD opcode_token;
DWORD i;
SHADER_OPCODE_ARG hw_arg;
@ -662,8 +662,8 @@ void shader_generate_main(
}
/* Read opcode */
opcode_token = *pToken++;
curOpcode = shader_get_opcode(iface, opcode_token);
hw_arg.opcode_token = *pToken++;
curOpcode = shader_get_opcode(iface, hw_arg.opcode_token);
/* Select handler */
if (curOpcode == NULL)
@ -675,7 +675,7 @@ void shader_generate_main(
/* Unknown opcode and its parameters */
if (NULL == curOpcode) {
FIXME("Unrecognized opcode: token=%08lX\n", opcode_token);
FIXME("Unrecognized opcode: token=%08lX\n", hw_arg.opcode_token);
pToken += shader_skip_unrecognized(iface, pToken);
/* Nothing to do */
@ -685,7 +685,7 @@ void shader_generate_main(
D3DSIO_DEFI == curOpcode->opcode ||
D3DSIO_DEFB == curOpcode->opcode) {
pToken += shader_skip_opcode(This, curOpcode, opcode_token);
pToken += shader_skip_opcode(This, curOpcode, hw_arg.opcode_token);
/* If a generator function is set for current shader target, use it */
} else if (hw_fct != NULL) {
@ -702,17 +702,16 @@ void shader_generate_main(
}
/* Predication token */
if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED)
if (hw_arg.opcode_token & D3DSHADER_INSTRUCTION_PREDICATED)
hw_arg.predicate = *pToken++;
/* Other source tokens */
for (i = curOpcode->dst_token; i < curOpcode->num_params; i++) {
for (i = 0; i < (curOpcode->num_params - curOpcode->dst_token); i++) {
DWORD param, addr_token = 0;
pToken += shader_get_param(iface, pToken, &param, &addr_token);
hw_arg.src[i-1] = param;
hw_arg.src_addr[i-1] = addr_token;
hw_arg.src[i] = param;
hw_arg.src_addr[i] = addr_token;
}
/* Call appropriate function for output target */
@ -726,7 +725,7 @@ void shader_generate_main(
} else {
FIXME("Can't handle opcode %s in hwShader\n", curOpcode->name);
pToken += shader_skip_opcode(This, curOpcode, opcode_token);
pToken += shader_skip_opcode(This, curOpcode, hw_arg.opcode_token);
}
}
/* TODO: What about result.depth? */
@ -863,6 +862,22 @@ void shader_trace_init(
TRACE("%s", curOpcode->name);
if (curOpcode->opcode == D3DSIO_IFC ||
curOpcode->opcode == D3DSIO_BREAKC) {
DWORD op = (opcode_token & INST_CONTROLS_MASK) >> INST_CONTROLS_SHIFT;
switch (op) {
case COMPARISON_GT: TRACE("_gt"); break;
case COMPARISON_EQ: TRACE("_eq"); break;
case COMPARISON_GE: TRACE("_ge"); break;
case COMPARISON_LT: TRACE("_lt"); break;
case COMPARISON_NE: TRACE("_ne"); break;
case COMPARISON_LE: TRACE("_le"); break;
default:
TRACE("_(%lu)", op);
}
}
/* Destination token */
if (curOpcode->dst_token) {

View file

@ -755,9 +755,10 @@ static void shader_glsl_add_param(
/** Process GLSL instruction modifiers */
void shader_glsl_add_instruction_modifiers(SHADER_OPCODE_ARG* arg) {
if (0 != (arg->dst & D3DSP_DSTMOD_MASK)) {
DWORD mask = arg->dst & D3DSP_DSTMOD_MASK;
DWORD mask = arg->dst & D3DSP_DSTMOD_MASK;
if (arg->opcode->dst_token && mask != 0) {
char dst_reg[50];
char dst_mask[6];
char dst_str[100];
@ -777,6 +778,23 @@ void shader_glsl_add_instruction_modifiers(SHADER_OPCODE_ARG* arg) {
}
}
static inline const char* shader_get_comp_op(
const DWORD opcode) {
DWORD op = (opcode & INST_CONTROLS_MASK) >> INST_CONTROLS_SHIFT;
switch (op) {
case COMPARISON_GT: return ">";
case COMPARISON_EQ: return "==";
case COMPARISON_GE: return ">=";
case COMPARISON_LT: return "<";
case COMPARISON_NE: return "!=";
case COMPARISON_LE: return "<=";
default:
FIXME("Unrecognized comparison value: %lu\n", op);
return "(\?\?)";
}
}
/*****************************************************************************
*
* Begin processing individual instruction opcodes
@ -1152,24 +1170,73 @@ void shader_glsl_sincos(SHADER_OPCODE_ARG* arg) {
*/
void shader_glsl_loop(SHADER_OPCODE_ARG* arg) {
char src0_str[100];
char src0_reg[50];
char src0_mask[6];
char src1_str[100];
char src1_reg[50];
char src1_mask[6];
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
shader_addline(arg->buffer, "for (tmpInt = 0, aL = %s.y; tmpInt < %s.x; tmpInt++, aL += %s.z) {\n",
src0_reg, src0_reg, src0_reg);
src1_reg, src1_reg, src1_reg);
}
/** Process the D3DSIO_ENDLOOP instruction in GLSL:
* End the for() loop
*/
void shader_glsl_endloop(SHADER_OPCODE_ARG* arg) {
void shader_glsl_end(SHADER_OPCODE_ARG* arg) {
shader_addline(arg->buffer, "}\n");
}
void shader_glsl_rep(SHADER_OPCODE_ARG* arg) {
char src0_str[100];
char src0_reg[50];
char src0_mask[6];
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
shader_addline(arg->buffer, "for (tmpInt = 0; tmpInt < %s.x; tmpInt++) {\n", src0_reg);
}
void shader_glsl_if(SHADER_OPCODE_ARG* arg) {
char src0_str[100];
char src0_reg[50];
char src0_mask[6];
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
shader_addline(arg->buffer, "if (%s) {\n", src0_str);
}
void shader_glsl_ifc(SHADER_OPCODE_ARG* arg) {
char src0_str[100], src1_str[100];
char src0_reg[50], src1_reg[50];
char src0_mask[6], src1_mask[6];
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
shader_addline(arg->buffer, "if (%s %s %s) {\n",
src0_str, shader_get_comp_op(arg->opcode_token), src1_str);
}
void shader_glsl_else(SHADER_OPCODE_ARG* arg) {
shader_addline(arg->buffer, "} else {\n");
}
void shader_glsl_break(SHADER_OPCODE_ARG* arg) {
shader_addline(arg->buffer, "break;\n");
}
void shader_glsl_breakc(SHADER_OPCODE_ARG* arg) {
char src0_str[100], src1_str[100];
char src0_reg[50], src1_reg[50];
char src0_mask[6], src1_mask[6];
shader_glsl_add_param(arg, arg->src[0], arg->src_addr[0], TRUE, src0_reg, src0_mask, src0_str);
shader_glsl_add_param(arg, arg->src[1], arg->src_addr[1], TRUE, src1_reg, src1_mask, src1_str);
shader_addline(arg->buffer, "if (%s %s %s) break;\n",
src0_str, shader_get_comp_op(arg->opcode_token), src1_str);
}
/*********************************************
* Pixel Shader Specific Code begins here

View file

@ -676,20 +676,20 @@ CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
{D3DSIO_DCL, "dcl", NULL, 0, 2, pshader_dcl, NULL, NULL, 0, 0},
/* Flow control - requires GLSL or software shaders */
{D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 0, 1, pshader_rep, NULL, NULL, 0, 0},
{D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, 0, pshader_endrep, NULL, NULL, 0, 0},
{D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 0, 1, pshader_if, NULL, NULL, 0, 0},
{D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 0, 2, pshader_ifc, NULL, NULL, 0, 0},
{D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 0, 0, pshader_else, NULL, NULL, 0, 0},
{D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 0, 0, pshader_endif, NULL, NULL, 0, 0},
{D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 0, 0, pshader_break, NULL, NULL, 0, 0},
{D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 0, 2, pshader_breakc, NULL, NULL, 0, 0},
{D3DSIO_REP , "rep", NULL, 0, 1, pshader_rep, NULL, shader_glsl_rep, D3DPS_VERSION(2,1), -1},
{D3DSIO_ENDREP, "endrep", NULL, 0, 0, pshader_endrep, NULL, shader_glsl_end, D3DPS_VERSION(2,1), -1},
{D3DSIO_IF, "if", NULL, 0, 1, pshader_if, NULL, shader_glsl_if, D3DPS_VERSION(2,1), -1},
{D3DSIO_IFC, "ifc", NULL, 0, 2, pshader_ifc, NULL, shader_glsl_ifc, D3DPS_VERSION(2,1), -1},
{D3DSIO_ELSE, "else", NULL, 0, 0, pshader_else, NULL, shader_glsl_else, D3DPS_VERSION(2,1), -1},
{D3DSIO_ENDIF, "endif", NULL, 0, 0, pshader_endif, NULL, shader_glsl_end, D3DPS_VERSION(2,1), -1},
{D3DSIO_BREAK, "break", NULL, 0, 0, pshader_break, NULL, shader_glsl_break, D3DPS_VERSION(2,1), -1},
{D3DSIO_BREAKC, "breakc", NULL, 0, 2, pshader_breakc, NULL, shader_glsl_breakc, D3DPS_VERSION(2,1), -1},
{D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 0, 1, pshader_breakp, NULL, NULL, 0, 0},
{D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 0, 1, pshader_call, NULL, NULL, 0, 0},
{D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 0, 2, pshader_callnz, NULL, NULL, 0, 0},
{D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 0, 2, pshader_loop, NULL, shader_glsl_loop, 0, 0},
{D3DSIO_LOOP, "loop", NULL, 0, 2, pshader_loop, NULL, shader_glsl_loop, D3DPS_VERSION(3,0), -1},
{D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, 0, pshader_ret, NULL, NULL, 0, 0},
{D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, 0, pshader_endloop, NULL, shader_glsl_endloop, 0, 0},
{D3DSIO_ENDLOOP, "endloop", NULL, 0, 0, pshader_endloop, NULL, shader_glsl_end, D3DPS_VERSION(3,0), -1},
{D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 0, 1, pshader_label, NULL, NULL, 0, 0},
/* Constant definitions */

View file

@ -536,20 +536,20 @@ CONST SHADER_OPCODE IWineD3DVertexShaderImpl_shader_ins[] = {
{D3DSIO_DEFI, "defi", GLNAME_REQUIRE_GLSL, 1, 5, vshader_defi, NULL, NULL, 0, 0},
/* Flow control - requires GLSL or software shaders */
{D3DSIO_REP , "rep", GLNAME_REQUIRE_GLSL, 0, 1, vshader_rep, NULL, NULL, 0, 0},
{D3DSIO_ENDREP, "endrep", GLNAME_REQUIRE_GLSL, 0, 0, vshader_endrep, NULL, NULL, 0, 0},
{D3DSIO_IF, "if", GLNAME_REQUIRE_GLSL, 0, 1, vshader_if, NULL, NULL, 0, 0},
{D3DSIO_IFC, "ifc", GLNAME_REQUIRE_GLSL, 0, 2, vshader_ifc, NULL, NULL, 0, 0},
{D3DSIO_ELSE, "else", GLNAME_REQUIRE_GLSL, 0, 0, vshader_else, NULL, NULL, 0, 0},
{D3DSIO_ENDIF, "endif", GLNAME_REQUIRE_GLSL, 0, 0, vshader_endif, NULL, NULL, 0, 0},
{D3DSIO_BREAK, "break", GLNAME_REQUIRE_GLSL, 0, 0, vshader_break, NULL, NULL, 0, 0},
{D3DSIO_BREAKC, "breakc", GLNAME_REQUIRE_GLSL, 0, 2, vshader_breakc, NULL, NULL, 0, 0},
{D3DSIO_REP , "rep", NULL, 0, 1, vshader_rep, NULL, shader_glsl_rep, D3DVS_VERSION(2,0), -1},
{D3DSIO_ENDREP, "endrep", NULL, 0, 0, vshader_endrep, NULL, shader_glsl_end, D3DVS_VERSION(2,0), -1},
{D3DSIO_IF, "if", NULL, 0, 1, vshader_if, NULL, shader_glsl_if, D3DVS_VERSION(2,0), -1},
{D3DSIO_IFC, "ifc", NULL, 0, 2, vshader_ifc, NULL, shader_glsl_ifc, D3DVS_VERSION(2,1), -1},
{D3DSIO_ELSE, "else", NULL, 0, 0, vshader_else, NULL, shader_glsl_else, D3DVS_VERSION(2,0), -1},
{D3DSIO_ENDIF, "endif", NULL, 0, 0, vshader_endif, NULL, shader_glsl_end, D3DVS_VERSION(2,0), -1},
{D3DSIO_BREAK, "break", NULL, 0, 0, vshader_break, NULL, shader_glsl_break, D3DVS_VERSION(2,1), -1},
{D3DSIO_BREAKC, "breakc", NULL, 0, 2, vshader_breakc, NULL, shader_glsl_breakc, D3DVS_VERSION(2,1), -1},
{D3DSIO_BREAKP, "breakp", GLNAME_REQUIRE_GLSL, 0, 1, vshader_breakp, NULL, NULL, 0, 0},
{D3DSIO_CALL, "call", GLNAME_REQUIRE_GLSL, 0, 1, vshader_call, NULL, NULL, 0, 0},
{D3DSIO_CALLNZ, "callnz", GLNAME_REQUIRE_GLSL, 0, 2, vshader_callnz, NULL, NULL, 0, 0},
{D3DSIO_LOOP, "loop", GLNAME_REQUIRE_GLSL, 0, 2, vshader_loop, NULL, shader_glsl_loop, 0, 0},
{D3DSIO_LOOP, "loop", NULL, 0, 2, vshader_loop, NULL, shader_glsl_loop, D3DVS_VERSION(2,0), -1},
{D3DSIO_RET, "ret", GLNAME_REQUIRE_GLSL, 0, 0, vshader_ret, NULL, NULL, 0, 0},
{D3DSIO_ENDLOOP, "endloop", GLNAME_REQUIRE_GLSL, 0, 0, vshader_endloop, NULL, shader_glsl_endloop, 0, 0},
{D3DSIO_ENDLOOP, "endloop", NULL, 0, 0, vshader_endloop, NULL, shader_glsl_end, D3DVS_VERSION(2,0), -1},
{D3DSIO_LABEL, "label", GLNAME_REQUIRE_GLSL, 0, 1, vshader_label, NULL, NULL, 0, 0},
{D3DSIO_MOVA, "mova", GLNAME_REQUIRE_GLSL, 1, 2, vshader_mova, NULL, shader_glsl_mov, 0, 0},

View file

@ -1318,6 +1318,19 @@ typedef struct SHADER_BUFFER {
unsigned int lineNo;
} SHADER_BUFFER;
/* Undocumented opcode controls */
#define INST_CONTROLS_SHIFT 16
#define INST_CONTROLS_MASK 0x00ff0000
typedef enum COMPARISON_TYPE {
COMPARISON_GT = 1,
COMPARISON_EQ = 2,
COMPARISON_GE = 3,
COMPARISON_LT = 4,
COMPARISON_NE = 5,
COMPARISON_LE = 6
} COMPARISON_TYPE;
typedef struct SHADER_OPCODE {
unsigned int opcode;
const char* name;
@ -1335,6 +1348,7 @@ typedef struct SHADER_OPCODE_ARG {
IWineD3DBaseShader* shader;
shader_reg_maps* reg_maps;
CONST SHADER_OPCODE* opcode;
DWORD opcode_token;
DWORD dst;
DWORD dst_addr;
DWORD predicate;
@ -1442,7 +1456,13 @@ extern void shader_glsl_lit(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_dst(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_sincos(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_loop(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_endloop(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_end(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_if(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_ifc(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_else(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_break(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_breakc(SHADER_OPCODE_ARG* arg);
extern void shader_glsl_rep(SHADER_OPCODE_ARG* arg);
/** GLSL Pixel Shader Prototypes */
extern void pshader_glsl_tex(SHADER_OPCODE_ARG* arg);