wined3d: Use RB tree for storing lights.

This commit is contained in:
Paul Gofman 2023-05-16 21:12:24 -06:00 committed by Alexandre Julliard
parent debe2bd632
commit 71da110b46
4 changed files with 100 additions and 134 deletions

View file

@ -1998,7 +1998,7 @@ static void wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data)
{
const struct wined3d_cs_set_light *op = data;
struct wined3d_light_info *light_info;
unsigned int light_idx, hash_idx;
unsigned int light_idx;
light_idx = op->light.OriginalIndex;
@ -2011,10 +2011,9 @@ static void wined3d_cs_exec_set_light(struct wined3d_cs *cs, const void *data)
return;
}
hash_idx = LIGHTMAP_HASHFUNC(light_idx);
list_add_head(&cs->state.light_state.light_map[hash_idx], &light_info->entry);
light_info->glIndex = -1;
light_info->OriginalIndex = light_idx;
rb_put(&cs->state.light_state.lights_tree, (void *)(ULONG_PTR)light_idx, &light_info->entry);
}
if (light_info->glIndex != -1)

View file

@ -1907,7 +1907,7 @@ void CDECL wined3d_device_context_reset_state(struct wined3d_device_context *con
void CDECL wined3d_device_context_set_state(struct wined3d_device_context *context, struct wined3d_state *state)
{
const struct wined3d_light_info *light;
struct wined3d_light_info *light;
unsigned int i, j;
TRACE("context %p, state %p.\n", context, state);
@ -1991,13 +1991,10 @@ void CDECL wined3d_device_context_set_state(struct wined3d_device_context *conte
wined3d_device_context_emit_set_viewports(context, state->viewport_count, state->viewports);
wined3d_device_context_emit_set_scissor_rects(context, state->scissor_rect_count, state->scissor_rects);
for (i = 0; i < LIGHTMAP_SIZE; ++i)
RB_FOR_EACH_ENTRY(light, &state->light_state.lights_tree, struct wined3d_light_info, entry)
{
LIST_FOR_EACH_ENTRY(light, &state->light_state.light_map[i], struct wined3d_light_info, entry)
{
wined3d_device_context_set_light(context, light->OriginalIndex, &light->OriginalParms);
wined3d_device_context_emit_set_light_enable(context, light->OriginalIndex, light->glIndex != -1);
}
wined3d_device_context_set_light(context, light->OriginalIndex, &light->OriginalParms);
wined3d_device_context_emit_set_light_enable(context, light->OriginalIndex, light->glIndex != -1);
}
for (i = 0; i < WINEHIGHEST_RENDER_STATE + 1; ++i)
@ -3074,6 +3071,7 @@ static void init_transformed_lights(struct lights_settings *ls,
{
const struct wined3d_light_info *lights[WINED3D_MAX_SOFTWARE_ACTIVE_LIGHTS];
const struct wined3d_light_info *light_info;
struct wined3d_light_info *light_iter;
struct light_transformed *light;
struct wined3d_vec4 vec4;
unsigned int light_count;
@ -3105,39 +3103,37 @@ static void init_transformed_lights(struct lights_settings *ls,
ls->normalise = !!state->render_states[WINED3D_RS_NORMALIZENORMALS];
ls->localviewer = !!state->render_states[WINED3D_RS_LOCALVIEWER];
for (i = 0, index = 0; i < LIGHTMAP_SIZE && index < ARRAY_SIZE(lights); ++i)
index = 0;
RB_FOR_EACH_ENTRY(light_iter, &state->light_state.lights_tree, struct wined3d_light_info, entry)
{
LIST_FOR_EACH_ENTRY(light_info, &state->light_state.light_map[i], struct wined3d_light_info, entry)
if (!light_iter->enabled)
continue;
switch (light_iter->OriginalParms.type)
{
if (!light_info->enabled)
continue;
switch (light_info->OriginalParms.type)
{
case WINED3D_LIGHT_DIRECTIONAL:
++ls->directional_light_count;
break;
case WINED3D_LIGHT_POINT:
++ls->point_light_count;
break;
case WINED3D_LIGHT_SPOT:
++ls->spot_light_count;
break;
case WINED3D_LIGHT_PARALLELPOINT:
++ls->parallel_point_light_count;
break;
default:
FIXME("Unhandled light type %#x.\n", light_info->OriginalParms.type);
continue;
}
lights[index++] = light_info;
if (index == WINED3D_MAX_SOFTWARE_ACTIVE_LIGHTS)
case WINED3D_LIGHT_DIRECTIONAL:
++ls->directional_light_count;
break;
case WINED3D_LIGHT_POINT:
++ls->point_light_count;
break;
case WINED3D_LIGHT_SPOT:
++ls->spot_light_count;
break;
case WINED3D_LIGHT_PARALLELPOINT:
++ls->parallel_point_light_count;
break;
default:
FIXME("Unhandled light type %#x.\n", light_iter->OriginalParms.type);
continue;
}
lights[index++] = light_iter;
if (index == WINED3D_MAX_SOFTWARE_ACTIVE_LIGHTS)
break;
}
light_count = index;

View file

@ -340,24 +340,19 @@ void CDECL wined3d_stateblock_init_contained_states(struct wined3d_stateblock *s
}
}
static void stateblock_init_lights(struct wined3d_stateblock *stateblock, const struct list *src_map)
static void stateblock_init_lights(struct wined3d_stateblock *stateblock, const struct rb_tree *src_tree)
{
struct list *dst_map = stateblock->stateblock_state.light_state->light_map;
unsigned int i;
struct rb_tree *dst_tree = &stateblock->stateblock_state.light_state->lights_tree;
struct wined3d_light_info *src_light;
for (i = 0; i < LIGHTMAP_SIZE; ++i)
RB_FOR_EACH_ENTRY(src_light, src_tree, struct wined3d_light_info, entry)
{
const struct wined3d_light_info *src_light;
struct wined3d_light_info *dst_light = heap_alloc(sizeof(*dst_light));
LIST_FOR_EACH_ENTRY(src_light, &src_map[i], struct wined3d_light_info, entry)
{
struct wined3d_light_info *dst_light = heap_alloc(sizeof(*dst_light));
*dst_light = *src_light;
list_add_tail(&dst_map[i], &dst_light->entry);
dst_light->changed = true;
list_add_tail(&stateblock->changed.changed_lights, &dst_light->changed_entry);
}
*dst_light = *src_light;
rb_put(dst_tree, (void *)(ULONG_PTR)dst_light->OriginalIndex, &dst_light->entry);
dst_light->changed = true;
list_add_tail(&stateblock->changed.changed_lights, &dst_light->changed_entry);
}
}
@ -544,41 +539,34 @@ void wined3d_stateblock_state_cleanup(struct wined3d_stateblock_state *state)
}
}
for (i = 0; i < LIGHTMAP_SIZE; ++i)
RB_FOR_EACH_ENTRY_DESTRUCTOR(light, cursor, &state->light_state->lights_tree, struct wined3d_light_info, entry)
{
LIST_FOR_EACH_ENTRY_SAFE(light, cursor, &state->light_state->light_map[i], struct wined3d_light_info, entry)
{
if (light->changed)
list_remove(&light->changed_entry);
list_remove(&light->entry);
heap_free(light);
}
if (light->changed)
list_remove(&light->changed_entry);
rb_remove(&state->light_state->lights_tree, &light->entry);
heap_free(light);
}
}
void state_cleanup(struct wined3d_state *state)
{
unsigned int counter;
struct wined3d_light_info *light, *cursor;
unsigned int i;
if (!(state->flags & WINED3D_STATE_NO_REF))
state_unbind_resources(state);
for (counter = 0; counter < WINED3D_MAX_ACTIVE_LIGHTS; ++counter)
for (i = 0; i < WINED3D_MAX_ACTIVE_LIGHTS; ++i)
{
state->light_state.lights[counter] = NULL;
state->light_state.lights[i] = NULL;
}
for (counter = 0; counter < LIGHTMAP_SIZE; ++counter)
RB_FOR_EACH_ENTRY_DESTRUCTOR(light, cursor, &state->light_state.lights_tree, struct wined3d_light_info, entry)
{
struct list *e1, *e2;
LIST_FOR_EACH_SAFE(e1, e2, &state->light_state.light_map[counter])
{
struct wined3d_light_info *light = LIST_ENTRY(e1, struct wined3d_light_info, entry);
list_remove(&light->entry);
if (light->changed)
list_remove(&light->changed_entry);
heap_free(light);
}
if (light->changed)
list_remove(&light->changed_entry);
rb_remove(&state->light_state.lights_tree, &light->entry);
heap_free(light);
}
}
@ -601,17 +589,12 @@ ULONG CDECL wined3d_stateblock_decref(struct wined3d_stateblock *stateblock)
struct wined3d_light_info *wined3d_light_state_get_light(const struct wined3d_light_state *state, unsigned int idx)
{
struct wined3d_light_info *light_info;
unsigned int hash_idx;
struct rb_entry *entry;
hash_idx = LIGHTMAP_HASHFUNC(idx);
LIST_FOR_EACH_ENTRY(light_info, &state->light_map[hash_idx], struct wined3d_light_info, entry)
{
if (light_info->OriginalIndex == idx)
return light_info;
}
if (!(entry = rb_get(&state->lights_tree, (void *)(ULONG_PTR)idx)))
return NULL;
return NULL;
return RB_ENTRY_VALUE(entry, struct wined3d_light_info, entry);
}
static void set_light_changed(struct wined3d_stateblock *stateblock, struct wined3d_light_info *light_info)
@ -628,7 +611,6 @@ HRESULT wined3d_light_state_set_light(struct wined3d_light_state *state, DWORD l
const struct wined3d_light *params, struct wined3d_light_info **light_info)
{
struct wined3d_light_info *object;
unsigned int hash_idx;
if (!(object = wined3d_light_state_get_light(state, light_idx)))
{
@ -639,10 +621,9 @@ HRESULT wined3d_light_state_set_light(struct wined3d_light_state *state, DWORD l
return E_OUTOFMEMORY;
}
hash_idx = LIGHTMAP_HASHFUNC(light_idx);
list_add_head(&state->light_map[hash_idx], &object->entry);
object->glIndex = -1;
object->OriginalIndex = light_idx;
rb_put(&state->lights_tree, (void *)(ULONG_PTR)light_idx, &object->entry);
}
object->OriginalParms = *params;
@ -702,44 +683,40 @@ static void wined3d_state_record_lights(struct wined3d_light_state *dst_state,
{
const struct wined3d_light_info *src;
struct wined3d_light_info *dst;
UINT i;
/* Lights... For a recorded state block, we just had a chain of actions
* to perform, so we need to walk that chain and update any actions which
* differ. */
for (i = 0; i < LIGHTMAP_SIZE; ++i)
RB_FOR_EACH_ENTRY(dst, &dst_state->lights_tree, struct wined3d_light_info, entry)
{
LIST_FOR_EACH_ENTRY(dst, &dst_state->light_map[i], struct wined3d_light_info, entry)
if ((src = wined3d_light_state_get_light(src_state, dst->OriginalIndex)))
{
if ((src = wined3d_light_state_get_light(src_state, dst->OriginalIndex)))
{
dst->OriginalParms = src->OriginalParms;
dst->OriginalParms = src->OriginalParms;
if (src->glIndex == -1 && dst->glIndex != -1)
{
/* Light disabled. */
dst_state->lights[dst->glIndex] = NULL;
}
else if (src->glIndex != -1 && dst->glIndex == -1)
{
/* Light enabled. */
dst_state->lights[src->glIndex] = dst;
}
dst->glIndex = src->glIndex;
if (src->glIndex == -1 && dst->glIndex != -1)
{
/* Light disabled. */
dst_state->lights[dst->glIndex] = NULL;
}
else
else if (src->glIndex != -1 && dst->glIndex == -1)
{
/* This can happen if the light was originally created as a
* default light for SetLightEnable() while recording. */
WARN("Light %u in dst_state %p does not exist in src_state %p.\n",
dst->OriginalIndex, dst_state, src_state);
/* Light enabled. */
dst_state->lights[src->glIndex] = dst;
}
dst->glIndex = src->glIndex;
}
else
{
/* This can happen if the light was originally created as a
* default light for SetLightEnable() while recording. */
WARN("Light %u in dst_state %p does not exist in src_state %p.\n",
dst->OriginalIndex, dst_state, src_state);
dst->OriginalParms = WINED3D_default_light;
if (dst->glIndex != -1)
{
dst_state->lights[dst->glIndex] = NULL;
dst->glIndex = -1;
}
dst->OriginalParms = WINED3D_default_light;
if (dst->glIndex != -1)
{
dst_state->lights[dst->glIndex] = NULL;
dst->glIndex = -1;
}
}
}
@ -1895,18 +1872,21 @@ static void state_init_default(struct wined3d_state *state, const struct wined3d
}
}
static int lights_compare(const void *key, const struct rb_entry *entry)
{
const struct wined3d_light_info *light = RB_ENTRY_VALUE(entry, struct wined3d_light_info, entry);
unsigned int original_index = (ULONG_PTR)key;
return wined3d_uint32_compare(light->OriginalIndex, original_index);
}
void state_init(struct wined3d_state *state, const struct wined3d_d3d_info *d3d_info,
uint32_t flags, enum wined3d_feature_level feature_level)
{
unsigned int i;
state->feature_level = feature_level;
state->flags = flags;
for (i = 0; i < LIGHTMAP_SIZE; i++)
{
list_init(&state->light_state.light_map[i]);
}
rb_init(&state->light_state.lights_tree, lights_compare);
if (flags & WINED3D_STATE_INIT_DEFAULT)
state_init_default(state, d3d_info);
@ -2001,12 +1981,7 @@ static void stateblock_state_init_default(struct wined3d_stateblock_state *state
void wined3d_stateblock_state_init(struct wined3d_stateblock_state *state,
const struct wined3d_device *device, uint32_t flags)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(state->light_state->light_map); i++)
{
list_init(&state->light_state->light_map[i]);
}
rb_init(&state->light_state->lights_tree, lights_compare);
if (flags & WINED3D_STATE_INIT_DEFAULT)
stateblock_state_init_default(state, &device->adapter->d3d_info);
@ -2035,7 +2010,7 @@ static HRESULT stateblock_init(struct wined3d_stateblock *stateblock, const stru
switch (type)
{
case WINED3D_SBT_ALL:
stateblock_init_lights(stateblock, device_state->stateblock_state.light_state->light_map);
stateblock_init_lights(stateblock, &device_state->stateblock_state.light_state->lights_tree);
stateblock_savedstates_set_all(&stateblock->changed,
d3d_info->limits.vs_uniform_count, d3d_info->limits.ps_uniform_count);
break;
@ -2046,7 +2021,7 @@ static HRESULT stateblock_init(struct wined3d_stateblock *stateblock, const stru
break;
case WINED3D_SBT_VERTEX_STATE:
stateblock_init_lights(stateblock, device_state->stateblock_state.light_state->light_map);
stateblock_init_lights(stateblock, &device_state->stateblock_state.light_state->lights_tree);
stateblock_savedstates_set_vertex(&stateblock->changed,
d3d_info->limits.vs_uniform_count);
break;

View file

@ -2991,7 +2991,7 @@ struct wined3d_light_info
float exponent;
float cutoff;
struct list entry;
struct rb_entry entry;
struct list changed_entry;
bool changed;
};
@ -3880,13 +3880,9 @@ struct wined3d_rasterizer_state
struct wine_rb_entry entry;
};
#define LIGHTMAP_SIZE 43
#define LIGHTMAP_HASHFUNC(x) ((x) % LIGHTMAP_SIZE)
struct wined3d_light_state
{
/* Light hashmap. Collisions are handled using linked lists. */
struct list light_map[LIGHTMAP_SIZE];
struct rb_tree lights_tree;
const struct wined3d_light_info *lights[WINED3D_MAX_ACTIVE_LIGHTS];
};