switch from std::any to class hierarchy for content_stats_t

Fixes bogus (huge integers) content stats reporting on macOS (also fix tjunc stats reporting)

having the non-copyable std::atomic<size_t> inside a std::any which must
be copyable was problematic

IMO this is slightly better because it lets us use non-copyable types
This commit is contained in:
Eric Wasylishen 2022-07-18 20:13:33 -06:00
parent b6153e3084
commit 6025585f01
5 changed files with 29 additions and 31 deletions

View File

@ -559,7 +559,7 @@ public:
} }
private: private:
struct content_stats_t struct content_stats_t : public content_stats_base_t
{ {
std::atomic<size_t> solid; std::atomic<size_t> solid;
std::atomic<size_t> empty; std::atomic<size_t> empty;
@ -569,20 +569,17 @@ private:
std::atomic<size_t> detail_fence; std::atomic<size_t> detail_fence;
std::atomic<size_t> sky; std::atomic<size_t> sky;
std::atomic<size_t> illusionary_visblocker; std::atomic<size_t> illusionary_visblocker;
content_stats_t() = default;
inline content_stats_t(const content_stats_t &copy) { }
}; };
public: public:
std::any create_content_stats() const override std::unique_ptr<content_stats_base_t> create_content_stats() const override
{ {
return content_stats_t{}; return std::unique_ptr<content_stats_base_t>(new content_stats_t{});
} }
void count_contents_in_stats(const contentflags_t &contents, std::any &stats_any) const override void count_contents_in_stats(const contentflags_t &contents, content_stats_base_t &stats_any) const override
{ {
content_stats_t &stats = std::any_cast<content_stats_t &>(stats_any); content_stats_t &stats = dynamic_cast<content_stats_t &>(stats_any);
if (contents_are_solid(contents)) { if (contents_are_solid(contents)) {
stats.solid++; stats.solid++;
@ -603,9 +600,9 @@ public:
} }
} }
void print_content_stats(const std::any &stats_any, const char *what) const override void print_content_stats(const content_stats_base_t &stats_any, const char *what) const override
{ {
const content_stats_t &stats = std::any_cast<const content_stats_t &>(stats_any); const content_stats_t &stats = dynamic_cast<const content_stats_t &>(stats_any);
if (stats.empty) { if (stats.empty) {
logging::print(logging::flag::STAT, " {:8} empty {}\n", stats.empty, what); logging::print(logging::flag::STAT, " {:8} empty {}\n", stats.empty, what);
@ -1281,26 +1278,23 @@ public:
} }
private: private:
struct content_stats_t struct content_stats_t : public content_stats_base_t
{ {
//std::array<std::atomic<size_t>, 32> native_types; //std::array<std::atomic<size_t>, 32> native_types;
std::unordered_map<int32_t, size_t> native_types; std::unordered_map<int32_t, size_t> native_types;
std::atomic<size_t> total_brushes; std::atomic<size_t> total_brushes;
std::atomic<size_t> visblocker_brushes; std::atomic<size_t> visblocker_brushes;
content_stats_t() = default;
inline content_stats_t(const content_stats_t &copy) { }
}; };
public: public:
std::any create_content_stats() const override std::unique_ptr<content_stats_base_t> create_content_stats() const override
{ {
return content_stats_t{}; return std::unique_ptr<content_stats_base_t>(new content_stats_t{});
} }
void count_contents_in_stats(const contentflags_t &contents, std::any &stats_any) const override void count_contents_in_stats(const contentflags_t &contents, content_stats_base_t &stats_any) const override
{ {
content_stats_t &stats = std::any_cast<content_stats_t &>(stats_any); content_stats_t &stats = dynamic_cast<content_stats_t &>(stats_any);
/*for (int32_t i = 0; i < 32; i++) { /*for (int32_t i = 0; i < 32; i++) {
if (contents.native & nth_bit(i)) { if (contents.native & nth_bit(i)) {
@ -1320,9 +1314,9 @@ public:
stats.total_brushes++; stats.total_brushes++;
} }
void print_content_stats(const std::any &stats_any, const char *what) const override void print_content_stats(const content_stats_base_t &stats_any, const char *what) const override
{ {
const content_stats_t &stats = std::any_cast<const content_stats_t &>(stats_any); const content_stats_t &stats = dynamic_cast<const content_stats_t &>(stats_any);
/*for (int32_t i = 0; i < 32; i++) { /*for (int32_t i = 0; i < 32; i++) {
if (stats.native_types[i]) { if (stats.native_types[i]) {

View File

@ -233,6 +233,10 @@ enum gameid_t
GAME_TOTAL GAME_TOTAL
}; };
struct content_stats_base_t {
virtual ~content_stats_base_t() = default;
};
// Game definition, which contains data specific to // Game definition, which contains data specific to
// the game a BSP version is being compiled for. // the game a BSP version is being compiled for.
struct gamedef_t struct gamedef_t
@ -304,9 +308,9 @@ struct gamedef_t
const std::string &texname, const surfflags_t &flags, const contentflags_t &contents) const = 0; const std::string &texname, const surfflags_t &flags, const contentflags_t &contents) const = 0;
virtual void init_filesystem(const fs::path &source, const settings::common_settings &settings) const = 0; virtual void init_filesystem(const fs::path &source, const settings::common_settings &settings) const = 0;
virtual const std::vector<qvec3b> &get_default_palette() const = 0; virtual const std::vector<qvec3b> &get_default_palette() const = 0;
virtual std::any create_content_stats() const = 0; virtual std::unique_ptr<content_stats_base_t> create_content_stats() const = 0;
virtual void count_contents_in_stats(const contentflags_t &contents, std::any &stats) const = 0; virtual void count_contents_in_stats(const contentflags_t &contents, content_stats_base_t &stats) const = 0;
virtual void print_content_stats(const std::any &stats, const char *what) const = 0; virtual void print_content_stats(const content_stats_base_t &stats, const char *what) const = 0;
}; };
// Lump specification; stores the name and size // Lump specification; stores the name and size

View File

@ -841,7 +841,7 @@ std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, const mapbrush_t *ma
//============================================================================= //=============================================================================
static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum, std::any &stats) static void Brush_LoadEntity(mapentity_t *dst, const mapentity_t *src, const int hullnum, content_stats_base_t &stats)
{ {
const mapbrush_t *mapbrush; const mapbrush_t *mapbrush;
qvec3d rotate_offset{}; qvec3d rotate_offset{};
@ -1063,9 +1063,9 @@ hullnum 0 does not contain clip brushes.
*/ */
void Brush_LoadEntity(mapentity_t *entity, const int hullnum) void Brush_LoadEntity(mapentity_t *entity, const int hullnum)
{ {
std::any stats = qbsp_options.target_game->create_content_stats(); auto stats = qbsp_options.target_game->create_content_stats();
Brush_LoadEntity(entity, entity, hullnum, stats); Brush_LoadEntity(entity, entity, hullnum, *stats);
/* /*
* If this is the world entity, find all func_group and func_detail * If this is the world entity, find all func_group and func_detail
@ -1085,12 +1085,12 @@ void Brush_LoadEntity(mapentity_t *entity, const int hullnum)
ProcessAreaPortal(source); ProcessAreaPortal(source);
if (IsWorldBrushEntity(source) || IsNonRemoveWorldBrushEntity(source)) { if (IsWorldBrushEntity(source) || IsNonRemoveWorldBrushEntity(source)) {
Brush_LoadEntity(entity, source, hullnum, stats); Brush_LoadEntity(entity, source, hullnum, *stats);
} }
} }
} }
qbsp_options.target_game->print_content_stats(stats, "brushes"); qbsp_options.target_game->print_content_stats(*stats, "brushes");
} }
void bspbrush_t::update_bounds() void bspbrush_t::update_bounds()

View File

@ -48,7 +48,7 @@ constexpr int PSIDE_BOTH = (PSIDE_FRONT|PSIDE_BACK);
constexpr int PSIDE_FACING = 4; constexpr int PSIDE_FACING = 4;
struct bspstats_t { struct bspstats_t {
std::any leafstats; std::unique_ptr<content_stats_base_t> leafstats;
// total number of nodes, includes c_nonvis // total number of nodes, includes c_nonvis
std::atomic<int> c_nodes; std::atomic<int> c_nodes;
// number of nodes created by splitting on a side_t which had !visible // number of nodes created by splitting on a side_t which had !visible
@ -414,7 +414,7 @@ static void LeafNode(node_t *leafnode, std::vector<std::unique_ptr<bspbrush_t>>
leafnode->original_brushes.push_back(brush->original); leafnode->original_brushes.push_back(brush->original);
} }
qbsp_options.target_game->count_contents_in_stats(leafnode->contents, stats.leafstats); qbsp_options.target_game->count_contents_in_stats(leafnode->contents, *stats.leafstats);
} }
//============================================================ //============================================================

View File

@ -636,7 +636,7 @@ void TJunc(node_t *headnode)
{ {
logging::print(logging::flag::PROGRESS, "---- {} ----\n", __func__); logging::print(logging::flag::PROGRESS, "---- {} ----\n", __func__);
tjunc_stats_t stats; tjunc_stats_t stats{};
std::unordered_set<face_t *> faces; std::unordered_set<face_t *> faces;
FindFaces_r(headnode, faces); FindFaces_r(headnode, faces);