[WINED3D 3/3] Take predication tokens into account

Ivan Gyurdiev ivg2 at cornell.edu
Wed May 17 20:09:56 CDT 2006


Each instruction can have a predication token. Account for it in the 
trace pass, register count pass, and store it in the SHADER_OPCODE_ARG 
structure for generation. MSDN claims the token is at the end of the 
instruction, but that's not true - testing a demo, which lets me 
manipulate the shader shows the predication token is the first source 
token immediately following the destination token.

Also add trace support for NOT source modifier, which is frequently used 
with predicate registers.

Here is an example:
-------------------

This is an example asm line I tested, which combines previously added
source and destination relative addressing with predication - in a 3.0 
shader:

setp_le p0, r0, r1
(!p0) mad o2[aL + 10], c[a0.x + 1], c[a0.y + 5], c[a0.z + 15]

This is what the trace prints out with this patch. The setp (_le) suffix 
is not accounted for. I'm not sure how to extract that. Bits 16-23 in 
the instruction code are reserved for "specific controls", maybe that's 
how it's done.

trace:d3d_shader:IWineD3DVertexShaderImpl_SetFunction setp p0, r0, r1
trace:d3d_shader:IWineD3DVertexShaderImpl_SetFunction (!p0) mad o[aL.z + 
12], c[a0.x + 1], c[a0.y + 5], c[a0.z + 15]

This is what it compiles to, which is obviously wrong (but I haven't 
fixed that part yet, 2.0/3.0 shaders are best handled in glsl):

fixme:d3d_shader:generate_base_shader Token setp requires greater 
functionality than Vertex or Fragment_Program_ARB supports
trace:d3d_shader:shader_addline GL HW (6, 144) : MAD 
result.texcoord[12], C[A0.x + 1], C[A0.x + 5], C[A0.x + 15];

-------------- next part --------------
---

 dlls/wined3d/baseshader.c      |   28 ++++++++++++++++++++++------
 dlls/wined3d/pixelshader.c     |   18 +++++++++++++++++-
 dlls/wined3d/vertexshader.c    |   16 ++++++++++++++++
 dlls/wined3d/wined3d_private.h |    1 +
 4 files changed, 56 insertions(+), 7 deletions(-)

111bdaa551726f1e7d757fc89144117698787c9e
diff --git a/dlls/wined3d/baseshader.c b/dlls/wined3d/baseshader.c
index a9e847a..f9f939f 100644
--- a/dlls/wined3d/baseshader.c
+++ b/dlls/wined3d/baseshader.c
@@ -176,6 +176,7 @@ void shader_get_registers_used(
 
     while (D3DVS_END() != *pToken) {
         CONST SHADER_OPCODE* curOpcode;
+        DWORD opcode_token;
 
         /* Skip version */
         if (shader_is_version_token(*pToken)) {
@@ -191,8 +192,8 @@ void shader_get_registers_used(
         }
 
         /* Fetch opcode */
-        curOpcode = shader_get_opcode(iface, *pToken);
-        ++pToken;
+        opcode_token = *pToken++;
+        curOpcode = shader_get_opcode(iface, opcode_token);
 
         /* Unhandled opcode, and its parameters */
         if (NULL == curOpcode) {
@@ -212,9 +213,19 @@ void shader_get_registers_used(
 
         /* Set texture registers, and temporary registers */
         } else {
-            int i;
+            int i, limit;
 
-            for (i = 0; i < curOpcode->num_params; ++i) {
+            /* This will loop over all the registers and try to
+             * make a bitmask of the ones we're interested in. 
+             *
+             * Relative addressing tokens are ignored, but that's 
+             * okay, since we'll catch any address registers when 
+             * they are initialized (required by spec) */
+
+            limit = (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED)?
+                curOpcode->num_params + 1: curOpcode->num_params;
+
+            for (i = 0; i < limit; ++i) {
 
                 DWORD param, addr_token, reg, regtype;
                 pToken += shader_get_param(iface, pToken, &param, &addr_token);
@@ -359,6 +370,8 @@ void shader_dump_param(
             TRACE("-");
         else if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_COMP)
             TRACE("1-");
+        else if ((param & D3DSP_SRCMOD_MASK) == D3DSPSM_NOT)
+            TRACE("!");
     }
 
     switch (regtype) {
@@ -445,10 +458,10 @@ void shader_dump_param(
 
         if (0 != (param & D3DSP_SRCMOD_MASK)) {
             DWORD mask = param & D3DSP_SRCMOD_MASK;
-            /*TRACE("_modifier(0x%08lx) ", mask);*/
             switch (mask) {
                 case D3DSPSM_NONE:    break;
                 case D3DSPSM_NEG:     break;
+                case D3DSPSM_NOT:     break;
                 case D3DSPSM_BIAS:    TRACE("_bias"); break;
                 case D3DSPSM_BIASNEG: TRACE("_bias"); break;
                 case D3DSPSM_SIGN:    TRACE("_bx2"); break;
@@ -459,7 +472,7 @@ void shader_dump_param(
                 case D3DSPSM_DZ:      TRACE("_dz"); break;
                 case D3DSPSM_DW:      TRACE("_dw"); break;
                 default:
-                    TRACE("_unknown(0x%08lx)", mask);
+                    TRACE("_unknown_modifier(%#lx)", mask >> D3DSP_SRCMOD_SHIFT);
             }
         }
 
@@ -619,6 +632,9 @@ void generate_base_shader(
                     hw_arg.dst = param;
                     hw_arg.dst_addr = addr_token;
 
+                    if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) 
+                        hw_arg.predicate = *pToken++;
+
                     for (i = 1; i < curOpcode->num_params; i++) {
                         /* DEF* instructions have constant src parameters, not registers */
                         if (curOpcode->opcode == D3DSIO_DEF || 
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 918de80..bafcd28 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -1458,9 +1458,18 @@ HRESULT WINAPI IWineD3DPixelShaderImpl_S
                     DWORD param, addr_token;
                     int tokens_read;
 
+                    /* Print out predication source token first - it follows
+                     * the destination token. */
+                    if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
+                        TRACE("(");
+                        shader_dump_param((IWineD3DBaseShader*) This, *(pToken + 2), 0, 1);
+                        TRACE(") ");
+                    }
+
                     TRACE("%s", curOpcode->name);
                     if (curOpcode->num_params > 0) {
 
+                        /* Destination token */
                         tokens_read = shader_get_param((IWineD3DBaseShader*) This,
                             pToken, &param, &addr_token);                       
                         pToken += tokens_read;
@@ -1469,7 +1478,14 @@ HRESULT WINAPI IWineD3DPixelShaderImpl_S
                         shader_dump_ins_modifiers(param);
                         TRACE(" ");
                         shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
-                         
+
+                        /* Predication token - already printed out, just skip it */
+                        if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
+                            pToken++;
+                            len++;
+                        }
+
+                        /* Other source tokens */
                         for (i = 1; i < curOpcode->num_params; ++i) {
 
                             tokens_read = shader_get_param((IWineD3DBaseShader*) This,
diff --git a/dlls/wined3d/vertexshader.c b/dlls/wined3d/vertexshader.c
index 6dfbd11..58a1963 100644
--- a/dlls/wined3d/vertexshader.c
+++ b/dlls/wined3d/vertexshader.c
@@ -1576,9 +1576,18 @@ HRESULT WINAPI IWineD3DVertexShaderImpl_
                     DWORD param, addr_token;
                     int tokens_read;
 
+                    /* Print out predication source token first - it follows
+                     * the destination token. */
+                    if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
+                        TRACE("(");
+                        shader_dump_param((IWineD3DBaseShader*) This, *(pToken + 2), 0, 1);
+                        TRACE(") ");
+                    }
+
                     TRACE("%s", curOpcode->name);
                     if (curOpcode->num_params > 0) {
 
+                        /* Destination token */
                         tokens_read = shader_get_param((IWineD3DBaseShader*) This,
                             pToken, &param, &addr_token);
                         pToken += tokens_read;
@@ -1588,6 +1597,13 @@ HRESULT WINAPI IWineD3DVertexShaderImpl_
                         TRACE(" ");
                         shader_dump_param((IWineD3DBaseShader*) This, param, addr_token, 0);
 
+                        /* Predication token - already printed out, just skip it */
+                        if (opcode_token & D3DSHADER_INSTRUCTION_PREDICATED) {
+                            pToken++;
+                            len++;
+                        }
+
+                        /* Other source tokens */
                         for (i = 1; i < curOpcode->num_params; ++i) {
 
                             tokens_read = shader_get_param((IWineD3DBaseShader*) This,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 7a61921..6b90544 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1296,6 +1296,7 @@ typedef struct SHADER_OPCODE_ARG {
     CONST SHADER_OPCODE* opcode;
     DWORD dst;
     DWORD dst_addr;
+    DWORD predicate;
     DWORD src[4];
     DWORD src_addr[4];
     SHADER_BUFFER* buffer;
-- 
1.3.1



More information about the wine-patches mailing list