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:
struct content_stats_t
struct content_stats_t : public content_stats_base_t
{
std::atomic<size_t> solid;
std::atomic<size_t> empty;
@ -569,20 +569,17 @@ private:
std::atomic<size_t> detail_fence;
std::atomic<size_t> sky;
std::atomic<size_t> illusionary_visblocker;
content_stats_t() = default;
inline content_stats_t(const content_stats_t &copy) { }
};
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)) {
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) {
logging::print(logging::flag::STAT, " {:8} empty {}\n", stats.empty, what);
@ -1281,26 +1278,23 @@ public:
}
private:
struct content_stats_t
struct content_stats_t : public content_stats_base_t
{
//std::array<std::atomic<size_t>, 32> native_types;
std::unordered_map<int32_t, size_t> native_types;
std::atomic<size_t> total_brushes;
std::atomic<size_t> visblocker_brushes;
content_stats_t() = default;
inline content_stats_t(const content_stats_t &copy) { }
};
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++) {
if (contents.native & nth_bit(i)) {
@ -1320,9 +1314,9 @@ public:
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++) {
if (stats.native_types[i]) {

View File

@ -233,6 +233,10 @@ enum gameid_t
GAME_TOTAL
};
struct content_stats_base_t {
virtual ~content_stats_base_t() = default;
};
// Game definition, which contains data specific to
// the game a BSP version is being compiled for.
struct gamedef_t
@ -304,9 +308,9 @@ struct gamedef_t
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 const std::vector<qvec3b> &get_default_palette() const = 0;
virtual std::any create_content_stats() const = 0;
virtual void count_contents_in_stats(const contentflags_t &contents, std::any &stats) const = 0;
virtual void print_content_stats(const std::any &stats, const char *what) 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, content_stats_base_t &stats) 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

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;
qvec3d rotate_offset{};
@ -1063,9 +1063,9 @@ hullnum 0 does not contain clip brushes.
*/
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
@ -1085,12 +1085,12 @@ void Brush_LoadEntity(mapentity_t *entity, const int hullnum)
ProcessAreaPortal(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()

View File

@ -48,7 +48,7 @@ constexpr int PSIDE_BOTH = (PSIDE_FRONT|PSIDE_BACK);
constexpr int PSIDE_FACING = 4;
struct bspstats_t {
std::any leafstats;
std::unique_ptr<content_stats_base_t> leafstats;
// total number of nodes, includes c_nonvis
std::atomic<int> c_nodes;
// 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);
}
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__);
tjunc_stats_t stats;
tjunc_stats_t stats{};
std::unordered_set<face_t *> faces;
FindFaces_r(headnode, faces);