mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-26 14:39:58 +01:00
Micro-optimize icon smoothing subsystem, cutting down more than 50% of its init time (about .8s drop on local, more on prod) (#69741)
With atoms now being 50% of the init time instead of ~80%, I've decided to poke around other subsystems.
Unfortunately they're not straight forward at all and extremely boring. bitmask_smooth() in particular is just a big proc that is called ~60k times, so I made some adjustments to its macro to reduce ops.
I removed code that looped over two entire Z-levels to find things to smooth, added by e2dd404, at a time before the initialize system. This doesn't have huge gains since it just defers to the queue anyway, but it still shaved off 0.1-0.2s on local.
I removed update_appearance(~UPDATE_SMOOTHING) from something since the person who added it doesn't remember why and it doesn't appear to do anything. Lemon thinks it's something to do with emissives, but I tested with neon carpet and it seemed to work fine.
This commit is contained in:
@@ -54,45 +54,6 @@ DEFINE_BITFIELD(smoothing_junction, list(
|
||||
#define DEFAULT_UNDERLAY_ICON_STATE "plating"
|
||||
|
||||
|
||||
#define SET_ADJ_IN_DIR(source, junction, direction, direction_flag) \
|
||||
do { \
|
||||
var/turf/neighbor = get_step(source, direction); \
|
||||
if(!neighbor) { \
|
||||
if(source.smoothing_flags & SMOOTH_BORDER) { \
|
||||
junction |= direction_flag; \
|
||||
}; \
|
||||
}; \
|
||||
else { \
|
||||
if(!isnull(neighbor.smoothing_groups)) { \
|
||||
for(var/target in source.canSmoothWith) { \
|
||||
if(!(source.canSmoothWith[target] & neighbor.smoothing_groups[target])) { \
|
||||
continue; \
|
||||
}; \
|
||||
junction |= direction_flag; \
|
||||
break; \
|
||||
}; \
|
||||
}; \
|
||||
if(!(junction & direction_flag) && source.smoothing_flags & SMOOTH_OBJ) { \
|
||||
for(var/obj/thing in neighbor) { \
|
||||
if(!thing.anchored || isnull(thing.smoothing_groups)) { \
|
||||
continue; \
|
||||
}; \
|
||||
for(var/target in source.canSmoothWith) { \
|
||||
if(!(source.canSmoothWith[target] & thing.smoothing_groups[target])) { \
|
||||
continue; \
|
||||
}; \
|
||||
junction |= direction_flag; \
|
||||
break; \
|
||||
}; \
|
||||
if(junction & direction_flag) { \
|
||||
break; \
|
||||
}; \
|
||||
}; \
|
||||
}; \
|
||||
}; \
|
||||
} while(FALSE)
|
||||
|
||||
|
||||
///Scans all adjacent turfs to find targets to smooth with.
|
||||
/atom/proc/calculate_adjacencies()
|
||||
. = NONE
|
||||
@@ -165,8 +126,6 @@ DEFINE_BITFIELD(smoothing_junction, list(
|
||||
else
|
||||
CRASH("smooth_icon called for [src] with smoothing_flags == [smoothing_flags]")
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_SMOOTHED_ICON)
|
||||
update_appearance(~UPDATE_SMOOTHING)
|
||||
|
||||
|
||||
/atom/proc/corners_diagonal_smooth(adjacencies)
|
||||
switch(adjacencies)
|
||||
@@ -319,7 +278,6 @@ DEFINE_BITFIELD(smoothing_junction, list(
|
||||
|
||||
return NO_ADJ_FOUND
|
||||
|
||||
|
||||
/**
|
||||
* Basic smoothing proc. The atom checks for adjacent directions to smooth with and changes the icon_state based on that.
|
||||
*
|
||||
@@ -329,8 +287,48 @@ DEFINE_BITFIELD(smoothing_junction, list(
|
||||
/atom/proc/bitmask_smooth()
|
||||
var/new_junction = NONE
|
||||
|
||||
// cache for sanic speed
|
||||
var/canSmoothWith = src.canSmoothWith
|
||||
|
||||
var/smooth_border = (smoothing_flags & SMOOTH_BORDER)
|
||||
var/smooth_obj = (smoothing_flags & SMOOTH_OBJ)
|
||||
|
||||
#define SET_ADJ_IN_DIR(direction, direction_flag) \
|
||||
set_adj_in_dir: { \
|
||||
do { \
|
||||
var/turf/neighbor = get_step(src, direction); \
|
||||
if(neighbor) { \
|
||||
var/neighbor_smoothing_groups = neighbor.smoothing_groups; \
|
||||
if(neighbor_smoothing_groups) { \
|
||||
for(var/target in canSmoothWith) { \
|
||||
if(canSmoothWith[target] & neighbor_smoothing_groups[target]) { \
|
||||
new_junction |= direction_flag; \
|
||||
break set_adj_in_dir; \
|
||||
}; \
|
||||
}; \
|
||||
}; \
|
||||
if(smooth_obj) { \
|
||||
for(var/atom/movable/thing as anything in neighbor) { \
|
||||
var/thing_smoothing_groups = thing.smoothing_groups; \
|
||||
if(!thing.anchored || isnull(thing_smoothing_groups)) { \
|
||||
continue; \
|
||||
}; \
|
||||
for(var/target in canSmoothWith) { \
|
||||
if(canSmoothWith[target] & thing_smoothing_groups[target]) { \
|
||||
new_junction |= direction_flag; \
|
||||
break set_adj_in_dir; \
|
||||
}; \
|
||||
}; \
|
||||
}; \
|
||||
}; \
|
||||
} else if (smooth_border) { \
|
||||
new_junction |= direction_flag; \
|
||||
}; \
|
||||
} while(FALSE) \
|
||||
}
|
||||
|
||||
for(var/direction in GLOB.cardinals) //Cardinal case first.
|
||||
SET_ADJ_IN_DIR(src, new_junction, direction, direction)
|
||||
SET_ADJ_IN_DIR(direction, direction)
|
||||
|
||||
if(!(new_junction & (NORTH|SOUTH)) || !(new_junction & (EAST|WEST)))
|
||||
set_smoothed_icon_state(new_junction)
|
||||
@@ -338,20 +336,22 @@ DEFINE_BITFIELD(smoothing_junction, list(
|
||||
|
||||
if(new_junction & NORTH_JUNCTION)
|
||||
if(new_junction & WEST_JUNCTION)
|
||||
SET_ADJ_IN_DIR(src, new_junction, NORTHWEST, NORTHWEST_JUNCTION)
|
||||
SET_ADJ_IN_DIR(NORTHWEST, NORTHWEST_JUNCTION)
|
||||
|
||||
if(new_junction & EAST_JUNCTION)
|
||||
SET_ADJ_IN_DIR(src, new_junction, NORTHEAST, NORTHEAST_JUNCTION)
|
||||
SET_ADJ_IN_DIR(NORTHEAST, NORTHEAST_JUNCTION)
|
||||
|
||||
if(new_junction & SOUTH_JUNCTION)
|
||||
if(new_junction & WEST_JUNCTION)
|
||||
SET_ADJ_IN_DIR(src, new_junction, SOUTHWEST, SOUTHWEST_JUNCTION)
|
||||
SET_ADJ_IN_DIR(SOUTHWEST, SOUTHWEST_JUNCTION)
|
||||
|
||||
if(new_junction & EAST_JUNCTION)
|
||||
SET_ADJ_IN_DIR(src, new_junction, SOUTHEAST, SOUTHEAST_JUNCTION)
|
||||
SET_ADJ_IN_DIR(SOUTHEAST, SOUTHEAST_JUNCTION)
|
||||
|
||||
set_smoothed_icon_state(new_junction)
|
||||
|
||||
#undef SET_ADJ_IN_DIR
|
||||
|
||||
|
||||
///Changes the icon state based on the new junction bitmask. Returns the old junction value.
|
||||
/atom/proc/set_smoothed_icon_state(new_junction)
|
||||
@@ -361,36 +361,46 @@ DEFINE_BITFIELD(smoothing_junction, list(
|
||||
|
||||
|
||||
/turf/closed/set_smoothed_icon_state(new_junction)
|
||||
. = ..()
|
||||
if(smoothing_flags & SMOOTH_DIAGONAL_CORNERS)
|
||||
switch(new_junction)
|
||||
if(
|
||||
NORTH_JUNCTION|WEST_JUNCTION,
|
||||
NORTH_JUNCTION|EAST_JUNCTION,
|
||||
SOUTH_JUNCTION|WEST_JUNCTION,
|
||||
SOUTH_JUNCTION|EAST_JUNCTION,
|
||||
NORTH_JUNCTION|WEST_JUNCTION|NORTHWEST_JUNCTION,
|
||||
NORTH_JUNCTION|EAST_JUNCTION|NORTHEAST_JUNCTION,
|
||||
SOUTH_JUNCTION|WEST_JUNCTION|SOUTHWEST_JUNCTION,
|
||||
SOUTH_JUNCTION|EAST_JUNCTION|SOUTHEAST_JUNCTION
|
||||
)
|
||||
icon_state = "[base_icon_state]-[smoothing_junction]-d"
|
||||
if(!fixed_underlay && new_junction != .) // Mutable underlays?
|
||||
var/junction_dir = reverse_ndir(smoothing_junction)
|
||||
var/turned_adjacency = REVERSE_DIR(junction_dir)
|
||||
var/turf/neighbor_turf = get_step(src, turned_adjacency & (NORTH|SOUTH))
|
||||
var/mutable_appearance/underlay_appearance = mutable_appearance(layer = TURF_LAYER, offset_spokesman = src, plane = FLOOR_PLANE)
|
||||
// Avoid calling ..() here to avoid setting icon_state twice, which is expensive given how hot this proc is
|
||||
. = smoothing_junction
|
||||
smoothing_junction = new_junction
|
||||
|
||||
if (!(smoothing_flags & SMOOTH_DIAGONAL_CORNERS))
|
||||
icon_state = "[base_icon_state]-[smoothing_junction]"
|
||||
return .
|
||||
|
||||
switch(new_junction)
|
||||
if(
|
||||
NORTH_JUNCTION|WEST_JUNCTION,
|
||||
NORTH_JUNCTION|EAST_JUNCTION,
|
||||
SOUTH_JUNCTION|WEST_JUNCTION,
|
||||
SOUTH_JUNCTION|EAST_JUNCTION,
|
||||
NORTH_JUNCTION|WEST_JUNCTION|NORTHWEST_JUNCTION,
|
||||
NORTH_JUNCTION|EAST_JUNCTION|NORTHEAST_JUNCTION,
|
||||
SOUTH_JUNCTION|WEST_JUNCTION|SOUTHWEST_JUNCTION,
|
||||
SOUTH_JUNCTION|EAST_JUNCTION|SOUTHEAST_JUNCTION,
|
||||
)
|
||||
icon_state = "[base_icon_state]-[smoothing_junction]-d"
|
||||
if(new_junction == . || fixed_underlay) // Mutable underlays?
|
||||
return .
|
||||
|
||||
var/junction_dir = reverse_ndir(smoothing_junction)
|
||||
var/turned_adjacency = REVERSE_DIR(junction_dir)
|
||||
var/turf/neighbor_turf = get_step(src, turned_adjacency & (NORTH|SOUTH))
|
||||
var/mutable_appearance/underlay_appearance = mutable_appearance(layer = TURF_LAYER, offset_spokesman = src, plane = FLOOR_PLANE)
|
||||
if(!neighbor_turf.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
|
||||
neighbor_turf = get_step(src, turned_adjacency & (EAST|WEST))
|
||||
|
||||
if(!neighbor_turf.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
|
||||
neighbor_turf = get_step(src, turned_adjacency)
|
||||
|
||||
if(!neighbor_turf.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
|
||||
neighbor_turf = get_step(src, turned_adjacency & (EAST|WEST))
|
||||
|
||||
if(!neighbor_turf.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
|
||||
neighbor_turf = get_step(src, turned_adjacency)
|
||||
|
||||
if(!neighbor_turf.get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency))
|
||||
if(!get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency)) //if all else fails, ask our own turf
|
||||
underlay_appearance.icon = DEFAULT_UNDERLAY_ICON
|
||||
underlay_appearance.icon_state = DEFAULT_UNDERLAY_ICON_STATE
|
||||
underlays += underlay_appearance
|
||||
if(!get_smooth_underlay_icon(underlay_appearance, src, turned_adjacency)) //if all else fails, ask our own turf
|
||||
underlay_appearance.icon = DEFAULT_UNDERLAY_ICON
|
||||
underlay_appearance.icon_state = DEFAULT_UNDERLAY_ICON_STATE
|
||||
underlays += underlay_appearance
|
||||
else
|
||||
icon_state = "[base_icon_state]-[smoothing_junction]"
|
||||
|
||||
/turf/open/floor/set_smoothed_icon_state(new_junction)
|
||||
if(broken || burnt)
|
||||
@@ -521,5 +531,3 @@ DEFINE_BITFIELD(smoothing_junction, list(
|
||||
|
||||
#undef DEFAULT_UNDERLAY_ICON
|
||||
#undef DEFAULT_UNDERLAY_ICON_STATE
|
||||
|
||||
#undef SET_ADJ_IN_DIR
|
||||
|
||||
@@ -32,16 +32,13 @@ SUBSYSTEM_DEF(icon_smooth)
|
||||
can_fire = FALSE
|
||||
|
||||
/datum/controller/subsystem/icon_smooth/Initialize()
|
||||
smooth_zlevel(1, TRUE)
|
||||
smooth_zlevel(2, TRUE)
|
||||
|
||||
var/list/queue = smooth_queue
|
||||
smooth_queue = list()
|
||||
|
||||
while(length(queue))
|
||||
var/atom/smoothing_atom = queue[length(queue)]
|
||||
queue.len--
|
||||
if(QDELETED(smoothing_atom) || !(smoothing_atom.smoothing_flags & SMOOTH_QUEUED) || smoothing_atom.z <= 2)
|
||||
if(QDELETED(smoothing_atom) || !(smoothing_atom.smoothing_flags & SMOOTH_QUEUED) || !smoothing_atom.z)
|
||||
continue
|
||||
smoothing_atom.smooth_icon()
|
||||
CHECK_TICK
|
||||
|
||||
Reference in New Issue
Block a user