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:
parent
345dd49eda
commit
6ede56495a
|
@ -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, ¶m, &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) {
|
||||
|
||||
|
|
|
@ -756,8 +756,9 @@ 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;
|
||||
|
||||
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 src1_str[100];
|
||||
char src1_reg[50];
|
||||
char src1_mask[6];
|
||||
|
||||
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",
|
||||
src1_reg, src1_reg, src1_reg);
|
||||
}
|
||||
|
||||
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, aL = %s.y; tmpInt < %s.x; tmpInt++, aL += %s.z) {\n",
|
||||
src0_reg, src0_reg, src0_reg);
|
||||
shader_addline(arg->buffer, "for (tmpInt = 0; tmpInt < %s.x; tmpInt++) {\n", src0_reg);
|
||||
}
|
||||
|
||||
/** Process the D3DSIO_ENDLOOP instruction in GLSL:
|
||||
* End the for() loop
|
||||
*/
|
||||
void shader_glsl_endloop(SHADER_OPCODE_ARG* arg) {
|
||||
void shader_glsl_if(SHADER_OPCODE_ARG* arg) {
|
||||
|
||||
shader_addline(arg->buffer, "}\n");
|
||||
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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue