From 7aac0159a995e35c96d30ffed19630c0320bfc0f Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Tue, 25 Oct 2011 21:20:29 +0200 Subject: [PATCH] wined3d: Move the ARB shader program constant handling to the backend where it belongs. --- 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 3cd99be4e93..e81a72e6a6d 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 f11b8dbee08..e384fb3ffb1 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 48b55864fab..5aace82a374 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 7e736d889f0..35a317c531d 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 51dc125a8d5..69bd69d6aed 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 e911eddb076..3b865807cb5 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;