[WINED3D 5] More flow control instructions 2

Ivan Gyurdiev ivg231 at gmail.com
Mon Jul 10 05:24:59 CDT 2006


- Implement call, callnz, label, and ret
- Implement support for NOT modifier

The subroutines are tracked in the register counting pass, and 
prototyped ahead of time. Note that for now we'll only support 16 of 
them (sm 2.0 limit). Shader model 3 allows up to 2048 subroutines, but 
I'd rather not keep track of that many yet - maybe when more things are 
made dynamic on the heap. We'll need to think about some of those issues 
for software shader constant support as well.

-------------- next part --------------
---
 dlls/wined3d/baseshader.c      |   12 ++++++++++--
 dlls/wined3d/glsl_shader.c     |   32 ++++++++++++++++++++++++++++++++
 dlls/wined3d/pixelshader.c     |   22 ++++++++++++++++++----
 dlls/wined3d/vertexshader.c    |   12 ++++++++----
 dlls/wined3d/wined3d_private.h |    9 +++++++++
 5 files changed, 77 insertions(+), 10 deletions(-)

diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index 1275dd5..b3823c2 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -277,7 +277,14 @@ HRESULT shader_get_registers_used(
                    D3DSIO_REP == curOpcode->opcode) {
             reg_maps->loop = 1;
             pToken += curOpcode->num_params;
-        
+   
+        /* For subroutine prototypes */
+        } else if (D3DSIO_LABEL == curOpcode->opcode) {
+
+            DWORD snum = *pToken & D3DSP_REGNUM_MASK; 
+            reg_maps->labels[snum] = 1;
+            pToken += curOpcode->num_params;
+ 
         /* Set texture, address, temporary registers */
         } else {
             int i, limit;
@@ -683,7 +690,8 @@ void shader_generate_main(
                        D3DSIO_NOP == curOpcode->opcode ||
                        D3DSIO_DEF == curOpcode->opcode ||
                        D3DSIO_DEFI == curOpcode->opcode ||
-                       D3DSIO_DEFB == curOpcode->opcode) {
+                       D3DSIO_DEFB == curOpcode->opcode ||
+                       D3DSIO_RET == curOpcode->opcode) {
 
                 pToken += shader_skip_opcode(This, curOpcode, hw_arg.opcode_token);
 
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index bd91f10..223a8e0 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -331,6 +331,12 @@ void shader_generate_glsl_declarations(
     char pshader = shader_is_pshader_version(This->baseShader.hex_version);
     char prefix = pshader ? 'P' : 'V';
 
+    /* Prototype the subroutines */
+    for (i = 0; i < This->baseShader.limits.label; i++) {
+        if (reg_maps->labels[i])
+            shader_addline(buffer, "void subroutine%lu();\n", i);
+    }
+
     /* Declare the constants (aka uniforms) */
     if (This->baseShader.limits.constant_float > 0)
         shader_addline(buffer, "uniform vec4 %cC[%u];\n", prefix, This->baseShader.limits.constant_float);
@@ -495,6 +501,9 @@ static void shader_glsl_gen_modifier (
     case D3DSPSM_NEG:
         sprintf(out_str, "-%s%s", in_reg, in_regswizzle);
         break;
+    case D3DSPSM_NOT:
+        sprintf(out_str, "!%s%s", in_reg, in_regswizzle);
+        break;
     case D3DSPSM_BIAS:
         sprintf(out_str, "(%s%s - vec4(0.5)%s)", in_reg, in_regswizzle, in_regswizzle);
         break;
@@ -1238,6 +1247,29 @@ void shader_glsl_breakc(SHADER_OPCODE_AR
         src0_str, shader_get_comp_op(arg->opcode_token), src1_str);
 }
 
+void shader_glsl_label(SHADER_OPCODE_ARG* arg) {
+
+    DWORD snum = (arg->src[0]) & D3DSP_REGNUM_MASK;
+    shader_addline(arg->buffer, "}\n");
+    shader_addline(arg->buffer, "void subroutine%lu () {\n",  snum);
+}
+
+void shader_glsl_call(SHADER_OPCODE_ARG* arg) {
+    DWORD snum = (arg->src[0]) & D3DSP_REGNUM_MASK;
+    shader_addline(arg->buffer, "subroutine%lu();\n", snum);
+}
+
+void shader_glsl_callnz(SHADER_OPCODE_ARG* arg) {
+
+    char src1_str[100];
+    char src1_reg[50];
+    char src1_mask[6];
+   
+    DWORD snum = (arg->src[0]) & D3DSP_REGNUM_MASK;
+    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) subroutine%lu();\n", src1_str, snum);
+}
+
 /*********************************************
  * Pixel Shader Specific Code begins here
  ********************************************/
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 977cb4e..0c84414 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -685,12 +685,12 @@ CONST SHADER_OPCODE IWineD3DPixelShaderI
     {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_CALL,     "call",     NULL, 0, 1, pshader_call,    NULL, shader_glsl_call, D3DPS_VERSION(2,1), -1},
+    {D3DSIO_CALLNZ,   "callnz",   NULL, 0, 2, pshader_callnz,  NULL, shader_glsl_callnz, D3DPS_VERSION(2,1), -1},
     {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_RET,      "ret",      NULL, 0, 0, pshader_ret,     NULL, NULL,               D3DPS_VERSION(2,1), -1},
     {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},
+    {D3DSIO_LABEL,    "label",    NULL, 0, 1, pshader_label,   NULL, shader_glsl_label,  D3DPS_VERSION(2,1), -1},
 
     /* Constant definitions */
     {D3DSIO_DEF,      "def",      "undefined",         1, 5, pshader_def,     NULL, NULL, 0, 0},
@@ -751,6 +751,7 @@ static void pshader_set_limits(
                    This->baseShader.limits.texcoord = 4;
                    This->baseShader.limits.sampler = 4;
                    This->baseShader.limits.packed_input = 0;
+                   This->baseShader.limits.label = 0;
                    break;
 
           case D3DPS_VERSION(1,4):
@@ -761,10 +762,20 @@ static void pshader_set_limits(
                    This->baseShader.limits.texcoord = 6;
                    This->baseShader.limits.sampler = 6;
                    This->baseShader.limits.packed_input = 0;
+                   This->baseShader.limits.label = 0;
                    break;
                
           /* FIXME: temporaries must match D3DPSHADERCAPS2_0.NumTemps */ 
           case D3DPS_VERSION(2,0):
+                   This->baseShader.limits.temporary = 32;
+                   This->baseShader.limits.constant_float = 32;
+                   This->baseShader.limits.constant_int = 16;
+                   This->baseShader.limits.constant_bool = 16;
+                   This->baseShader.limits.texcoord = 8;
+                   This->baseShader.limits.sampler = 16;
+                   This->baseShader.limits.packed_input = 0;
+                   break;
+
           case D3DPS_VERSION(2,1):
                    This->baseShader.limits.temporary = 32;
                    This->baseShader.limits.constant_float = 32;
@@ -773,6 +784,7 @@ static void pshader_set_limits(
                    This->baseShader.limits.texcoord = 8;
                    This->baseShader.limits.sampler = 16;
                    This->baseShader.limits.packed_input = 0;
+                   This->baseShader.limits.label = 16;
                    break;
 
           case D3DPS_VERSION(3,0):
@@ -783,6 +795,7 @@ static void pshader_set_limits(
                    This->baseShader.limits.texcoord = 0;
                    This->baseShader.limits.sampler = 16;
                    This->baseShader.limits.packed_input = 12;
+                   This->baseShader.limits.label = 2048;
                    break;
 
           default: This->baseShader.limits.temporary = 32;
@@ -792,6 +805,7 @@ static void pshader_set_limits(
                    This->baseShader.limits.texcoord = 8;
                    This->baseShader.limits.sampler = 16;
                    This->baseShader.limits.packed_input = 0;
+                   This->baseShader.limits.label = 0;
                    FIXME("Unrecognized pixel shader version %#lx\n", 
                        This->baseShader.hex_version);
       }
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 20d1d40..53f4a23 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -545,12 +545,12 @@ CONST SHADER_OPCODE IWineD3DVertexShader
     {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_CALL,     "call",     NULL, 0, 1, vshader_call,    NULL, shader_glsl_call,   D3DVS_VERSION(2,0), -1},
+    {D3DSIO_CALLNZ,   "callnz",   NULL, 0, 2, vshader_callnz,  NULL, shader_glsl_callnz, D3DVS_VERSION(2,0), -1},
     {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_RET,      "ret",      NULL, 0, 0, vshader_ret,     NULL, NULL,               D3DVS_VERSION(2,0), -1},
     {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_LABEL,    "label",    NULL, 0, 1, vshader_label,   NULL, shader_glsl_label,  D3DVS_VERSION(2,0), -1},
 
     {D3DSIO_MOVA,     "mova",     GLNAME_REQUIRE_GLSL, 1, 2, vshader_mova,    NULL, shader_glsl_mov, 0, 0},
     {D3DSIO_SETP,     "setp",     GLNAME_REQUIRE_GLSL, 1, 3, vshader_setp,    NULL, NULL, 0, 0},
@@ -577,6 +577,7 @@ static void vshader_set_limits(
                    This->baseShader.limits.address = 1;
                    This->baseShader.limits.packed_output = 0;
                    This->baseShader.limits.sampler = 0;
+                   This->baseShader.limits.label = 0;
                    break;
       
           case D3DVS_VERSION(2,0):
@@ -587,6 +588,7 @@ static void vshader_set_limits(
                    This->baseShader.limits.address = 1;
                    This->baseShader.limits.packed_output = 0;
                    This->baseShader.limits.sampler = 0;
+                   This->baseShader.limits.label = 16;
                    break;
 
           case D3DVS_VERSION(3,0):
@@ -596,6 +598,7 @@ static void vshader_set_limits(
                    This->baseShader.limits.address = 1;
                    This->baseShader.limits.packed_output = 12;
                    This->baseShader.limits.sampler = 4;
+                   This->baseShader.limits.label = 2048;
                    break;
 
           default: This->baseShader.limits.temporary = 12;
@@ -604,6 +607,7 @@ static void vshader_set_limits(
                    This->baseShader.limits.address = 1;
                    This->baseShader.limits.packed_output = 0;
                    This->baseShader.limits.sampler = 0;
+                   This->baseShader.limits.label = 16;
                    FIXME("Unrecognized vertex shader version %#lx\n",
                        This->baseShader.hex_version);
       }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 5102e7c..c1ce763 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1282,6 +1282,10 @@ #define MAX_ATTRIBS 16
 #define MAX_CONST_I 16
 #define MAX_CONST_B 16
 
+/* FIXME: This needs to go up to 2048 for
+ * Shader model 3 according to msdn (and for software shaders) */
+#define MAX_LABELS 16
+
 typedef struct semantic {
     DWORD usage;
     DWORD reg;
@@ -1301,6 +1305,7 @@ typedef struct shader_reg_maps {
     char packed_input[MAX_REG_INPUT];       /* pshader >= 3.0 */
     char packed_output[MAX_REG_OUTPUT];     /* vertex >= 3.0 */
     char attributes[MAX_ATTRIBS];           /* vertex */
+    char labels[MAX_LABELS];                /* pixel, vertex */
 
     /* Sampler usage tokens 
      * Use 0 as default (bit 31 is always 1 on a valid token) */
@@ -1368,6 +1373,7 @@ typedef struct SHADER_LIMITS {
     unsigned int packed_output;
     unsigned int packed_input;
     unsigned int attributes;
+    unsigned int label;
 } SHADER_LIMITS;
 
 /** Keeps track of details for TEX_M#x# shader opcodes which need to 
@@ -1463,6 +1469,9 @@ extern void shader_glsl_else(SHADER_OPCO
 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);
+extern void shader_glsl_call(SHADER_OPCODE_ARG* arg);
+extern void shader_glsl_callnz(SHADER_OPCODE_ARG* arg);
+extern void shader_glsl_label(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