Cache the result of GetImage() in Vehicle::UpdateViewport() where possible.
Sprite number is not cached if callback is made, or a variable access outside a whitelist occurs. Invalidate cached sprite number when direction or cargo changes, or vehicle is marked dirty.
This commit is contained in:
@@ -1293,6 +1293,7 @@ TileIndex Aircraft::GetOrderStationLocation(StationID station)
|
|||||||
void Aircraft::MarkDirty()
|
void Aircraft::MarkDirty()
|
||||||
{
|
{
|
||||||
this->colourmap = PAL_NONE;
|
this->colourmap = PAL_NONE;
|
||||||
|
this->cur_image_valid_dir = INVALID_DIR;
|
||||||
this->UpdateViewport(true, false);
|
this->UpdateViewport(true, false);
|
||||||
if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this, EIT_ON_MAP);
|
if (this->subtype == AIR_HELICOPTER) this->Next()->Next()->cur_image = GetRotorImage(this, EIT_ON_MAP);
|
||||||
}
|
}
|
||||||
|
@@ -186,6 +186,7 @@ void DisasterVehicle::UpdatePosition(int x, int y, int z)
|
|||||||
this->z_pos = z;
|
this->z_pos = z;
|
||||||
this->tile = TileVirtXY(x, y);
|
this->tile = TileVirtXY(x, y);
|
||||||
|
|
||||||
|
this->cur_image_valid_dir = INVALID_DIR;
|
||||||
this->UpdateImage();
|
this->UpdateImage();
|
||||||
this->UpdatePositionAndViewport();
|
this->UpdatePositionAndViewport();
|
||||||
|
|
||||||
@@ -199,6 +200,7 @@ void DisasterVehicle::UpdatePosition(int x, int y, int z)
|
|||||||
safe_y = Clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
|
safe_y = Clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
|
||||||
u->z_pos = GetSlopePixelZ(safe_x, safe_y);
|
u->z_pos = GetSlopePixelZ(safe_x, safe_y);
|
||||||
u->direction = this->direction;
|
u->direction = this->direction;
|
||||||
|
u->cur_image_valid_dir = INVALID_DIR;
|
||||||
|
|
||||||
u->UpdateImage();
|
u->UpdateImage();
|
||||||
u->UpdatePositionAndViewport();
|
u->UpdatePositionAndViewport();
|
||||||
|
@@ -108,6 +108,7 @@ void GroundVehicle<T, Type>::CargoChanged()
|
|||||||
weight += current_weight;
|
weight += current_weight;
|
||||||
/* Slope steepness is in percent, result in N. */
|
/* Slope steepness is in percent, result in N. */
|
||||||
u->gcache.cached_slope_resistance = current_weight * u->GetSlopeSteepness() * 100;
|
u->gcache.cached_slope_resistance = current_weight * u->GetSlopeSteepness() * 100;
|
||||||
|
u->cur_image_valid_dir = INVALID_DIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Store consist weight in cache. */
|
/* Store consist weight in cache. */
|
||||||
|
@@ -237,6 +237,8 @@ static U EvalAdjustT(const DeterministicSpriteGroupAdjust *adjust, ScopeResolver
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _sprite_group_resolve_check_veh_enable = false;
|
||||||
|
bool _sprite_group_resolve_check_veh_result = false;
|
||||||
|
|
||||||
const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) const
|
const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) const
|
||||||
{
|
{
|
||||||
@@ -252,6 +254,7 @@ const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) con
|
|||||||
/* Try to get the variable. We shall assume it is available, unless told otherwise. */
|
/* Try to get the variable. We shall assume it is available, unless told otherwise. */
|
||||||
bool available = true;
|
bool available = true;
|
||||||
if (adjust->variable == 0x7E) {
|
if (adjust->variable == 0x7E) {
|
||||||
|
_sprite_group_resolve_check_veh_result = false;
|
||||||
const SpriteGroup *subgroup = SpriteGroup::Resolve(adjust->subroutine, object, false);
|
const SpriteGroup *subgroup = SpriteGroup::Resolve(adjust->subroutine, object, false);
|
||||||
if (subgroup == NULL) {
|
if (subgroup == NULL) {
|
||||||
value = CALLBACK_FAILED;
|
value = CALLBACK_FAILED;
|
||||||
@@ -261,8 +264,49 @@ const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) con
|
|||||||
|
|
||||||
/* Note: 'last_value' and 'reseed' are shared between the main chain and the procedure */
|
/* Note: 'last_value' and 'reseed' are shared between the main chain and the procedure */
|
||||||
} else if (adjust->variable == 0x7B) {
|
} else if (adjust->variable == 0x7B) {
|
||||||
|
_sprite_group_resolve_check_veh_result = false;
|
||||||
value = GetVariable(object, scope, adjust->parameter, last_value, &available);
|
value = GetVariable(object, scope, adjust->parameter, last_value, &available);
|
||||||
} else {
|
} else {
|
||||||
|
if (_sprite_group_resolve_check_veh_enable) {
|
||||||
|
switch (adjust->variable) {
|
||||||
|
// whitelist of variables which can be checked without requiring an immediate re-check on the next tick
|
||||||
|
case 0xC:
|
||||||
|
case 0x1A:
|
||||||
|
case 0x1C:
|
||||||
|
case 0x25:
|
||||||
|
case 0x40:
|
||||||
|
case 0x41:
|
||||||
|
case 0x42:
|
||||||
|
case 0x47:
|
||||||
|
case 0x49:
|
||||||
|
case 0x4B:
|
||||||
|
case 0x4D:
|
||||||
|
case 0x60:
|
||||||
|
case 0x7D:
|
||||||
|
case 0x7F:
|
||||||
|
case 0x80 + 0x0:
|
||||||
|
case 0x80 + 0x1:
|
||||||
|
case 0x80 + 0x4:
|
||||||
|
case 0x80 + 0x5:
|
||||||
|
case 0x80 + 0x39:
|
||||||
|
case 0x80 + 0x3A:
|
||||||
|
case 0x80 + 0x3B:
|
||||||
|
case 0x80 + 0x3C:
|
||||||
|
case 0x80 + 0x3D:
|
||||||
|
case 0x80 + 0x44:
|
||||||
|
case 0x80 + 0x45:
|
||||||
|
case 0x80 + 0x46:
|
||||||
|
case 0x80 + 0x47:
|
||||||
|
case 0x80 + 0x5A:
|
||||||
|
case 0x80 + 0x72:
|
||||||
|
case 0x80 + 0x7A:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_sprite_group_resolve_check_veh_result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
value = GetVariable(object, scope, adjust->variable, adjust->parameter, &available);
|
value = GetVariable(object, scope, adjust->variable, adjust->parameter, &available);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -408,6 +408,7 @@ void RoadVehicle::MarkDirty()
|
|||||||
{
|
{
|
||||||
for (RoadVehicle *v = this; v != NULL; v = v->Next()) {
|
for (RoadVehicle *v = this; v != NULL; v = v->Next()) {
|
||||||
v->colourmap = PAL_NONE;
|
v->colourmap = PAL_NONE;
|
||||||
|
v->cur_image_valid_dir = INVALID_DIR;
|
||||||
v->UpdateViewport(true, false);
|
v->UpdateViewport(true, false);
|
||||||
}
|
}
|
||||||
this->CargoChanged();
|
this->CargoChanged();
|
||||||
|
@@ -259,6 +259,7 @@ Trackdir Ship::GetVehicleTrackdir() const
|
|||||||
void Ship::MarkDirty()
|
void Ship::MarkDirty()
|
||||||
{
|
{
|
||||||
this->colourmap = PAL_NONE;
|
this->colourmap = PAL_NONE;
|
||||||
|
this->cur_image_valid_dir = INVALID_DIR;
|
||||||
this->UpdateViewport(true, false);
|
this->UpdateViewport(true, false);
|
||||||
this->UpdateCache();
|
this->UpdateCache();
|
||||||
}
|
}
|
||||||
|
@@ -1638,6 +1638,8 @@ static void SwapTrainFlags(uint16 *swap_flag1, uint16 *swap_flag2)
|
|||||||
*/
|
*/
|
||||||
static void UpdateStatusAfterSwap(Train *v)
|
static void UpdateStatusAfterSwap(Train *v)
|
||||||
{
|
{
|
||||||
|
v->cur_image_valid_dir = INVALID_DIR;
|
||||||
|
|
||||||
/* Reverse the direction. */
|
/* Reverse the direction. */
|
||||||
if (v->track != TRACK_BIT_DEPOT) v->direction = ReverseDir(v->direction);
|
if (v->track != TRACK_BIT_DEPOT) v->direction = ReverseDir(v->direction);
|
||||||
|
|
||||||
@@ -3052,6 +3054,7 @@ void Train::MarkDirty()
|
|||||||
Train *v = this;
|
Train *v = this;
|
||||||
do {
|
do {
|
||||||
v->colourmap = PAL_NONE;
|
v->colourmap = PAL_NONE;
|
||||||
|
v->cur_image_valid_dir = INVALID_DIR;
|
||||||
v->UpdateViewport(true, false);
|
v->UpdateViewport(true, false);
|
||||||
} while ((v = v->Next()) != NULL);
|
} while ((v = v->Next()) != NULL);
|
||||||
|
|
||||||
|
@@ -367,6 +367,7 @@ Vehicle::Vehicle(VehicleType type)
|
|||||||
this->cargo_age_counter = 1;
|
this->cargo_age_counter = 1;
|
||||||
this->last_station_visited = INVALID_STATION;
|
this->last_station_visited = INVALID_STATION;
|
||||||
this->last_loading_station = INVALID_STATION;
|
this->last_loading_station = INVALID_STATION;
|
||||||
|
this->cur_image_valid_dir = INVALID_DIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -291,6 +291,7 @@ public:
|
|||||||
uint16 load_unload_ticks; ///< Ticks to wait before starting next cycle.
|
uint16 load_unload_ticks; ///< Ticks to wait before starting next cycle.
|
||||||
GroupID group_id; ///< Index of group Pool array
|
GroupID group_id; ///< Index of group Pool array
|
||||||
byte subtype; ///< subtype (Filled with values from #EffectVehicles/#TrainSubTypes/#AircraftSubTypes)
|
byte subtype; ///< subtype (Filled with values from #EffectVehicles/#TrainSubTypes/#AircraftSubTypes)
|
||||||
|
DirectionByte cur_image_valid_dir; ///< NOSAVE: direction for which cur_image does not need to be regenerated on the next tick
|
||||||
|
|
||||||
NewGRFCache grf_cache; ///< Cache of often used calculated NewGRF values
|
NewGRFCache grf_cache; ///< Cache of often used calculated NewGRF values
|
||||||
VehicleCache vcache; ///< Cache of often used vehicle values.
|
VehicleCache vcache; ///< Cache of often used vehicle values.
|
||||||
@@ -1158,11 +1159,20 @@ struct SpecializedVehicle : public Vehicle {
|
|||||||
/* Skip updating sprites on dedicated servers without screen */
|
/* Skip updating sprites on dedicated servers without screen */
|
||||||
if (_network_dedicated) return;
|
if (_network_dedicated) return;
|
||||||
|
|
||||||
|
extern bool _sprite_group_resolve_check_veh_enable;
|
||||||
|
extern bool _sprite_group_resolve_check_veh_result;
|
||||||
|
|
||||||
/* Explicitly choose method to call to prevent vtable dereference -
|
/* Explicitly choose method to call to prevent vtable dereference -
|
||||||
* it gives ~3% runtime improvements in games with many vehicles */
|
* it gives ~3% runtime improvements in games with many vehicles */
|
||||||
if (update_delta) ((T *)this)->T::UpdateDeltaXY(this->direction);
|
if (update_delta) ((T *)this)->T::UpdateDeltaXY(this->direction);
|
||||||
SpriteID old_image = this->cur_image;
|
SpriteID old_image = this->cur_image;
|
||||||
this->cur_image = ((T *)this)->T::GetImage(this->direction, EIT_ON_MAP);
|
if (this->cur_image_valid_dir != this->direction) {
|
||||||
|
_sprite_group_resolve_check_veh_enable = true;
|
||||||
|
_sprite_group_resolve_check_veh_result = true;
|
||||||
|
this->cur_image = ((T *)this)->T::GetImage(this->direction, EIT_ON_MAP);
|
||||||
|
this->cur_image_valid_dir = _sprite_group_resolve_check_veh_result ? this->direction : INVALID_DIR;
|
||||||
|
_sprite_group_resolve_check_veh_enable = false;
|
||||||
|
}
|
||||||
if (force_update || this->cur_image != old_image) this->Vehicle::UpdateViewport(true);
|
if (force_update || this->cur_image != old_image) this->Vehicle::UpdateViewport(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user