[WINED3D 4] More flow control instructions
Ivan Gyurdiev
ivg231 at gmail.com
Mon Jul 10 04:11:35 CDT 2006
- 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.
Note that loops will not work on pixel shaders at the moment - will
return a GLSL error.
That's either a hardware or a GLSL limitation. Loops seem to work
properly on vertex shaders.
-------------- next part --------------
---
dlls/wined3d/baseshader.c | 39 ++++++++++++-----
dlls/wined3d/glsl_shader.c | 91 +++++++++++++++++++++++++++++++++++-----
dlls/wined3d/pixelshader.c | 20 ++++-----
dlls/wined3d/vertexshader.c | 20 ++++-----
dlls/wined3d/wined3d_private.h | 22 +++++++++-
5 files changed, 147 insertions(+), 45 deletions(-)
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index 5baca25..1275dd5 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -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) {
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 0d0ed3a..bd91f10 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -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_modifie
}
}
+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_AR
*/
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
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 40d7a40..977cb4e 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -676,20 +676,20 @@ CONST SHADER_OPCODE IWineD3DPixelShaderI
{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 */
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index d71b5c5..20d1d40 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -536,20 +536,20 @@ CONST SHADER_OPCODE IWineD3DVertexShader
{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},
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 0fc8b3f..5102e7c 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -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_OPCOD
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);
--
1.4.0
More information about the wine-patches
mailing list