[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