Add parallel analysis of unit invalidation using OpenMP.
This is ifdefed out by default, mail to wesnoth-dev to follow shortly
This commit is contained in:
parent
2e5c727b87
commit
6edcc85bc3
7 changed files with 112 additions and 56 deletions
|
@ -64,6 +64,7 @@ Version 1.9.4+svn:
|
|||
* Fixed a replay OOS issue caused by ToD areas defined outside of events
|
||||
(bug #17783).
|
||||
* Changed: when loading a file fails to open try with a .gz file.
|
||||
* Unit invalidation is processed in parallel using OpenMP
|
||||
|
||||
Version 1.9.4:
|
||||
* AI:
|
||||
|
|
|
@ -2416,6 +2416,9 @@ void display::invalidate_all()
|
|||
{
|
||||
DBG_DP << "invalidate_all()\n";
|
||||
invalidateAll_ = true;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp critical(invalidated_)
|
||||
#endif //_OPENMP
|
||||
invalidated_.clear();
|
||||
update_rect(map_area());
|
||||
}
|
||||
|
@ -2425,7 +2428,12 @@ bool display::invalidate(const map_location& loc)
|
|||
if(invalidateAll_)
|
||||
return false;
|
||||
|
||||
return invalidated_.insert(loc).second;
|
||||
bool tmp;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp critical(invalidated_)
|
||||
#endif //_OPENMP
|
||||
tmp = invalidated_.insert(loc).second;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool display::invalidate(const std::set<map_location>& locs)
|
||||
|
@ -2434,6 +2442,9 @@ bool display::invalidate(const std::set<map_location>& locs)
|
|||
return false;
|
||||
bool ret = false;
|
||||
foreach (const map_location& loc, locs) {
|
||||
#ifdef _OPENMP
|
||||
#pragma omp critical(invalidated_)
|
||||
#endif //_OPENMP
|
||||
ret = invalidated_.insert(loc).second || ret;
|
||||
}
|
||||
return ret;
|
||||
|
@ -2447,19 +2458,26 @@ bool display::propagate_invalidation(const std::set<map_location>& locs)
|
|||
if(locs.size()<=1)
|
||||
return false; // propagation never needed
|
||||
|
||||
// search the first hex invalidated (if any)
|
||||
std::set<map_location>::const_iterator i = locs.begin();
|
||||
for(; i != locs.end() && invalidated_.count(*i) == 0 ; ++i) {}
|
||||
bool result = false;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp critical(invalidated_)
|
||||
#endif //_OPENMP
|
||||
{
|
||||
// search the first hex invalidated (if any)
|
||||
std::set<map_location>::const_iterator i = locs.begin();
|
||||
for(; i != locs.end() && invalidated_.count(*i) == 0 ; ++i) {}
|
||||
|
||||
if (i == locs.end())
|
||||
return false; // no invalidation, don't propagate
|
||||
if (i != locs.end()) {
|
||||
|
||||
// propagate invalidation
|
||||
// 'i' is already in, but I suspect that splitting the range is bad
|
||||
// especially because locs are often adjacents
|
||||
size_t previous_size = invalidated_.size();
|
||||
invalidated_.insert(locs.begin(), locs.end());
|
||||
return previous_size < invalidated_.size();
|
||||
// propagate invalidation
|
||||
// 'i' is already in, but I suspect that splitting the range is bad
|
||||
// especially because locs are often adjacents
|
||||
size_t previous_size = invalidated_.size();
|
||||
invalidated_.insert(locs.begin(), locs.end());
|
||||
result = previous_size < invalidated_.size();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool display::invalidate_visible_locations_in_rect(const SDL_Rect& rect)
|
||||
|
|
|
@ -297,14 +297,6 @@ public:
|
|||
*/
|
||||
virtual void invalidate_animations_location(const map_location& /*loc*/) {}
|
||||
|
||||
/**
|
||||
* What hex are currently invalidated (read only)
|
||||
* used for some fine grained invalidation algorithm which need recurstion
|
||||
*/
|
||||
const std::set<map_location> & get_invalidated() const { return invalidated_; }
|
||||
|
||||
|
||||
|
||||
const gamemap& get_map() const { return *map_; }
|
||||
|
||||
/**
|
||||
|
|
|
@ -905,16 +905,23 @@ void game_display::invalidate_animations()
|
|||
foreach(unit* temp_unit, temp_units_) {
|
||||
temp_unit->refresh();
|
||||
}
|
||||
bool new_inval = true;
|
||||
while(new_inval) {
|
||||
new_inval = false;
|
||||
foreach (unit& u, units_) {
|
||||
new_inval |= u.invalidate(u.get_location());
|
||||
}
|
||||
foreach(unit* temp_unit, temp_units_) {
|
||||
new_inval |= temp_unit->invalidate(temp_unit->get_location());
|
||||
}
|
||||
std::vector<unit*> unit_list;
|
||||
foreach (unit &u, units_) {
|
||||
unit_list.push_back(&u);
|
||||
}
|
||||
foreach (unit *u, temp_units_) {
|
||||
unit_list.push_back(u);
|
||||
}
|
||||
bool new_inval;
|
||||
do {
|
||||
new_inval = false;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for reduction(|:new_inval) shared(unit_list) schedule(guided)
|
||||
#endif //_OPENMP
|
||||
for(unsigned int i=0; i < unit_list.size(); i++) {
|
||||
new_inval |= unit_list[i]->invalidate(unit_list[i]->get_location());
|
||||
}
|
||||
}while(new_inval);
|
||||
}
|
||||
|
||||
int& game_display::debug_highlight(const map_location& loc)
|
||||
|
|
|
@ -146,19 +146,24 @@ static int last_index_ = 0;
|
|||
|
||||
void flush_cache()
|
||||
{
|
||||
images_.flush();
|
||||
hexed_images_.flush();
|
||||
tod_colored_images_.flush();
|
||||
scaled_to_zoom_.flush();
|
||||
scaled_to_hex_images_.flush();
|
||||
brightened_images_.flush();
|
||||
semi_brightened_images_.flush();
|
||||
in_hex_info_.flush();
|
||||
mini_terrain_cache.clear();
|
||||
mini_fogged_terrain_cache.clear();
|
||||
reversed_images_.clear();
|
||||
image_existence_map.clear();
|
||||
precached_dirs.clear();
|
||||
#ifdef _OPENMP
|
||||
#pragma omp critical(image_cache)
|
||||
#endif //_OPENMP
|
||||
{
|
||||
images_.flush();
|
||||
hexed_images_.flush();
|
||||
tod_colored_images_.flush();
|
||||
scaled_to_zoom_.flush();
|
||||
scaled_to_hex_images_.flush();
|
||||
brightened_images_.flush();
|
||||
semi_brightened_images_.flush();
|
||||
in_hex_info_.flush();
|
||||
mini_terrain_cache.clear();
|
||||
mini_fogged_terrain_cache.clear();
|
||||
reversed_images_.clear();
|
||||
image_existence_map.clear();
|
||||
precached_dirs.clear();
|
||||
}
|
||||
/* We can't reset last_index_, since some locators are still alive
|
||||
when using :refresh. That would cause them to point to the wrong
|
||||
images. Not resetting the variable causes a memory leak, though. */
|
||||
|
@ -1080,8 +1085,20 @@ surface get_image(const image::locator& i_locator, TYPE type)
|
|||
}
|
||||
|
||||
// return the image if already cached
|
||||
if(i_locator.in_cache(*imap))
|
||||
return i_locator.locate_in_cache(*imap);
|
||||
bool tmp;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp critical(image_cache)
|
||||
#endif //_OPENMP
|
||||
tmp=i_locator.in_cache(*imap);
|
||||
|
||||
if(tmp) {
|
||||
surface result;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp critical(image_cache)
|
||||
#endif //_OPENMP
|
||||
result = i_locator.locate_in_cache(*imap);
|
||||
return result;
|
||||
}
|
||||
|
||||
// not cached, generate it
|
||||
switch(type) {
|
||||
|
@ -1115,6 +1132,9 @@ surface get_image(const image::locator& i_locator, TYPE type)
|
|||
if(res)
|
||||
res = create_optimized_surface(res);
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp critical(image_cache)
|
||||
#endif //_OPENMP
|
||||
i_locator.add_to_cache(*imap, res);
|
||||
|
||||
return res;
|
||||
|
@ -1128,8 +1148,13 @@ surface get_hexmask()
|
|||
|
||||
bool is_in_hex(const locator& i_locator)
|
||||
{
|
||||
bool result;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp critical(in_hex_info_)
|
||||
#endif //_OPENMP
|
||||
{
|
||||
if(i_locator.in_cache(in_hex_info_)) {
|
||||
return i_locator.locate_in_cache(in_hex_info_);
|
||||
result= i_locator.locate_in_cache(in_hex_info_);
|
||||
} else {
|
||||
const surface image(get_image(i_locator, UNSCALED));
|
||||
|
||||
|
@ -1140,8 +1165,10 @@ bool is_in_hex(const locator& i_locator)
|
|||
//std::cout << "in_hex : " << i_locator.get_filename()
|
||||
// << " " << (res ? "yes" : "no") << "\n";
|
||||
|
||||
return res;
|
||||
result= res;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1996,7 +1996,7 @@ bool unit::invalidate(const map_location &loc)
|
|||
// Very early calls, anim not initialized yet
|
||||
if(get_animation()) {
|
||||
frame_parameters params;
|
||||
game_display * disp = game_display::get_singleton();
|
||||
const game_display * disp = game_display::get_singleton();
|
||||
const gamemap & map = disp->get_map();
|
||||
const t_translation::t_terrain terrain = map.get_terrain(loc);
|
||||
const terrain_type& terrain_info = map.get_terrain_info(terrain);
|
||||
|
|
|
@ -663,13 +663,24 @@ std::set<map_location> unit_frame::get_overlaped_hex(const int frame_time,const
|
|||
result.insert(src.get_direction(map_location::SOUTH_WEST));
|
||||
}
|
||||
} else {
|
||||
surface image;
|
||||
if(!image_loc.is_void() && image_loc.get_filename() != "") { // invalid diag image, or not diagonal
|
||||
image=image::get_image(image_loc,
|
||||
image::SCALED_TO_ZOOM
|
||||
);
|
||||
int w=0;
|
||||
int h =0;
|
||||
#ifdef _OPENMP
|
||||
#pragma omp critical(frame_surface) // with the way surfaces work it's hard to lock the refcount within sdl_utils
|
||||
#endif //_OPENMP
|
||||
{
|
||||
surface image;
|
||||
if(!image_loc.is_void() && image_loc.get_filename() != "") { // invalid diag image, or not diagonal
|
||||
image=image::get_image(image_loc,
|
||||
image::SCALED_TO_ZOOM
|
||||
);
|
||||
}
|
||||
if(image != NULL) {
|
||||
w = image->w;
|
||||
h = image->h;
|
||||
}
|
||||
}
|
||||
if (image != NULL) {
|
||||
if (w != 0 || h != 0) {
|
||||
const int x = static_cast<int>(tmp_offset * xdst + (1.0-tmp_offset) * xsrc);
|
||||
const int y = static_cast<int>(tmp_offset * ydst + (1.0-tmp_offset) * ysrc);
|
||||
#ifdef LOW_MEM
|
||||
|
@ -680,8 +691,8 @@ std::set<map_location> unit_frame::get_overlaped_hex(const int frame_time,const
|
|||
bool facing_north = direction == map_location::NORTH_WEST || direction == map_location::NORTH || direction == map_location::NORTH_EAST;
|
||||
if(!current_data.auto_vflip) facing_north = true;
|
||||
if(!current_data.auto_hflip) facing_west = false;
|
||||
int my_x = x +current_data.x+d2- image->w/2;
|
||||
int my_y = y +current_data.y+d2- image->h/2;
|
||||
int my_x = x +current_data.x+d2- w/2;
|
||||
int my_y = y +current_data.y+d2- h/2;
|
||||
if(facing_west) {
|
||||
my_x += current_data.directional_x;
|
||||
} else {
|
||||
|
@ -693,7 +704,7 @@ std::set<map_location> unit_frame::get_overlaped_hex(const int frame_time,const
|
|||
my_y -= current_data.directional_y;
|
||||
}
|
||||
|
||||
const SDL_Rect r = create_rect(my_x, my_y, image->w, image->h);
|
||||
const SDL_Rect r = create_rect(my_x, my_y, w, h);
|
||||
// check if our underlying hexes are invalidated
|
||||
// if we need to update ourselve because we changed, invalidate our hexes
|
||||
// and return whether or not our hexs was invalidated
|
||||
|
|
Loading…
Add table
Reference in a new issue