[repacker] handle a couple of duplication edge cases.
- Detect cases where there are multiple links from a parent to a child. Don't duplicate that child if those are the only remaining links to the child. - Correctly handle isolating a subgraph where the root idx has multiple incoming links.
This commit is contained in:
parent
c19ec97da7
commit
fe155de989
|
@ -366,10 +366,15 @@ struct graph_t
|
||||||
*/
|
*/
|
||||||
bool isolate_subgraph (unsigned root_idx)
|
bool isolate_subgraph (unsigned root_idx)
|
||||||
{
|
{
|
||||||
|
update_incoming_edge_count ();
|
||||||
hb_hashmap_t<unsigned, unsigned> subgraph;
|
hb_hashmap_t<unsigned, unsigned> subgraph;
|
||||||
hb_hashmap_t<unsigned, unsigned> index_map;
|
|
||||||
|
// incoming edges to root_idx should be all 32 bit in length so we don't need to de-dup these
|
||||||
|
// set the subgraph incoming edge count to match all of root_idx's incoming edges
|
||||||
|
subgraph.set (root_idx, vertices_[root_idx].incoming_edges);
|
||||||
find_subgraph(root_idx, subgraph);
|
find_subgraph(root_idx, subgraph);
|
||||||
|
|
||||||
|
hb_hashmap_t<unsigned, unsigned> index_map;
|
||||||
bool made_changes = false;
|
bool made_changes = false;
|
||||||
for (auto entry : subgraph.iter ())
|
for (auto entry : subgraph.iter ())
|
||||||
{
|
{
|
||||||
|
@ -393,15 +398,16 @@ struct graph_t
|
||||||
|
|
||||||
void find_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& subgraph)
|
void find_subgraph (unsigned node_idx, hb_hashmap_t<unsigned, unsigned>& subgraph)
|
||||||
{
|
{
|
||||||
if (subgraph.has (node_idx))
|
|
||||||
{
|
|
||||||
subgraph.set (node_idx, subgraph[node_idx] + 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
subgraph.set (node_idx, 1);
|
|
||||||
for (const auto& link : vertices_[node_idx].obj.links)
|
for (const auto& link : vertices_[node_idx].obj.links)
|
||||||
|
{
|
||||||
|
if (subgraph.has (link.objidx))
|
||||||
|
{
|
||||||
|
subgraph.set (link.objidx, subgraph[link.objidx] + 1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
subgraph.set (link.objidx, 1);
|
||||||
find_subgraph (link.objidx, subgraph);
|
find_subgraph (link.objidx, subgraph);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -466,13 +472,30 @@ struct graph_t
|
||||||
* parent to the clone. The copy is a shallow copy, objects
|
* parent to the clone. The copy is a shallow copy, objects
|
||||||
* linked from child are not duplicated.
|
* linked from child are not duplicated.
|
||||||
*/
|
*/
|
||||||
void duplicate (unsigned parent_idx, unsigned child_idx)
|
bool duplicate (unsigned parent_idx, unsigned child_idx)
|
||||||
{
|
{
|
||||||
|
update_incoming_edge_count ();
|
||||||
|
|
||||||
|
unsigned links_to_child = 0;
|
||||||
|
for (const auto& l : vertices_[parent_idx].obj.links)
|
||||||
|
{
|
||||||
|
if (l.objidx == child_idx) links_to_child++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vertices_[child_idx].incoming_edges <= links_to_child)
|
||||||
|
{
|
||||||
|
// Can't duplicate this node, doing so would orphan the original one as all remaining links
|
||||||
|
// to child are from parent.
|
||||||
|
DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d",
|
||||||
|
parent_idx, child_idx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
|
DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
|
||||||
parent_idx, child_idx);
|
parent_idx, child_idx);
|
||||||
|
|
||||||
unsigned clone_idx = duplicate (child_idx);
|
unsigned clone_idx = duplicate (child_idx);
|
||||||
if (clone_idx == (unsigned) -1) return;
|
if (clone_idx == (unsigned) -1) return false;
|
||||||
// duplicate shifts the root node idx, so if parent_idx was root update it.
|
// duplicate shifts the root node idx, so if parent_idx was root update it.
|
||||||
if (parent_idx == clone_idx) parent_idx++;
|
if (parent_idx == clone_idx) parent_idx++;
|
||||||
auto& clone = vertices_[clone_idx];
|
auto& clone = vertices_[clone_idx];
|
||||||
|
@ -489,6 +512,8 @@ struct graph_t
|
||||||
child.incoming_edges--;
|
child.incoming_edges--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -819,7 +844,7 @@ static bool _process_overflows (const hb_vector_t<graph_t::overflow_record_t>& o
|
||||||
{
|
{
|
||||||
// The child object is shared, we may be able to eliminate the overflow
|
// The child object is shared, we may be able to eliminate the overflow
|
||||||
// by duplicating it.
|
// by duplicating it.
|
||||||
sorted_graph.duplicate (r.parent, r.child);
|
if (!sorted_graph.duplicate (r.parent, r.child)) continue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue