use a reader/writer-esque lock (shared_mutex) instead of exclusive-only recursive lock to speed up plane stuff
This commit is contained in:
parent
f8babef4e1
commit
4e3739c751
|
|
@ -33,6 +33,7 @@
|
|||
#include <unordered_map>
|
||||
#include <list>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
|
||||
struct bspbrush_t;
|
||||
|
||||
|
|
@ -125,7 +126,7 @@ struct maptexdata_t
|
|||
|
||||
#include <common/imglib.hh>
|
||||
|
||||
extern std::recursive_mutex map_planes_lock;
|
||||
extern std::shared_mutex map_planes_lock;
|
||||
|
||||
struct hashvert_t
|
||||
{
|
||||
|
|
@ -241,7 +242,7 @@ struct mapdata_t
|
|||
const std::string &texinfoTextureName(int texinfo) const { return miptexTextureName(mtexinfos.at(texinfo).miptex); }
|
||||
|
||||
inline qbsp_plane_t get_plane(int pnum) {
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
std::shared_lock lock(map_planes_lock);
|
||||
return planes.at(pnum);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,17 @@ qvec3b Face_LookupTextureColor(const mbsp_t *bsp, const mface_t *face)
|
|||
return {127};
|
||||
}
|
||||
|
||||
inline bouncelight_t &CreateBounceLight(const mface_t *face, const mbsp_t *bsp)
|
||||
{
|
||||
unique_lock<mutex> lck{bouncelights_lock};
|
||||
bouncelight_t &l = bouncelights.emplace_back();
|
||||
|
||||
const int lastBounceLightIndex = static_cast<int>(bouncelights.size()) - 1;
|
||||
bouncelightsByFacenum[Face_GetNum(bsp, face)].push_back(lastBounceLightIndex);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static void AddBounceLight(const qvec3d &pos, const std::unordered_map<int, qvec3d> &colorByStyle, const qvec3d &surfnormal,
|
||||
vec_t area, const mface_t *face, const mbsp_t *bsp)
|
||||
{
|
||||
|
|
@ -101,7 +112,7 @@ static void AddBounceLight(const qvec3d &pos, const std::unordered_map<int, qvec
|
|||
}
|
||||
Q_assert(area > 0);
|
||||
|
||||
bouncelight_t l;
|
||||
bouncelight_t &l = CreateBounceLight(face, bsp);
|
||||
l.poly = GLM_FacePoints(bsp, face);
|
||||
l.poly_edgeplanes = GLM_MakeInwardFacingEdgePlanes(l.poly);
|
||||
l.pos = pos;
|
||||
|
|
@ -124,12 +135,6 @@ static void AddBounceLight(const qvec3d &pos, const std::unordered_map<int, qvec
|
|||
} else if (light_options.visapprox.value() == visapprox_t::RAYS) {
|
||||
l.bounds = EstimateVisibleBoundsAtPoint(pos);
|
||||
}
|
||||
|
||||
unique_lock<mutex> lck{bouncelights_lock};
|
||||
bouncelights.push_back(l);
|
||||
|
||||
const int lastBounceLightIndex = static_cast<int>(bouncelights.size()) - 1;
|
||||
bouncelightsByFacenum[Face_GetNum(bsp, face)].push_back(lastBounceLightIndex);
|
||||
}
|
||||
|
||||
const std::vector<bouncelight_t> &BounceLights()
|
||||
|
|
|
|||
|
|
@ -66,8 +66,7 @@ Face_Plane
|
|||
*/
|
||||
qplane3d Face_Plane(const face_t *face)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
const qplane3d &result = map.planes.at(face->planenum);
|
||||
const qplane3d result = map.get_plane(face->planenum);
|
||||
|
||||
if (face->planeside) {
|
||||
return -result;
|
||||
|
|
@ -78,8 +77,7 @@ qplane3d Face_Plane(const face_t *face)
|
|||
|
||||
qplane3d Face_Plane(const side_t *face)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
const qplane3d &result = map.planes.at(face->planenum);
|
||||
const qplane3d result = map.get_plane(face->planenum);
|
||||
|
||||
if (face->planeside) {
|
||||
return -result;
|
||||
|
|
@ -97,8 +95,7 @@ Note: this will not catch 0 area polygons
|
|||
*/
|
||||
static void CheckFace(side_t *face, const mapface_t &sourceface)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
const qbsp_plane_t &plane = map.planes.at(face->planenum);
|
||||
const qbsp_plane_t plane = map.get_plane(face->planenum);
|
||||
|
||||
if (face->w.size() < 3) {
|
||||
if (face->w.size() == 2) {
|
||||
|
|
@ -229,38 +226,35 @@ inline int plane_hash_fn(const qplane3d &p)
|
|||
return Q_rint(fabs(p.dist));
|
||||
}
|
||||
|
||||
static void PlaneHash_Add(const qplane3d &p, int index)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
|
||||
const int hash = plane_hash_fn(p);
|
||||
map.planehash[hash].push_back(index);
|
||||
}
|
||||
|
||||
/*
|
||||
* NewPlane
|
||||
* - Returns a global plane number and the side that will be the front
|
||||
*/
|
||||
static int NewPlane(const qplane3d &plane, planeside_t *side)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
size_t index;
|
||||
|
||||
vec_t len = qv::length(plane.normal);
|
||||
{
|
||||
std::unique_lock lock(map_planes_lock);
|
||||
|
||||
if (len < 1 - qbsp_options.epsilon.value() || len > 1 + qbsp_options.epsilon.value())
|
||||
FError("invalid normal (vector length {:.4})", len);
|
||||
vec_t len = qv::length(plane.normal);
|
||||
|
||||
size_t index = map.planes.size();
|
||||
qbsp_plane_t &added_plane = map.planes.emplace_back(qbsp_plane_t{plane});
|
||||
if (len < 1 - qbsp_options.epsilon.value() || len > 1 + qbsp_options.epsilon.value())
|
||||
FError("invalid normal (vector length {:.4})", len);
|
||||
|
||||
bool out_flipped = NormalizePlane(added_plane, side != nullptr);
|
||||
index = map.planes.size();
|
||||
qbsp_plane_t &added_plane = map.planes.emplace_back(qbsp_plane_t{plane});
|
||||
|
||||
if (side) {
|
||||
*side = out_flipped ? SIDE_BACK : SIDE_FRONT;
|
||||
bool out_flipped = NormalizePlane(added_plane, side != nullptr);
|
||||
|
||||
if (side) {
|
||||
*side = out_flipped ? SIDE_BACK : SIDE_FRONT;
|
||||
}
|
||||
|
||||
const int hash = plane_hash_fn(added_plane);
|
||||
map.planehash[hash].push_back(index);
|
||||
}
|
||||
|
||||
PlaneHash_Add(added_plane, index);
|
||||
|
||||
// add the back side, too
|
||||
FindPlane(-plane, nullptr);
|
||||
|
||||
|
|
@ -274,20 +268,23 @@ static int NewPlane(const qplane3d &plane, planeside_t *side)
|
|||
*/
|
||||
int FindPlane(const qplane3d &plane, planeside_t *side)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
{
|
||||
std::shared_lock lock(map_planes_lock);
|
||||
|
||||
for (int i : map.planehash[plane_hash_fn(plane)]) {
|
||||
const qbsp_plane_t &p = map.planes.at(i);
|
||||
if (qv::epsilonEqual(p, plane)) {
|
||||
if (side) {
|
||||
*side = SIDE_FRONT;
|
||||
for (int i : map.planehash[plane_hash_fn(plane)]) {
|
||||
const qbsp_plane_t &p = map.planes.at(i);
|
||||
if (qv::epsilonEqual(p, plane)) {
|
||||
if (side) {
|
||||
*side = SIDE_FRONT;
|
||||
}
|
||||
return i;
|
||||
} else if (side && qv::epsilonEqual(-p, plane)) {
|
||||
*side = SIDE_BACK;
|
||||
return i;
|
||||
}
|
||||
return i;
|
||||
} else if (side && qv::epsilonEqual(-p, plane)) {
|
||||
*side = SIDE_BACK;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return NewPlane(plane, side);
|
||||
}
|
||||
|
||||
|
|
@ -297,7 +294,7 @@ int FindPlane(const qplane3d &plane, planeside_t *side)
|
|||
*/
|
||||
int FindPositivePlane(int planenum)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
std::shared_lock lock(map_planes_lock);
|
||||
|
||||
const auto &plane = map.planes[planenum];
|
||||
|
||||
|
|
|
|||
|
|
@ -252,13 +252,11 @@ static int QuickTestBrushToPlanenum(const bspbrush_t &brush, int planenum, int *
|
|||
}
|
||||
|
||||
// box on plane side
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
auto plane = map.planes[planenum];
|
||||
auto plane = map.get_plane(planenum);
|
||||
int s = BoxOnPlaneSide(brush.bounds, plane);
|
||||
|
||||
// if both sides, count the visible faces split
|
||||
if (s == PSIDE_BOTH)
|
||||
{
|
||||
if (s == PSIDE_BOTH) {
|
||||
*numsplits += 3;
|
||||
}
|
||||
|
||||
|
|
@ -289,11 +287,7 @@ static int TestBrushToPlanenum(const bspbrush_t &brush, int planenum, int *numsp
|
|||
}
|
||||
|
||||
// box on plane side
|
||||
qbsp_plane_t plane;
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
plane = map.planes[planenum];
|
||||
}
|
||||
qbsp_plane_t plane = map.get_plane(planenum);
|
||||
|
||||
//int s = SphereOnPlaneSide(brush.sphere_origin, brush.sphere_radius, plane);
|
||||
int s = BoxOnPlaneSide(brush.bounds, plane);
|
||||
|
|
@ -607,11 +601,7 @@ https://github.com/id-Software/Quake-2-Tools/blob/master/bsp/qbsp3/brushbsp.c#L9
|
|||
*/
|
||||
static twosided<std::unique_ptr<bspbrush_t>> SplitBrush(std::unique_ptr<bspbrush_t> brush, int planenum)
|
||||
{
|
||||
qplane3d split;
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
split = map.planes.at(planenum);
|
||||
}
|
||||
qplane3d split = map.get_plane(planenum);
|
||||
|
||||
twosided<std::unique_ptr<bspbrush_t>> result;
|
||||
|
||||
|
|
|
|||
|
|
@ -290,8 +290,7 @@ static void AddMarksurfaces_r(face_t *face, std::unique_ptr<face_t> face_copy, n
|
|||
return;
|
||||
}
|
||||
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
const qbsp_plane_t &splitplane = map.planes.at(node->planenum);
|
||||
const qbsp_plane_t splitplane = map.get_plane(node->planenum);
|
||||
|
||||
auto [frontFragment, backFragment] = SplitFace(std::move(face_copy), splitplane);
|
||||
if (frontFragment) {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
#include <common/qvec.hh>
|
||||
|
||||
mapdata_t map;
|
||||
std::recursive_mutex map_planes_lock;
|
||||
std::shared_mutex map_planes_lock;
|
||||
|
||||
const std::optional<img::texture_meta> &mapdata_t::load_image_meta(const std::string_view &name)
|
||||
{
|
||||
|
|
@ -2373,7 +2373,7 @@ from q3map
|
|||
*/
|
||||
void WriteBspBrushMap(const fs::path &name, const std::vector<std::unique_ptr<bspbrush_t>> &list)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
std::shared_lock lock(map_planes_lock);
|
||||
|
||||
logging::print("writing {}\n", name);
|
||||
std::ofstream f(name);
|
||||
|
|
|
|||
|
|
@ -98,8 +98,7 @@ static std::unique_ptr<face_t> TryMerge(const face_t *f1, const face_t *f2)
|
|||
|
||||
// check slope of connected lines
|
||||
// if the slopes are colinear, the point can be removed
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
const auto &plane = map.planes.at(f1->planenum);
|
||||
auto plane = map.get_plane(f1->planenum);
|
||||
planenormal = plane.normal;
|
||||
if (f1->planeside)
|
||||
planenormal = -planenormal;
|
||||
|
|
|
|||
|
|
@ -59,8 +59,7 @@ static node_t *PointInLeaf(node_t *node, const qvec3d &point)
|
|||
return node;
|
||||
}
|
||||
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
const auto &plane = map.planes.at(node->planenum);
|
||||
const auto plane = map.get_plane(node->planenum);
|
||||
vec_t dist = plane.distance_to(point);
|
||||
|
||||
if (dist > 0) {
|
||||
|
|
|
|||
|
|
@ -218,20 +218,18 @@ BaseWindingForNode
|
|||
Creates a winding from the given node plane, clipped by all parent nodes.
|
||||
================
|
||||
*/
|
||||
#define BASE_WINDING_EPSILON 0.001
|
||||
#define SPLIT_WINDING_EPSILON 0.001
|
||||
constexpr vec_t BASE_WINDING_EPSILON = 0.001;
|
||||
constexpr vec_t SPLIT_WINDING_EPSILON = 0.001;
|
||||
|
||||
std::optional<winding_t> BaseWindingForNode(node_t *node)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
auto plane = map.planes.at(node->planenum);
|
||||
auto plane = map.get_plane(node->planenum);
|
||||
|
||||
std::optional<winding_t> w = BaseWindingForPlane(plane);
|
||||
|
||||
// clip by all the parents
|
||||
for (node_t *np = node->parent; np && w; )
|
||||
{
|
||||
plane = map.planes.at(np->planenum);
|
||||
for (node_t *np = node->parent; np && w; ) {
|
||||
plane = map.get_plane(np->planenum);
|
||||
|
||||
const planeside_t keep = (np->children[0].get() == node) ?
|
||||
SIDE_FRONT : SIDE_BACK;
|
||||
|
|
@ -256,8 +254,6 @@ portals in the node.
|
|||
*/
|
||||
void MakeNodePortal(tree_t *tree, node_t *node, portalstats_t &stats)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
|
||||
auto w = BaseWindingForNode(node);
|
||||
|
||||
// clip the portal by all the other portals in the node
|
||||
|
|
@ -267,12 +263,12 @@ void MakeNodePortal(tree_t *tree, node_t *node, portalstats_t &stats)
|
|||
if (p->nodes[0] == node)
|
||||
{
|
||||
side = 0;
|
||||
plane = map.planes.at(p->planenum);
|
||||
plane = map.get_plane(p->planenum);
|
||||
}
|
||||
else if (p->nodes[1] == node)
|
||||
{
|
||||
side = 1;
|
||||
plane = -map.planes.at(p->planenum);
|
||||
plane = -map.get_plane(p->planenum);
|
||||
}
|
||||
else
|
||||
Error("CutNodePortals_r: mislinked portal");
|
||||
|
|
@ -722,8 +718,6 @@ Finds a brush side to use for texturing the given portal
|
|||
*/
|
||||
static void FindPortalSide(portal_t *p)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
|
||||
// decide which content change is strongest
|
||||
// solid > lava > water, etc
|
||||
contentflags_t viscontents =
|
||||
|
|
@ -734,11 +728,11 @@ static void FindPortalSide(portal_t *p)
|
|||
int planenum = p->onnode->planenum;
|
||||
side_t *bestside = nullptr;
|
||||
float bestdot = 0;
|
||||
qbsp_plane_t p1 = map.get_plane(p->onnode->planenum);
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
node_t *n = p->nodes[j];
|
||||
auto p1 = map.planes.at(p->onnode->planenum);
|
||||
|
||||
// iterate the n->original_brushes vector in reverse order, so later brushes
|
||||
// in the map file order are prioritized
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ static void WriteFloat(std::ofstream &portalFile, vec_t v)
|
|||
|
||||
static void WritePortals_r(node_t *node, std::ofstream &portalFile, bool clusters)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
std::shared_lock lock(map_planes_lock);
|
||||
|
||||
const portal_t *p, *next;
|
||||
std::optional<winding_t> w;
|
||||
|
|
|
|||
|
|
@ -315,8 +315,6 @@ against axial bounding boxes
|
|||
*/
|
||||
static std::vector<std::tuple<size_t, const side_t *>> AddBrushBevels(const bspbrush_t &b)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
|
||||
// add already-present planes
|
||||
std::vector<std::tuple<size_t, const side_t *>> planes;
|
||||
|
||||
|
|
@ -324,7 +322,7 @@ static std::vector<std::tuple<size_t, const side_t *>> AddBrushBevels(const bspb
|
|||
int32_t planenum = f.planenum;
|
||||
|
||||
if (f.planeside) {
|
||||
planenum = FindPlane(-map.planes.at(f.planenum), nullptr);
|
||||
planenum = FindPlane(-map.get_plane(f.planenum), nullptr);
|
||||
}
|
||||
|
||||
int32_t outputplanenum = ExportMapPlane(planenum);
|
||||
|
|
@ -409,7 +407,7 @@ static std::vector<std::tuple<size_t, const side_t *>> AddBrushBevels(const bspb
|
|||
// behind this plane, it is a proper edge bevel
|
||||
for (; it != b.sides.end(); it++) {
|
||||
auto &f = *it;
|
||||
const auto &plane = map.planes.at(f.planenum);
|
||||
const auto &plane = map.get_plane(f.planenum);
|
||||
qplane3d temp = f.planeside ? -plane : plane;
|
||||
|
||||
// if this plane has allready been used, skip it
|
||||
|
|
@ -765,7 +763,7 @@ hull sizes
|
|||
static void BSPX_Brushes_AddModel(
|
||||
struct bspxbrushes_s *ctx, int modelnum, std::vector<std::unique_ptr<bspbrush_t>> &brushes)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
std::shared_lock lock(map_planes_lock);
|
||||
|
||||
bspxbrushes_permodel permodel{1, modelnum};
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ using nlohmann::json;
|
|||
*/
|
||||
size_t ExportMapPlane(size_t planenum)
|
||||
{
|
||||
const auto lock = std::lock_guard(map_planes_lock);
|
||||
std::shared_lock lock(map_planes_lock);
|
||||
qbsp_plane_t &plane = map.planes.at(planenum);
|
||||
|
||||
if (plane.outputplanenum.has_value())
|
||||
|
|
|
|||
Loading…
Reference in New Issue