mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Sort proto-palettes by decreasing size when refitting overloaded palettes
Since that refitting process is a First-Fit, it benefits from that sorting step.
This commit is contained in:
@@ -32,7 +32,7 @@ namespace packing {
|
|||||||
* A reference to a proto-palette, and attached attributes for sorting purposes
|
* A reference to a proto-palette, and attached attributes for sorting purposes
|
||||||
*/
|
*/
|
||||||
struct ProtoPalAttrs {
|
struct ProtoPalAttrs {
|
||||||
size_t const protoPalIndex;
|
size_t protoPalIndex;
|
||||||
/*
|
/*
|
||||||
* Pages from which we are banned (to prevent infinite loops)
|
* Pages from which we are banned (to prevent infinite loops)
|
||||||
* This is dynamic because we wish not to hard-cap the amount of palettes
|
* This is dynamic because we wish not to hard-cap the amount of palettes
|
||||||
@@ -359,23 +359,19 @@ std::tuple<DefaultInitVec<size_t>, size_t>
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Sort the proto-palettes by size, which improves the packing algorithm's efficiency
|
// Sort the proto-palettes by size, which improves the packing algorithm's efficiency
|
||||||
|
auto const indexOfLargestProtoPalFirst = [&protoPalettes](size_t left, size_t right) {
|
||||||
|
ProtoPalette const &lhs = protoPalettes[left];
|
||||||
|
ProtoPalette const &rhs = protoPalettes[right];
|
||||||
|
return lhs.size() > rhs.size(); // We want the proto-pals to be sorted *largest first*!
|
||||||
|
};
|
||||||
DefaultInitVec<size_t> sortedProtoPalIDs(protoPalettes.size());
|
DefaultInitVec<size_t> sortedProtoPalIDs(protoPalettes.size());
|
||||||
sortedProtoPalIDs.clear();
|
sortedProtoPalIDs.clear();
|
||||||
for (size_t i = 0; i < protoPalettes.size(); ++i) {
|
for (size_t i = 0; i < protoPalettes.size(); ++i) {
|
||||||
sortedProtoPalIDs.insert(
|
sortedProtoPalIDs.insert(
|
||||||
std::lower_bound(
|
std::lower_bound(RANGE(sortedProtoPalIDs), i, indexOfLargestProtoPalFirst), i
|
||||||
RANGE(sortedProtoPalIDs),
|
|
||||||
i,
|
|
||||||
[&protoPalettes](size_t left, size_t right) {
|
|
||||||
ProtoPalette const &lhs = protoPalettes[left];
|
|
||||||
ProtoPalette const &rhs = protoPalettes[right];
|
|
||||||
return lhs.size()
|
|
||||||
> rhs.size(); // We want the proto-pals to be sorted *largest first*!
|
|
||||||
}
|
|
||||||
),
|
|
||||||
i
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Begin with all proto-palettes queued up for insertion
|
// Begin with all proto-palettes queued up for insertion
|
||||||
std::queue<ProtoPalAttrs> queue(std::deque<ProtoPalAttrs>(RANGE(sortedProtoPalIDs)));
|
std::queue<ProtoPalAttrs> queue(std::deque<ProtoPalAttrs>(RANGE(sortedProtoPalIDs)));
|
||||||
// Begin with no pages
|
// Begin with no pages
|
||||||
@@ -459,17 +455,25 @@ std::tuple<DefaultInitVec<size_t>, size_t>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deal with palettes still overloaded, by emptying them
|
// Deal with palettes still overloaded, by emptying them
|
||||||
|
auto const &largestProtoPalFirst =
|
||||||
|
[&protoPalettes](ProtoPalAttrs const &lhs, ProtoPalAttrs const &rhs) {
|
||||||
|
return protoPalettes[lhs.protoPalIndex].size()
|
||||||
|
> protoPalettes[rhs.protoPalIndex].size();
|
||||||
|
};
|
||||||
|
std::vector<ProtoPalAttrs> overloadQueue{};
|
||||||
for (AssignedProtos &pal : assignments) {
|
for (AssignedProtos &pal : assignments) {
|
||||||
if (pal.volume() > options.maxOpaqueColors()) {
|
if (pal.volume() > options.maxOpaqueColors()) {
|
||||||
for (ProtoPalAttrs &attrs : pal) {
|
for (ProtoPalAttrs &attrs : pal) {
|
||||||
queue.emplace(std::move(attrs));
|
overloadQueue.emplace(
|
||||||
|
std::lower_bound(RANGE(overloadQueue), attrs, largestProtoPalFirst),
|
||||||
|
std::move(attrs)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
pal.clear();
|
pal.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Place back any proto-palettes now in the queue via first-fit
|
// Place back any proto-palettes now in the queue via first-fit
|
||||||
while (!queue.empty()) {
|
for (ProtoPalAttrs const &attrs : overloadQueue) {
|
||||||
ProtoPalAttrs const &attrs = queue.front();
|
|
||||||
ProtoPalette const &protoPal = protoPalettes[attrs.protoPalIndex];
|
ProtoPalette const &protoPal = protoPalettes[attrs.protoPalIndex];
|
||||||
auto iter = std::find_if(RANGE(assignments), [&protoPal](AssignedProtos const &pal) {
|
auto iter = std::find_if(RANGE(assignments), [&protoPal](AssignedProtos const &pal) {
|
||||||
return pal.canFit(protoPal);
|
return pal.canFit(protoPal);
|
||||||
@@ -491,7 +495,6 @@ std::tuple<DefaultInitVec<size_t>, size_t>
|
|||||||
);
|
);
|
||||||
iter->assign(std::move(attrs));
|
iter->assign(std::move(attrs));
|
||||||
}
|
}
|
||||||
queue.pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.verbosity >= Options::VERB_INTERM) {
|
if (options.verbosity >= Options::VERB_INTERM) {
|
||||||
|
|||||||
Reference in New Issue
Block a user