[WINED3D 5] More flow control instructions 2

Ivan Gyurdiev ivg231 at gmail.com
Mon Jul 10 05:35:15 CDT 2006


Ivan Gyurdiev wrote:
> - 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.
Ok, let's try this one again. I set the limit on 3.0 shaders to 2048, 
and now it's prototyping 2048 of them (interesting it doesn't crash).

-------------- 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 = 16; /* FIXME: 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 = 16; /* FIXME: 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