Stefan Doesinger : wined3d: Implement IFC in ARB.

Alexandre Julliard julliard at winehq.org
Tue Jun 16 09:09:38 CDT 2009


Module: wine
Branch: master
Commit: e608ef856eed8031fcb594ee3e027b19fe1f2614
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e608ef856eed8031fcb594ee3e027b19fe1f2614

Author: Stefan Doesinger <stefan at codeweavers.com>
Date:   Wed Jun  3 14:11:58 2009 +0200

wined3d: Implement IFC in ARB.

---

 dlls/wined3d/arb_program_shader.c |  119 +++++++++++++++++++++++++++++++++----
 1 files changed, 107 insertions(+), 12 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 0800540..1994ce2 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -86,8 +86,13 @@ struct control_frame
     } type;
     BOOL                            muting;
     BOOL                            outer_loop;
-    unsigned int                    loop_no;
+    union
+    {
+        unsigned int                loop_no;
+        unsigned int                ifc_no;
+    };
     DWORD                           loop_control[3];
+    BOOL                            had_else;
 };
 
 struct arb_ps_compile_args
@@ -157,7 +162,7 @@ struct shader_arb_ctx_priv
     struct list                         record;
     BOOL                                recording;
     BOOL                                muted;
-    unsigned int                        num_loops, loop_depth;
+    unsigned int                        num_loops, loop_depth, num_ifcs;
     int                                 aL;
 };
 
@@ -2273,6 +2278,92 @@ static void shader_hw_breakc(const struct wined3d_shader_instruction *ins)
     }
 }
 
+static void shader_hw_ifc(const struct wined3d_shader_instruction *ins)
+{
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    struct list *e = list_head(&priv->control_frames);
+    struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
+    const char *comp;
+    char src_name0[50];
+    char src_name1[50];
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    /* Invert the flag. We jump to the else label if the condition is NOT true */
+    switch(ins->flags)
+    {
+        case COMPARISON_GT: comp = "LE"; break;
+        case COMPARISON_EQ: comp = "NE"; break;
+        case COMPARISON_GE: comp = "LT"; break;
+        case COMPARISON_LT: comp = "GE"; break;
+        case COMPARISON_NE: comp = "EQ"; break;
+        case COMPARISON_LE: comp = "GT"; break;
+        default:
+            FIXME("Unrecognized comparison value: %u\n", ins->flags);
+            comp = "\?\?";
+    }
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1);
+
+    if(vshader)
+    {
+        shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1);
+        shader_addline(buffer, "BRA ifc_%u_endif (%s.x);\n", control_frame->ifc_no, comp);
+    }
+    else
+    {
+        shader_addline(buffer, "SUBC CC, %s, %s;\n", src_name0, src_name1);
+        shader_addline(buffer, "IF %s.x;\n", comp);
+    }
+}
+
+static void shader_hw_else(const struct wined3d_shader_instruction *ins)
+{
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    struct list *e = list_head(&priv->control_frames);
+    struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    if(vshader)
+    {
+        shader_addline(buffer, "BRA ifc_%u_endif;\n", control_frame->ifc_no);
+        shader_addline(buffer, "ifc_%u_else:\n", control_frame->ifc_no);
+        control_frame->had_else = TRUE;
+    }
+    else
+    {
+        shader_addline(buffer, "ELSE;\n");
+    }
+}
+
+static void shader_hw_endif(const struct wined3d_shader_instruction *ins)
+{
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    struct shader_arb_ctx_priv *priv = ins->ctx->backend_data;
+    struct list *e = list_head(&priv->control_frames);
+    struct control_frame *control_frame = LIST_ENTRY(e, struct control_frame, entry);
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    if(vshader)
+    {
+        if(control_frame->had_else)
+        {
+            shader_addline(buffer, "ifc_%u_endif:\n", control_frame->ifc_no);
+        }
+        else
+        {
+            shader_addline(buffer, "#No else branch. else is endif\n");
+            shader_addline(buffer, "ifc_%u_else:\n", control_frame->ifc_no);
+        }
+    }
+    else
+    {
+        shader_addline(buffer, "ENDIF;\n");
+    }
+}
+
 static GLuint create_arb_blt_vertex_program(const WineD3D_GL_Info *gl_info)
 {
     GLuint program_id = 0;
@@ -3317,15 +3408,15 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL
     /* WINED3DSIH_DST           */ shader_hw_map2gl,
     /* WINED3DSIH_DSX           */ shader_hw_map2gl,
     /* WINED3DSIH_DSY           */ shader_hw_dsy,
-    /* WINED3DSIH_ELSE          */ NULL,
-    /* WINED3DSIH_ENDIF         */ NULL,
+    /* WINED3DSIH_ELSE          */ shader_hw_else,
+    /* WINED3DSIH_ENDIF         */ shader_hw_endif,
     /* WINED3DSIH_ENDLOOP       */ shader_hw_endloop,
     /* WINED3DSIH_ENDREP        */ shader_hw_endrep,
     /* WINED3DSIH_EXP           */ shader_hw_map2gl,
     /* WINED3DSIH_EXPP          */ shader_hw_map2gl,
     /* WINED3DSIH_FRC           */ shader_hw_map2gl,
-    /* WINED3DSIH_IF            */ NULL,
-    /* WINED3DSIH_IFC           */ NULL,
+    /* WINED3DSIH_IF            */ NULL /* Hardcoded into the shader */,
+    /* WINED3DSIH_IFC           */ shader_hw_ifc,
     /* WINED3DSIH_LABEL         */ NULL,
     /* WINED3DSIH_LIT           */ shader_hw_map2gl,
     /* WINED3DSIH_LOG           */ shader_hw_map2gl,
@@ -3693,6 +3784,7 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
         /* IF(bool) and if_cond(a, b) use the same ELSE and ENDIF tokens */
         control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
         control_frame->type = IFC;
+        control_frame->ifc_no = priv->num_ifcs++;
         list_add_head(&priv->control_frames, &control_frame->entry);
     }
     else if(ins->handler_idx == WINED3DSIH_ELSE)
@@ -3726,12 +3818,6 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
             HeapFree(GetProcessHeap(), 0, control_frame);
             return; /* Instruction is handled */
         }
-        else
-        {
-            list_remove(&control_frame->entry);
-            HeapFree(GetProcessHeap(), 0, control_frame);
-            /* ifc - generate a hw endif */
-        }
     }
 
     if(priv->muted) return;
@@ -3755,6 +3841,15 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
         HeapFree(GetProcessHeap(), 0, control_frame);
         priv->loop_depth--;
     }
+    else if(ins->handler_idx == WINED3DSIH_ENDIF)
+    {
+        /* Non-ifc ENDIFs don't reach that place because of the return in the if block above */
+        struct list *e = list_head(&priv->control_frames);
+        control_frame = LIST_ENTRY(e, struct control_frame, entry);
+        list_remove(&control_frame->entry);
+        HeapFree(GetProcessHeap(), 0, control_frame);
+    }
+
 
     shader_arb_add_instruction_modifiers(ins);
 }




More information about the wine-cvs mailing list