wined3d: Only apply shader constants that changed.
Henri Verbeet
hverbeet at codeweavers.com
Fri Dec 19 12:21:56 CST 2008
This improves performance a bit for applications that use a lot of shaders
with a lot of constants.
---
dlls/wined3d/glsl_shader.c | 402 ++++++++++++++++++++++++++++------------
dlls/wined3d/stateblock.c | 13 --
dlls/wined3d/utils.c | 10 +
dlls/wined3d/wined3d_private.h | 9 +-
4 files changed, 293 insertions(+), 141 deletions(-)
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index b9a0e2e..2aceb90 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -29,6 +29,7 @@
*/
#include "config.h"
+#include <limits.h>
#include <stdio.h>
#include "wined3d_private.h"
@@ -54,11 +55,35 @@ typedef struct {
DWORD coord_mask;
} glsl_sample_function_t;
+enum heap_node_op
+{
+ HEAP_NODE_TRAVERSE_LEFT,
+ HEAP_NODE_TRAVERSE_RIGHT,
+ HEAP_NODE_POP,
+};
+
+struct constant_entry
+{
+ unsigned int idx;
+ unsigned int version;
+};
+
+struct constant_heap
+{
+ struct constant_entry *entries;
+ unsigned int *positions;
+ unsigned int size;
+};
+
/* GLSL shader private data */
struct shader_glsl_priv {
struct hash_table_t *glsl_program_lookup;
- const struct glsl_shader_prog_link *glsl_program;
+ struct glsl_shader_prog_link *glsl_program;
+ struct constant_heap vconst_heap;
+ struct constant_heap pconst_heap;
+ unsigned char *stack;
GLhandleARB depth_blt_program[tex_type_count];
+ UINT next_constant_version;
};
/* Struct to maintain data about a linked GLSL program */
@@ -79,6 +104,7 @@ struct glsl_shader_prog_link {
GLhandleARB vshader;
IWineD3DPixelShader *pshader;
struct ps_compile_args ps_args;
+ UINT constant_version;
};
typedef struct {
@@ -189,107 +215,166 @@ static void shader_glsl_load_vsamplers(const WineD3D_GL_Info *gl_info, IWineD3DS
}
}
-/**
- * Loads floating point constants (aka uniforms) into the currently set GLSL program.
- * When constant_list == NULL, it will load all the constants.
- */
-static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const WineD3D_GL_Info *gl_info,
- unsigned int max_constants, const float *constants, const GLhandleARB *constant_locations,
- const struct list *constant_list)
+static inline void walk_constant_heap(const WineD3D_GL_Info *gl_info, const float *constants,
+ const GLhandleARB *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
{
- const constants_entry *constant;
- const local_constant *lconst;
- GLhandleARB tmp_loc;
- DWORD i, j, k;
- const DWORD *idx;
-
- if (TRACE_ON(d3d_shader)) {
- LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
- idx = constant->idx;
- j = constant->count;
- while (j--) {
- i = *idx++;
- tmp_loc = constant_locations[i];
- if (tmp_loc != -1) {
- TRACE_(d3d_constants)("Loading constants %i: %f, %f, %f, %f\n", i,
- constants[i * 4 + 0], constants[i * 4 + 1],
- constants[i * 4 + 2], constants[i * 4 + 3]);
+ int stack_idx = 0;
+ unsigned int heap_idx = 1;
+ unsigned int idx;
+
+ if (heap->entries[heap_idx].version <= version) return;
+
+ idx = heap->entries[heap_idx].idx;
+ if (constant_locations[idx] != -1) GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+
+ while (stack_idx >= 0)
+ {
+ /* Note that we fall through to the next case statement. */
+ switch(stack[stack_idx])
+ {
+ case HEAP_NODE_TRAVERSE_LEFT:
+ {
+ unsigned int left_idx = heap_idx << 1;
+ if (left_idx < heap->size && heap->entries[left_idx].version > version)
+ {
+ heap_idx = left_idx;
+ idx = heap->entries[heap_idx].idx;
+ if (constant_locations[idx] != -1)
+ GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+
+ stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+ break;
}
}
+
+ case HEAP_NODE_TRAVERSE_RIGHT:
+ {
+ unsigned int right_idx = (heap_idx << 1) + 1;
+ if (right_idx < heap->size && heap->entries[right_idx].version > version)
+ {
+ heap_idx = right_idx;
+ idx = heap->entries[heap_idx].idx;
+ if (constant_locations[idx] != -1)
+ GL_EXTCALL(glUniform4fvARB(constant_locations[idx], 1, &constants[idx * 4]));
+
+ stack[stack_idx++] = HEAP_NODE_POP;
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+ break;
+ }
+ }
+
+ case HEAP_NODE_POP:
+ {
+ heap_idx >>= 1;
+ --stack_idx;
+ break;
+ }
}
}
+ checkGLcall("walk_constant_heap()");
+}
- /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */
- if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.reg_maps.shader_version) == 1
- && shader_is_pshader_version(This->baseShader.reg_maps.shader_version))
+static inline void apply_clamped_constant(const WineD3D_GL_Info *gl_info, GLint location, const GLfloat *data)
+{
+ GLfloat clamped_constant[4];
+
+ if (location == -1) return;
+
+ clamped_constant[0] = data[0] < -1.0f ? -1.0f : data[0] > 1.0 ? 1.0 : data[0];
+ clamped_constant[1] = data[1] < -1.0f ? -1.0f : data[1] > 1.0 ? 1.0 : data[1];
+ clamped_constant[2] = data[2] < -1.0f ? -1.0f : data[2] > 1.0 ? 1.0 : data[2];
+ clamped_constant[3] = data[3] < -1.0f ? -1.0f : data[3] > 1.0 ? 1.0 : data[3];
+
+ GL_EXTCALL(glUniform4fvARB(location, 1, clamped_constant));
+}
+
+static inline void walk_constant_heap_clamped(const WineD3D_GL_Info *gl_info, const float *constants,
+ const GLhandleARB *constant_locations, const struct constant_heap *heap, unsigned char *stack, DWORD version)
+{
+ int stack_idx = 0;
+ unsigned int heap_idx = 1;
+ unsigned int idx;
+
+ if (heap->entries[heap_idx].version <= version) return;
+
+ idx = heap->entries[heap_idx].idx;
+ apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+
+ while (stack_idx >= 0)
{
- float lcl_const[4];
-
- LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
- idx = constant->idx;
- j = constant->count;
- while (j--) {
- i = *idx++;
- tmp_loc = constant_locations[i];
- if (tmp_loc != -1) {
- /* We found this uniform name in the program - go ahead and send the data */
- k = i * 4;
- if(constants[k + 0] < -1.0) lcl_const[0] = -1.0;
- else if(constants[k + 0] > 1.0) lcl_const[0] = 1.0;
- else lcl_const[0] = constants[k + 0];
- if(constants[k + 1] < -1.0) lcl_const[1] = -1.0;
- else if(constants[k + 1] > 1.0) lcl_const[1] = 1.0;
- else lcl_const[1] = constants[k + 1];
- if(constants[k + 2] < -1.0) lcl_const[2] = -1.0;
- else if(constants[k + 2] > 1.0) lcl_const[2] = 1.0;
- else lcl_const[2] = constants[k + 2];
- if(constants[k + 3] < -1.0) lcl_const[3] = -1.0;
- else if(constants[k + 3] > 1.0) lcl_const[3] = 1.0;
- else lcl_const[3] = constants[k + 3];
-
- GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, lcl_const));
+ /* Note that we fall through to the next case statement. */
+ switch(stack[stack_idx])
+ {
+ case HEAP_NODE_TRAVERSE_LEFT:
+ {
+ unsigned int left_idx = heap_idx << 1;
+ if (left_idx < heap->size && heap->entries[left_idx].version > version)
+ {
+ heap_idx = left_idx;
+ idx = heap->entries[heap_idx].idx;
+ apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+
+ stack[stack_idx++] = HEAP_NODE_TRAVERSE_RIGHT;
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+ break;
}
}
- }
- } else {
- LIST_FOR_EACH_ENTRY(constant, constant_list, constants_entry, entry) {
- idx = constant->idx;
- j = constant->count;
- while (j--) {
- i = *idx++;
- tmp_loc = constant_locations[i];
- if (tmp_loc != -1) {
- /* We found this uniform name in the program - go ahead and send the data */
- GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, constants + (i * 4)));
+
+ case HEAP_NODE_TRAVERSE_RIGHT:
+ {
+ unsigned int right_idx = (heap_idx << 1) + 1;
+ if (right_idx < heap->size && heap->entries[right_idx].version > version)
+ {
+ heap_idx = right_idx;
+ idx = heap->entries[heap_idx].idx;
+ apply_clamped_constant(gl_info, constant_locations[idx], &constants[idx * 4]);
+
+ stack[stack_idx++] = HEAP_NODE_POP;
+ stack[stack_idx] = HEAP_NODE_TRAVERSE_LEFT;
+ break;
}
}
+
+ case HEAP_NODE_POP:
+ {
+ heap_idx >>= 1;
+ --stack_idx;
+ break;
+ }
}
}
- checkGLcall("glUniform4fvARB()");
+ checkGLcall("walk_constant_heap_clamped()");
+}
- if(!This->baseShader.load_local_constsF) {
+/* Loads floating point constants (aka uniforms) into the currently set GLSL program. */
+static void shader_glsl_load_constantsF(IWineD3DBaseShaderImpl *This, const WineD3D_GL_Info *gl_info,
+ const float *constants, const GLhandleARB *constant_locations, const struct constant_heap *heap,
+ unsigned char *stack, UINT version)
+{
+ const local_constant *lconst;
+
+ /* 1.X pshaders have the constants clamped to [-1;1] implicitly. */
+ if (WINED3DSHADER_VERSION_MAJOR(This->baseShader.reg_maps.shader_version) == 1
+ && shader_is_pshader_version(This->baseShader.reg_maps.shader_version))
+ walk_constant_heap_clamped(gl_info, constants, constant_locations, heap, stack, version);
+ else
+ walk_constant_heap(gl_info, constants, constant_locations, heap, stack, version);
+
+ if (!This->baseShader.load_local_constsF)
+ {
TRACE("No need to load local float constants for this shader\n");
return;
}
- /* Load immediate constants */
- if (TRACE_ON(d3d_shader)) {
- LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
- tmp_loc = constant_locations[lconst->idx];
- if (tmp_loc != -1) {
- const GLfloat *values = (const GLfloat *)lconst->value;
- TRACE_(d3d_constants)("Loading local constants %i: %f, %f, %f, %f\n", lconst->idx,
- values[0], values[1], values[2], values[3]);
- }
- }
- }
/* Immediate constants are clamped to [-1;1] at shader creation time if needed */
- LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry) {
- tmp_loc = constant_locations[lconst->idx];
- if (tmp_loc != -1) {
- /* We found this uniform name in the program - go ahead and send the data */
- GL_EXTCALL(glUniform4fvARB(tmp_loc, 1, (const GLfloat *)lconst->value));
- }
+ LIST_FOR_EACH_ENTRY(lconst, &This->baseShader.constantsF, local_constant, entry)
+ {
+ GLhandleARB location = constant_locations[lconst->idx];
+ /* We found this uniform name in the program - go ahead and send the data */
+ if (location != -1) GL_EXTCALL(glUniform4fvARB(location, 1, (const GLfloat *)lconst->value));
}
checkGLcall("glUniform4fvARB()");
}
@@ -381,7 +466,11 @@ static void shader_glsl_load_constantsB(IWineD3DBaseShaderImpl *This, const Wine
}
}
-
+static void reset_program_constant_version(void *value, void *context)
+{
+ struct glsl_shader_prog_link *entry = (struct glsl_shader_prog_link *)value;
+ entry->constant_version = 0;
+}
/**
* Loads the app-supplied constants into the currently set GLSL program.
@@ -392,14 +481,13 @@ static void shader_glsl_load_constants(
char useVertexShader) {
IWineD3DDeviceImpl* deviceImpl = (IWineD3DDeviceImpl*) device;
- const struct shader_glsl_priv *priv = (struct shader_glsl_priv *)deviceImpl->shader_priv;
+ struct shader_glsl_priv *priv = (struct shader_glsl_priv *)deviceImpl->shader_priv;
IWineD3DStateBlockImpl* stateBlock = deviceImpl->stateBlock;
const WineD3D_GL_Info *gl_info = &deviceImpl->adapter->gl_info;
- const GLhandleARB *constant_locations;
- const struct list *constant_list;
GLhandleARB programId;
- const struct glsl_shader_prog_link *prog = priv->glsl_program;
+ struct glsl_shader_prog_link *prog = priv->glsl_program;
+ UINT constant_version;
int i;
if (!prog) {
@@ -407,16 +495,14 @@ static void shader_glsl_load_constants(
return;
}
programId = prog->programId;
+ constant_version = prog->constant_version;
if (useVertexShader) {
IWineD3DBaseShaderImpl* vshader = (IWineD3DBaseShaderImpl*) stateBlock->vertexShader;
- constant_locations = prog->vuniformF_locations;
- constant_list = &stateBlock->set_vconstantsF;
-
/* Load DirectX 9 float constants/uniforms for vertex shader */
- shader_glsl_load_constantsF(vshader, gl_info, GL_LIMITS(vshader_constantsF),
- stateBlock->vertexShaderConstantF, constant_locations, constant_list);
+ shader_glsl_load_constantsF(vshader, gl_info, stateBlock->vertexShaderConstantF,
+ prog->vuniformF_locations, &priv->vconst_heap, priv->stack, constant_version);
/* Load DirectX 9 integer constants/uniforms for vertex shader */
if(vshader->baseShader.uses_int_consts) {
@@ -439,12 +525,9 @@ static void shader_glsl_load_constants(
IWineD3DBaseShaderImpl* pshader = (IWineD3DBaseShaderImpl*) stateBlock->pixelShader;
- constant_locations = prog->puniformF_locations;
- constant_list = &stateBlock->set_pconstantsF;
-
/* Load DirectX 9 float constants/uniforms for pixel shader */
- shader_glsl_load_constantsF(pshader, gl_info, GL_LIMITS(pshader_constantsF),
- stateBlock->pixelShaderConstantF, constant_locations, constant_list);
+ shader_glsl_load_constantsF(pshader, gl_info, stateBlock->pixelShaderConstantF,
+ prog->puniformF_locations, &priv->pconst_heap, priv->stack, constant_version);
/* Load DirectX 9 integer constants/uniforms for pixel shader */
if(pshader->baseShader.uses_int_consts) {
@@ -496,49 +579,71 @@ static void shader_glsl_load_constants(
GL_EXTCALL(glUniform4fvARB(prog->ycorrection_location, 1, correction_params));
}
}
+
+ if (priv->next_constant_version == UINT_MAX)
+ {
+ TRACE("Max constant version reached, resetting to 0.\n");
+ hash_table_for_each_entry(priv->glsl_program_lookup, reset_program_constant_version, NULL);
+ priv->next_constant_version = 1;
+ }
+ else
+ {
+ prog->constant_version = priv->next_constant_version++;
+ }
+}
+
+static inline void update_heap_entry(struct constant_heap *heap, unsigned int idx,
+ unsigned int heap_idx, DWORD new_version)
+{
+ struct constant_entry *entries = heap->entries;
+ unsigned int *positions = heap->positions;
+ unsigned int parent_idx;
+
+ while (heap_idx > 1)
+ {
+ parent_idx = heap_idx >> 1;
+
+ if (new_version <= entries[parent_idx].version) break;
+
+ entries[heap_idx] = entries[parent_idx];
+ positions[entries[parent_idx].idx] = heap_idx;
+ heap_idx = parent_idx;
+ }
+
+ entries[heap_idx].version = new_version;
+ entries[heap_idx].idx = idx;
+ positions[idx] = heap_idx;
}
static void shader_glsl_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ struct shader_glsl_priv *priv = (struct shader_glsl_priv *)This->shader_priv;
+ struct constant_heap *heap = &priv->vconst_heap;
UINT i;
for (i = start; i < count + start; ++i)
{
if (!This->stateBlock->changed.vertexShaderConstantsF[i])
- {
- constants_entry *ptr = LIST_ENTRY(list_head(&This->stateBlock->set_vconstantsF),
- constants_entry, entry);
-
- if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx))
- {
- ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
- list_add_head(&This->stateBlock->set_vconstantsF, &ptr->entry);
- }
- ptr->idx[ptr->count++] = i;
- }
+ update_heap_entry(heap, i, heap->size++, priv->next_constant_version);
+ else
+ update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version);
}
}
static void shader_glsl_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count)
{
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ struct shader_glsl_priv *priv = (struct shader_glsl_priv *)This->shader_priv;
+ struct constant_heap *heap = &priv->pconst_heap;
UINT i;
for (i = start; i < count + start; ++i)
{
if (!This->stateBlock->changed.pixelShaderConstantsF[i])
- {
- constants_entry *ptr = LIST_ENTRY(list_head(&This->stateBlock->set_pconstantsF),
- constants_entry, entry);
-
- if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx))
- {
- ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
- list_add_head(&This->stateBlock->set_pconstantsF, &ptr->entry);
- }
- ptr->idx[ptr->count++] = i;
- }
+ update_heap_entry(heap, i, heap->size++, priv->next_constant_version);
+ else
+ update_heap_entry(heap, i, heap->positions[i], priv->next_constant_version);
}
}
@@ -3215,6 +3320,7 @@ static void set_glsl_shader_program(IWineD3DDevice *iface, BOOL use_ps, BOOL use
entry->vshader = vshader_id;
entry->pshader = pshader;
entry->ps_args = compile_args;
+ entry->constant_version = 0;
/* Add the hash table entry */
add_glsl_program_entry(priv, entry);
@@ -3578,10 +3684,64 @@ static BOOL glsl_program_key_compare(const void *keya, const void *keyb)
(memcmp(&ka->ps_args, &kb->ps_args, sizeof(kb->ps_args)) == 0);
}
+static BOOL constant_heap_init(struct constant_heap *heap, unsigned int constant_count)
+{
+ SIZE_T size = (constant_count + 1) * sizeof(*heap->entries) + constant_count * sizeof(*heap->positions);
+ void *mem = HeapAlloc(GetProcessHeap(), 0, size);
+
+ if (!mem)
+ {
+ ERR("Failed to allocate memory\n");
+ return FALSE;
+ }
+
+ heap->entries = mem;
+ heap->entries[1].version = 0;
+ heap->positions = (unsigned int *)(heap->entries + constant_count + 1);
+ heap->size = 1;
+
+ return TRUE;
+}
+
+static void constant_heap_free(struct constant_heap *heap)
+{
+ HeapFree(GetProcessHeap(), 0, heap->entries);
+}
+
static HRESULT shader_glsl_alloc(IWineD3DDevice *iface) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ const WineD3D_GL_Info *gl_info = &This->adapter->gl_info;
struct shader_glsl_priv *priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct shader_glsl_priv));
+ SIZE_T stack_size = wined3d_log2i(max(GL_LIMITS(vshader_constantsF), GL_LIMITS(pshader_constantsF))) + 1;
+
+ priv->stack = HeapAlloc(GetProcessHeap(), 0, stack_size * sizeof(*priv->stack));
+ if (!priv->stack)
+ {
+ ERR("Failed to allocate memory.\n");
+ HeapFree(GetProcessHeap(), 0, priv);
+ return E_OUTOFMEMORY;
+ }
+
+ if (!constant_heap_init(&priv->vconst_heap, GL_LIMITS(vshader_constantsF)))
+ {
+ ERR("Failed to initialize vertex shader constant heap\n");
+ HeapFree(GetProcessHeap(), 0, priv->stack);
+ HeapFree(GetProcessHeap(), 0, priv);
+ return E_OUTOFMEMORY;
+ }
+
+ if (!constant_heap_init(&priv->pconst_heap, GL_LIMITS(pshader_constantsF)))
+ {
+ ERR("Failed to initialize pixel shader constant heap\n");
+ constant_heap_free(&priv->vconst_heap);
+ HeapFree(GetProcessHeap(), 0, priv->stack);
+ HeapFree(GetProcessHeap(), 0, priv);
+ return E_OUTOFMEMORY;
+ }
+
priv->glsl_program_lookup = hash_table_create(glsl_program_key_hash, glsl_program_key_compare);
+ priv->next_constant_version = 1;
+
This->shader_priv = priv;
return WINED3D_OK;
}
@@ -3601,6 +3761,8 @@ static void shader_glsl_free(IWineD3DDevice *iface) {
}
hash_table_destroy(priv->glsl_program_lookup, NULL, NULL);
+ constant_heap_free(&priv->pconst_heap);
+ constant_heap_free(&priv->vconst_heap);
HeapFree(GetProcessHeap(), 0, This->shader_priv);
This->shader_priv = NULL;
diff --git a/dlls/wined3d/stateblock.c b/dlls/wined3d/stateblock.c
index 4859262..e1d4627 100644
--- a/dlls/wined3d/stateblock.c
+++ b/dlls/wined3d/stateblock.c
@@ -57,9 +57,6 @@ HRESULT allocate_shader_constants(IWineD3DStateBlockImpl* object) {
object->contained_ps_consts_f = HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD) * GL_LIMITS(pshader_constantsF));
if (!object->contained_ps_consts_f) goto fail;
- list_init(&object->set_vconstantsF);
- list_init(&object->set_pconstantsF);
-
return WINED3D_OK;
fail:
@@ -252,7 +249,6 @@ static ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
if (!refCount) {
- constants_entry *constant, *constant2;
int counter;
/* type 0 represents the primary stateblock, so free all the resources */
@@ -294,15 +290,6 @@ static ULONG WINAPI IWineD3DStateBlockImpl_Release(IWineD3DStateBlock *iface) {
HeapFree(GetProcessHeap(), 0, This->changed.pixelShaderConstantsF);
HeapFree(GetProcessHeap(), 0, This->contained_vs_consts_f);
HeapFree(GetProcessHeap(), 0, This->contained_ps_consts_f);
-
- LIST_FOR_EACH_ENTRY_SAFE(constant, constant2, &This->set_vconstantsF, constants_entry, entry) {
- HeapFree(GetProcessHeap(), 0, constant);
- }
-
- LIST_FOR_EACH_ENTRY_SAFE(constant, constant2, &This->set_pconstantsF, constants_entry, entry) {
- HeapFree(GetProcessHeap(), 0, constant);
- }
-
HeapFree(GetProcessHeap(), 0, This);
}
return refCount;
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index b9c4bf2..95ee0ec 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -1723,6 +1723,16 @@ void hash_table_destroy(struct hash_table_t *table, void (*free_value)(void *val
HeapFree(GetProcessHeap(), 0, table);
}
+void hash_table_for_each_entry(struct hash_table_t *table, void (*callback)(void *value, void *context), void *context)
+{
+ unsigned int i = 0;
+
+ for (i = 0; i < table->entry_count; ++i)
+ {
+ callback(table->entries[i].value, context);
+ }
+}
+
static inline struct hash_table_entry_t *hash_table_get_by_idx(const struct hash_table_t *table, const void *key,
unsigned int idx)
{
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index d433b53..7e422fb 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -153,6 +153,7 @@ struct hash_table_t {
struct hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function_t *compare_function);
void hash_table_destroy(struct hash_table_t *table, void (*free_value)(void *value, void *cb), void *cb);
+void hash_table_for_each_entry(struct hash_table_t *table, void (*callback)(void *value, void *context), void *context);
void *hash_table_get(const struct hash_table_t *table, const void *key);
void hash_table_put(struct hash_table_t *table, void *key, void *value);
void hash_table_remove(struct hash_table_t *table, void *key);
@@ -1784,12 +1785,6 @@ typedef struct SAVEDSTATES {
BOOL scissorRect;
} SAVEDSTATES;
-typedef struct {
- struct list entry;
- DWORD count;
- DWORD idx[13];
-} constants_entry;
-
struct StageState {
DWORD stage;
DWORD state;
@@ -1808,8 +1803,6 @@ struct IWineD3DStateBlockImpl
/* Array indicating whether things have been set or changed */
SAVEDSTATES changed;
- struct list set_vconstantsF;
- struct list set_pconstantsF;
/* Vertex Shader Declaration */
IWineD3DVertexDeclaration *vertexDecl;
--
1.5.6.4
--------------020001090505090400010400--
More information about the wine-patches
mailing list