wined3d: Move the ARB shader program constant handling to the backend where it belongs.

This commit is contained in:
Henri Verbeet 2011-10-25 21:20:29 +02:00 committed by Alexandre Julliard
parent 89d0d3ffd8
commit 7aac0159a9
6 changed files with 89 additions and 77 deletions

View File

@ -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]);

View File

@ -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)
{

View File

@ -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:

View File

@ -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,
};

View File

@ -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,
};

View File

@ -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;