[PATCH 5/5] wined3d: Move the ARB shader program constant handling to the backend where it belongs.

Henri Verbeet hverbeet at codeweavers.com
Tue Oct 25 14:20:29 CDT 2011


---
 dlls/wined3d/arb_program_shader.c |  106 ++++++++++++++++++++++++++++---------
 dlls/wined3d/context.c            |   38 +-------------
 dlls/wined3d/device.c             |    2 -
 dlls/wined3d/glsl_shader.c        |    8 +--
 dlls/wined3d/shader.c             |    4 +-
 dlls/wined3d/wined3d_private.h    |    8 +--
 6 files changed, 89 insertions(+), 77 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 3cd99be..e81a72e 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -312,6 +312,10 @@ struct shader_arb_priv
 
     struct wine_rb_tree     signature_tree;
     DWORD ps_sig_number;
+
+    unsigned int highest_dirty_ps_const, highest_dirty_vs_const;
+    char *vshader_const_dirty, *pshader_const_dirty;
+    const struct wined3d_context *last_context;
 };
 
 /* GL locking for state handlers is done by the caller. */
@@ -633,14 +637,27 @@ static void shader_arb_load_constants(const struct wined3d_context *context, cha
     const struct wined3d_gl_info *gl_info = context->gl_info;
     struct shader_arb_priv *priv = device->shader_priv;
 
+    if (context != priv->last_context)
+    {
+        memset(priv->vshader_const_dirty, 1,
+                sizeof(*priv->vshader_const_dirty) * device->d3d_vshader_constantF);
+        priv->highest_dirty_vs_const = device->d3d_vshader_constantF;
+
+        memset(priv->pshader_const_dirty, 1,
+                sizeof(*priv->pshader_const_dirty) * device->d3d_pshader_constantF);
+        priv->highest_dirty_ps_const = device->d3d_pshader_constantF;
+
+        priv->last_context = context;
+    }
+
     if (useVertexShader)
     {
         struct wined3d_shader *vshader = state->vertex_shader;
         const struct arb_vs_compiled_shader *gl_shader = priv->compiled_vprog;
 
         /* Load DirectX 9 float constants for vertex shader */
-        device->highest_dirty_vs_const = shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB,
-                device->highest_dirty_vs_const, state->vs_consts_f, context->vshader_const_dirty);
+        priv->highest_dirty_vs_const = shader_arb_load_constantsF(vshader, gl_info, GL_VERTEX_PROGRAM_ARB,
+                priv->highest_dirty_vs_const, state->vs_consts_f, priv->vshader_const_dirty);
         shader_arb_vs_local_constants(gl_shader, context, state);
     }
 
@@ -651,8 +668,8 @@ static void shader_arb_load_constants(const struct wined3d_context *context, cha
         UINT rt_height = state->fb->render_targets[0]->resource.height;
 
         /* Load DirectX 9 float constants for pixel shader */
-        device->highest_dirty_ps_const = shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB,
-                device->highest_dirty_ps_const, state->ps_consts_f, context->pshader_const_dirty);
+        priv->highest_dirty_ps_const = shader_arb_load_constantsF(pshader, gl_info, GL_FRAGMENT_PROGRAM_ARB,
+                priv->highest_dirty_ps_const, state->ps_consts_f, priv->pshader_const_dirty);
         shader_arb_ps_local_constants(gl_shader, context, state, rt_height);
     }
 }
@@ -660,25 +677,27 @@ static void shader_arb_load_constants(const struct wined3d_context *context, cha
 static void shader_arb_update_float_vertex_constants(struct wined3d_device *device, UINT start, UINT count)
 {
     struct wined3d_context *context = context_get_current();
+    struct shader_arb_priv *priv = device->shader_priv;
 
     /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
      * context. On a context switch the old context will be fully dirtified */
     if (!context || context->swapchain->device != device) return;
 
-    memset(context->vshader_const_dirty + start, 1, sizeof(*context->vshader_const_dirty) * count);
-    device->highest_dirty_vs_const = max(device->highest_dirty_vs_const, start + count);
+    memset(priv->vshader_const_dirty + start, 1, sizeof(*priv->vshader_const_dirty) * count);
+    priv->highest_dirty_vs_const = max(priv->highest_dirty_vs_const, start + count);
 }
 
 static void shader_arb_update_float_pixel_constants(struct wined3d_device *device, UINT start, UINT count)
 {
     struct wined3d_context *context = context_get_current();
+    struct shader_arb_priv *priv = device->shader_priv;
 
     /* We don't want shader constant dirtification to be an O(contexts), so just dirtify the active
      * context. On a context switch the old context will be fully dirtified */
     if (!context || context->swapchain->device != device) return;
 
-    memset(context->pshader_const_dirty + start, 1, sizeof(*context->pshader_const_dirty) * count);
-    device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, start + count);
+    memset(priv->pshader_const_dirty + start, 1, sizeof(*priv->pshader_const_dirty) * count);
+    priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, start + count);
 }
 
 static DWORD *local_const_mapping(const struct wined3d_shader *shader)
@@ -4602,10 +4621,10 @@ static void shader_arb_select(const struct wined3d_context *context, BOOL usePS,
         if (priv->last_ps_const_clamped != ((struct arb_pshader_private *)ps->backend_data)->clamp_consts)
         {
             priv->last_ps_const_clamped = ((struct arb_pshader_private *)ps->backend_data)->clamp_consts;
-            device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, 8);
+            priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, 8);
             for(i = 0; i < 8; i++)
             {
-                context->pshader_const_dirty[i] = 1;
+                priv->pshader_const_dirty[i] = 1;
             }
             /* Also takes care of loading local constants */
             shader_arb_load_constants(context, TRUE, FALSE);
@@ -4799,14 +4818,34 @@ static const struct wine_rb_functions sig_tree_functions =
 static HRESULT shader_arb_alloc(struct wined3d_device *device)
 {
     struct shader_arb_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*priv));
+
+    priv->vshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
+            sizeof(*priv->vshader_const_dirty) * device->d3d_vshader_constantF);
+    if (!priv->vshader_const_dirty)
+        goto fail;
+    memset(priv->vshader_const_dirty, 1,
+           sizeof(*priv->vshader_const_dirty) * device->d3d_vshader_constantF);
+
+    priv->pshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
+            sizeof(*priv->pshader_const_dirty) * device->d3d_pshader_constantF);
+    if (!priv->pshader_const_dirty)
+        goto fail;
+    memset(priv->pshader_const_dirty, 1,
+            sizeof(*priv->pshader_const_dirty) * device->d3d_pshader_constantF);
+
     if(wine_rb_init(&priv->signature_tree, &sig_tree_functions) == -1)
     {
         ERR("RB tree init failed\n");
-        HeapFree(GetProcessHeap(), 0, priv);
-        return E_OUTOFMEMORY;
+        goto fail;
     }
     device->shader_priv = priv;
     return WINED3D_OK;
+
+fail:
+    HeapFree(GetProcessHeap(), 0, priv->pshader_const_dirty);
+    HeapFree(GetProcessHeap(), 0, priv->vshader_const_dirty);
+    HeapFree(GetProcessHeap(), 0, priv);
+    return E_OUTOFMEMORY;
 }
 
 static void release_signature(struct wine_rb_entry *entry, void *context)
@@ -4846,12 +4885,17 @@ static void shader_arb_free(struct wined3d_device *device)
     LEAVE_GL();
 
     wine_rb_destroy(&priv->signature_tree, release_signature, NULL);
+    HeapFree(GetProcessHeap(), 0, priv->pshader_const_dirty);
+    HeapFree(GetProcessHeap(), 0, priv->vshader_const_dirty);
     HeapFree(GetProcessHeap(), 0, device->shader_priv);
 }
 
-static BOOL shader_arb_dirty_const(void)
+static void shader_arb_context_destroyed(void *shader_priv, const struct wined3d_context *context)
 {
-    return TRUE;
+    struct shader_arb_priv *priv = shader_priv;
+
+    if (priv->last_context == context)
+        priv->last_context = NULL;
 }
 
 static void shader_arb_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
@@ -5481,7 +5525,7 @@ const struct wined3d_shader_backend_ops arb_program_shader_backend =
     shader_arb_destroy,
     shader_arb_alloc,
     shader_arb_free,
-    shader_arb_dirty_const,
+    shader_arb_context_destroyed,
     shader_arb_get_caps,
     shader_arb_color_fixup_supported,
 };
@@ -5612,10 +5656,13 @@ static void state_texfactor_arbfp(struct wined3d_context *context,
      * otherwise we'll overwrite application provided constants. */
     if (device->shader_backend == &arb_program_shader_backend)
     {
+        struct shader_arb_priv *priv;
+
         if (use_ps(state)) return;
 
-        context->pshader_const_dirty[ARB_FFP_CONST_TFACTOR] = 1;
-        device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_TFACTOR + 1);
+        priv = device->shader_priv;
+        priv->pshader_const_dirty[ARB_FFP_CONST_TFACTOR] = 1;
+        priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_TFACTOR + 1);
     }
 
     D3DCOLORTOGLFLOAT4(state->render_states[WINED3DRS_TEXTUREFACTOR], col);
@@ -5635,10 +5682,13 @@ static void state_arb_specularenable(struct wined3d_context *context,
      */
     if (device->shader_backend == &arb_program_shader_backend)
     {
+        struct shader_arb_priv *priv;
+
         if (use_ps(state)) return;
 
-        context->pshader_const_dirty[ARB_FFP_CONST_SPECULAR_ENABLE] = 1;
-        device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_SPECULAR_ENABLE + 1);
+        priv = device->shader_priv;
+        priv->pshader_const_dirty[ARB_FFP_CONST_SPECULAR_ENABLE] = 1;
+        priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_SPECULAR_ENABLE + 1);
     }
 
     if (state->render_states[WINED3DRS_SPECULARENABLE])
@@ -5676,9 +5726,12 @@ static void set_bumpmat_arbfp(struct wined3d_context *context, const struct wine
             /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */
             return;
         }
-    } else if(device->shader_backend == &arb_program_shader_backend) {
-        context->pshader_const_dirty[ARB_FFP_CONST_BUMPMAT(stage)] = 1;
-        device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_BUMPMAT(stage) + 1);
+    }
+    else if (device->shader_backend == &arb_program_shader_backend)
+    {
+        struct shader_arb_priv *priv = device->shader_priv;
+        priv->pshader_const_dirty[ARB_FFP_CONST_BUMPMAT(stage)] = 1;
+        priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_BUMPMAT(stage) + 1);
     }
 
     mat[0][0] = *((float *)&state->texture_states[stage][WINED3DTSS_BUMPENVMAT00]);
@@ -5713,9 +5766,12 @@ static void tex_bumpenvlum_arbfp(struct wined3d_context *context,
             /* Exit now, don't set the bumpmat below, otherwise we may overwrite pixel shader constants */
             return;
         }
-    } else if(device->shader_backend == &arb_program_shader_backend) {
-        context->pshader_const_dirty[ARB_FFP_CONST_LUMINANCE(stage)] = 1;
-        device->highest_dirty_ps_const = max(device->highest_dirty_ps_const, ARB_FFP_CONST_LUMINANCE(stage) + 1);
+    }
+    else if (device->shader_backend == &arb_program_shader_backend)
+    {
+        struct shader_arb_priv *priv = device->shader_priv;
+        priv->pshader_const_dirty[ARB_FFP_CONST_LUMINANCE(stage)] = 1;
+        priv->highest_dirty_ps_const = max(priv->highest_dirty_ps_const, ARB_FFP_CONST_LUMINANCE(stage) + 1);
     }
 
     param[0] = *((float *)&state->texture_states[stage][WINED3DTSS_BUMPENVLSCALE]);
diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
index f11b8db..e384fb3 100644
--- a/dlls/wined3d/context.c
+++ b/dlls/wined3d/context.c
@@ -1340,25 +1340,6 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain,
         return NULL;
     }
 
-    if (device->shader_backend->shader_dirtifyable_constants())
-    {
-        /* Create the dirty constants array and initialize them to dirty */
-        ret->vshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
-                sizeof(*ret->vshader_const_dirty) * device->d3d_vshader_constantF);
-        if (!ret->vshader_const_dirty)
-            goto out;
-
-        ret->pshader_const_dirty = HeapAlloc(GetProcessHeap(), 0,
-                sizeof(*ret->pshader_const_dirty) * device->d3d_pshader_constantF);
-        if (!ret->pshader_const_dirty)
-            goto out;
-
-        memset(ret->vshader_const_dirty, 1,
-               sizeof(*ret->vshader_const_dirty) * device->d3d_vshader_constantF);
-        memset(ret->pshader_const_dirty, 1,
-                sizeof(*ret->pshader_const_dirty) * device->d3d_pshader_constantF);
-    }
-
     ret->blit_targets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
             gl_info->limits.buffers * sizeof(*ret->blit_targets));
     if (!ret->blit_targets)
@@ -1655,8 +1636,6 @@ out:
     HeapFree(GetProcessHeap(), 0, ret->free_occlusion_queries);
     HeapFree(GetProcessHeap(), 0, ret->draw_buffers);
     HeapFree(GetProcessHeap(), 0, ret->blit_targets);
-    HeapFree(GetProcessHeap(), 0, ret->pshader_const_dirty);
-    HeapFree(GetProcessHeap(), 0, ret->vshader_const_dirty);
     HeapFree(GetProcessHeap(), 0, ret);
     return NULL;
 }
@@ -1682,8 +1661,6 @@ void context_destroy(struct wined3d_device *device, struct wined3d_context *cont
 
     HeapFree(GetProcessHeap(), 0, context->draw_buffers);
     HeapFree(GetProcessHeap(), 0, context->blit_targets);
-    HeapFree(GetProcessHeap(), 0, context->vshader_const_dirty);
-    HeapFree(GetProcessHeap(), 0, context->pshader_const_dirty);
     device_context_remove(device, context);
     if (destroy) HeapFree(GetProcessHeap(), 0, context);
 }
@@ -2455,7 +2432,7 @@ static void context_setup_target(struct wined3d_context *context, struct wined3d
 }
 
 /* Do not call while under the GL lock. */
-struct wined3d_context *context_acquire(struct wined3d_device *device, struct wined3d_surface *target)
+struct wined3d_context *context_acquire(const struct wined3d_device *device, struct wined3d_surface *target)
 {
     struct wined3d_context *current_context = context_get_current();
     struct wined3d_context *context;
@@ -2522,19 +2499,6 @@ struct wined3d_context *context_acquire(struct wined3d_device *device, struct wi
             device->frag_pipe->enable_extension(!context->last_was_blit);
             LEAVE_GL();
         }
-
-        if (context->vshader_const_dirty)
-        {
-            memset(context->vshader_const_dirty, 1,
-                    sizeof(*context->vshader_const_dirty) * device->d3d_vshader_constantF);
-            device->highest_dirty_vs_const = device->d3d_vshader_constantF;
-        }
-        if (context->pshader_const_dirty)
-        {
-            memset(context->pshader_const_dirty, 1,
-                   sizeof(*context->pshader_const_dirty) * device->d3d_pshader_constantF);
-            device->highest_dirty_ps_const = device->d3d_pshader_constantF;
-        }
     }
     else if (context->restore_ctx)
     {
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 48b5586..5aace82 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -1351,8 +1351,6 @@ HRESULT CDECL wined3d_device_init_3d(struct wined3d_device *device,
 
     if (wined3d_settings.logo)
         device_load_logo(device, wined3d_settings.logo);
-    device->highest_dirty_ps_const = 0;
-    device->highest_dirty_vs_const = 0;
     return WINED3D_OK;
 
 err_out:
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 7e736d8..35a317c 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -4909,11 +4909,7 @@ static void shader_glsl_free(struct wined3d_device *device)
     device->shader_priv = NULL;
 }
 
-static BOOL shader_glsl_dirty_const(void)
-{
-    /* TODO: GL_EXT_bindable_uniform can be used to share constants across shaders */
-    return FALSE;
-}
+static void shader_glsl_context_destroyed(void *shader_priv, const struct wined3d_context *context) {}
 
 static void shader_glsl_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
 {
@@ -5109,7 +5105,7 @@ const struct wined3d_shader_backend_ops glsl_shader_backend =
     shader_glsl_destroy,
     shader_glsl_alloc,
     shader_glsl_free,
-    shader_glsl_dirty_const,
+    shader_glsl_context_destroyed,
     shader_glsl_get_caps,
     shader_glsl_color_fixup_supported,
 };
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index 51dc125..69bd69d 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -1502,7 +1502,7 @@ static void shader_none_load_np2fixup_constants(void *shader_priv,
 static void shader_none_destroy(struct wined3d_shader *shader) {}
 static HRESULT shader_none_alloc(struct wined3d_device *device) {return WINED3D_OK;}
 static void shader_none_free(struct wined3d_device *device) {}
-static BOOL shader_none_dirty_const(void) {return FALSE;}
+static void shader_none_context_destroyed(void *shader_priv, const struct wined3d_context *context) {}
 
 static void shader_none_get_caps(const struct wined3d_gl_info *gl_info, struct shader_caps *caps)
 {
@@ -1547,7 +1547,7 @@ const struct wined3d_shader_backend_ops none_shader_backend =
     shader_none_destroy,
     shader_none_alloc,
     shader_none_free,
-    shader_none_dirty_const,
+    shader_none_context_destroyed,
     shader_none_get_caps,
     shader_none_color_fixup_supported,
 };
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index e911edd..3b86580 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -762,7 +762,7 @@ struct wined3d_shader_backend_ops
     void (*shader_destroy)(struct wined3d_shader *shader);
     HRESULT (*shader_alloc_private)(struct wined3d_device *device);
     void (*shader_free_private)(struct wined3d_device *device);
-    BOOL (*shader_dirtifyable_constants)(void);
+    void (*shader_context_destroyed)(void *shader_priv, const struct wined3d_context *context);
     void (*shader_get_caps)(const struct wined3d_gl_info *gl_info, struct shader_caps *caps);
     BOOL (*shader_color_fixup_supported)(struct color_fixup_desc fixup);
 };
@@ -1093,8 +1093,6 @@ struct wined3d_context
     DWORD active_texture;
     DWORD texture_type[MAX_COMBINED_SAMPLERS];
 
-    char                    *vshader_const_dirty, *pshader_const_dirty;
-
     /* The actual opengl context */
     UINT level;
     HGLRC restore_ctx;
@@ -1228,7 +1226,8 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
         struct wined3d_surface *src_surface, const RECT *src_rect,
         struct wined3d_surface *dst_surface, const RECT *dst_rect) DECLSPEC_HIDDEN;
 
-struct wined3d_context *context_acquire(struct wined3d_device *device, struct wined3d_surface *target) DECLSPEC_HIDDEN;
+struct wined3d_context *context_acquire(const struct wined3d_device *device,
+        struct wined3d_surface *target) DECLSPEC_HIDDEN;
 void context_alloc_event_query(struct wined3d_context *context,
         struct wined3d_event_query *query) DECLSPEC_HIDDEN;
 void context_alloc_occlusion_query(struct wined3d_context *context,
@@ -1705,7 +1704,6 @@ struct wined3d_device
 
     struct list             resources; /* a linked list to track resources created by the device */
     struct list             shaders;   /* a linked list to track shaders (pixel and vertex)      */
-    unsigned int            highest_dirty_ps_const, highest_dirty_vs_const;
 
     /* Render Target Support */
     DWORD valid_rt_mask;
-- 
1.7.3.4




More information about the wine-patches mailing list