Debug: Add mode to sprite dump window to show unoptimised

This commit is contained in:
Jonathan G Rennison
2022-06-07 18:54:42 +01:00
parent 22e10462dc
commit 86324e0fda
8 changed files with 209 additions and 57 deletions

View File

@@ -5544,20 +5544,8 @@ static const CallbackResultSpriteGroup *NewCallbackResultSpriteGroup(uint16 grou
return ptr;
}
/* Helper function to either create a callback or link to a previously
* defined spritegroup. */
static const SpriteGroup *GetGroupFromGroupID(byte setid, byte type, uint16 groupid)
static const SpriteGroup *PruneTargetSpriteGroup(const SpriteGroup *result)
{
if (HasBit(groupid, 15)) {
return NewCallbackResultSpriteGroup(groupid);
}
if (groupid > MAX_SPRITEGROUP || _cur.spritegroups[groupid] == nullptr) {
grfmsg(1, "GetGroupFromGroupID(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty", setid, type, groupid);
return nullptr;
}
const SpriteGroup *result = _cur.spritegroups[groupid];
if (HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2) || HasGrfOptimiserFlag(NGOF_NO_OPT_VARACT2_GROUP_PRUNE)) return result;
while (result != nullptr) {
if (result->type == SGT_DETERMINISTIC) {
@@ -5580,6 +5568,24 @@ static const SpriteGroup *GetGroupFromGroupID(byte setid, byte type, uint16 grou
return result;
}
/* Helper function to either create a callback or link to a previously
* defined spritegroup. */
static const SpriteGroup *GetGroupFromGroupID(byte setid, byte type, uint16 groupid)
{
if (HasBit(groupid, 15)) {
return NewCallbackResultSpriteGroup(groupid);
}
if (groupid > MAX_SPRITEGROUP || _cur.spritegroups[groupid] == nullptr) {
grfmsg(1, "GetGroupFromGroupID(0x%02X:0x%02X): Groupid 0x%04X does not exist, leaving empty", setid, type, groupid);
return nullptr;
}
const SpriteGroup *result = _cur.spritegroups[groupid];
if (likely(!HasBit(_misc_debug_flags, MDF_NEWGRF_SG_SAVE_RAW))) result = PruneTargetSpriteGroup(result);
return result;
}
static const SpriteGroup *GetGroupByID(uint16 groupid)
{
const SpriteGroup *result = _cur.spritegroups[groupid];
@@ -6793,6 +6799,46 @@ static void HandleVarAction2OptimisationPasses()
}
}
static void ProcessDeterministicSpriteGroupRanges(const std::vector<DeterministicSpriteGroupRange> &ranges, std::vector<DeterministicSpriteGroupRange> &ranges_out, const SpriteGroup *default_group)
{
/* Sort ranges ascending. When ranges overlap, this may required clamping or splitting them */
std::vector<uint32> bounds;
for (uint i = 0; i < ranges.size(); i++) {
bounds.push_back(ranges[i].low);
if (ranges[i].high != UINT32_MAX) bounds.push_back(ranges[i].high + 1);
}
std::sort(bounds.begin(), bounds.end());
bounds.erase(std::unique(bounds.begin(), bounds.end()), bounds.end());
std::vector<const SpriteGroup *> target;
for (uint j = 0; j < bounds.size(); ++j) {
uint32 v = bounds[j];
const SpriteGroup *t = default_group;
for (uint i = 0; i < ranges.size(); i++) {
if (ranges[i].low <= v && v <= ranges[i].high) {
t = ranges[i].group;
break;
}
}
target.push_back(t);
}
assert(target.size() == bounds.size());
for (uint j = 0; j < bounds.size(); ) {
if (target[j] != default_group) {
DeterministicSpriteGroupRange &r = ranges_out.emplace_back();
r.group = target[j];
r.low = bounds[j];
while (j < bounds.size() && target[j] == r.group) {
j++;
}
r.high = j < bounds.size() ? bounds[j] - 1 : UINT32_MAX;
} else {
j++;
}
}
}
/* Action 0x02 */
static void NewSpriteGroup(ByteReader *buf)
{
@@ -6849,6 +6895,11 @@ static void NewSpriteGroup(ByteReader *buf)
case 2: group->size = DSG_SIZE_DWORD; varsize = 4; break;
}
DeterministicSpriteGroupShadowCopy *shadow = nullptr;
if (unlikely(HasBit(_misc_debug_flags, MDF_NEWGRF_SG_SAVE_RAW))) {
shadow = &(_deterministic_sg_shadows[group]);
}
VarAction2OptimiseState va2_opt_state;
/* The initial value is always the constant 0 */
va2_opt_state.inference = VA2AIF_SIGNED_NON_NEGATIVE | VA2AIF_ONE_OR_ZERO | VA2AIF_HAVE_CONSTANT;
@@ -6904,6 +6955,11 @@ static void NewSpriteGroup(ByteReader *buf)
adjust.add_val = 0;
adjust.divmod_val = 0;
}
if (unlikely(shadow != nullptr)) {
shadow->adjusts.push_back(adjust);
/* Pruning was turned off so that the unpruned target could be saved in the shadow, prune now */
if (adjust.subroutine != nullptr) adjust.subroutine = PruneTargetSpriteGroup(adjust.subroutine);
}
OptimiseVarAction2Adjust(va2_opt_state, feature, varsize, group, adjust);
@@ -6919,46 +6975,23 @@ static void NewSpriteGroup(ByteReader *buf)
}
group->default_group = GetGroupFromGroupID(setid, type, buf->ReadWord());
if (unlikely(shadow != nullptr)) {
ProcessDeterministicSpriteGroupRanges(ranges, shadow->ranges, group->default_group);
shadow->default_group = group->default_group;
/* Pruning was turned off so that the unpruned targets could be saved in the shadow ranges, prune now */
for (DeterministicSpriteGroupRange &range : ranges) {
range.group = PruneTargetSpriteGroup(range.group);
}
group->default_group = PruneTargetSpriteGroup(group->default_group);
}
group->error_group = ranges.size() > 0 ? ranges[0].group : group->default_group;
/* nvar == 0 is a special case -- we turn our value into a callback result */
group->calculated_result = ranges.size() == 0;
/* Sort ranges ascending. When ranges overlap, this may required clamping or splitting them */
std::vector<uint32> bounds;
for (uint i = 0; i < ranges.size(); i++) {
bounds.push_back(ranges[i].low);
if (ranges[i].high != UINT32_MAX) bounds.push_back(ranges[i].high + 1);
}
std::sort(bounds.begin(), bounds.end());
bounds.erase(std::unique(bounds.begin(), bounds.end()), bounds.end());
std::vector<const SpriteGroup *> target;
for (uint j = 0; j < bounds.size(); ++j) {
uint32 v = bounds[j];
const SpriteGroup *t = group->default_group;
for (uint i = 0; i < ranges.size(); i++) {
if (ranges[i].low <= v && v <= ranges[i].high) {
t = ranges[i].group;
break;
}
}
target.push_back(t);
}
assert(target.size() == bounds.size());
for (uint j = 0; j < bounds.size(); ) {
if (target[j] != group->default_group) {
DeterministicSpriteGroupRange &r = group->ranges.emplace_back();
r.group = target[j];
r.low = bounds[j];
while (j < bounds.size() && target[j] == r.group) {
j++;
}
r.high = j < bounds.size() ? bounds[j] - 1 : UINT32_MAX;
} else {
j++;
}
}
ProcessDeterministicSpriteGroupRanges(ranges, group->ranges, group->default_group);
OptimiseVarAction2DeterministicSpriteGroup(va2_opt_state, feature, varsize, group);
break;
@@ -6994,6 +7027,16 @@ static void NewSpriteGroup(ByteReader *buf)
group->groups.push_back(GetGroupFromGroupID(setid, type, buf->ReadWord()));
}
if (unlikely(HasBit(_misc_debug_flags, MDF_NEWGRF_SG_SAVE_RAW))) {
RandomizedSpriteGroupShadowCopy *shadow = &(_randomized_sg_shadows[group]);
shadow->groups = group->groups;
/* Pruning was turned off so that the unpruned targets could be saved in the shadow groups, prune now */
for (const SpriteGroup *&group : group->groups) {
group = PruneTargetSpriteGroup(group);
}
}
break;
}
@@ -11289,6 +11332,9 @@ void ResetNewGRFData()
InitializeSoundPool();
_spritegroup_pool.CleanPool();
_callback_result_cache.clear();
_deterministic_sg_shadows.clear();
_randomized_sg_shadows.clear();
_grfs_loaded_with_sg_shadow_enable = HasBit(_misc_debug_flags, MDF_NEWGRF_SG_SAVE_RAW);
}
/**