mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-12-01 00:12:27 +00:00
- Enable backpatching in the internal nodebuilder.
SVN r2477 (polyobjects)
This commit is contained in:
parent
14c6c53709
commit
edb4686a48
7 changed files with 194 additions and 86 deletions
|
@ -63,7 +63,7 @@ const int AAPreference = 16;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
FNodeBuilder::FNodeBuilder(FLevel &level)
|
FNodeBuilder::FNodeBuilder(FLevel &level)
|
||||||
: Level(level), GLNodes(false), EnableSSE2(true), SegsStuffed(0)
|
: Level(level), GLNodes(false), SegsStuffed(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
VertexMap = NULL;
|
VertexMap = NULL;
|
||||||
|
@ -71,8 +71,8 @@ FNodeBuilder::FNodeBuilder(FLevel &level)
|
||||||
|
|
||||||
FNodeBuilder::FNodeBuilder (FLevel &level,
|
FNodeBuilder::FNodeBuilder (FLevel &level,
|
||||||
TArray<FPolyStart> &polyspots, TArray<FPolyStart> &anchors,
|
TArray<FPolyStart> &polyspots, TArray<FPolyStart> &anchors,
|
||||||
bool makeGLNodes, bool enableSSE2)
|
bool makeGLNodes)
|
||||||
: Level(level), GLNodes(makeGLNodes), EnableSSE2(enableSSE2), SegsStuffed(0)
|
: Level(level), GLNodes(makeGLNodes), SegsStuffed(0)
|
||||||
{
|
{
|
||||||
VertexMap = new FVertexMap (*this, Level.MinX, Level.MinY, Level.MaxX, Level.MaxY);
|
VertexMap = new FVertexMap (*this, Level.MinX, Level.MinY, Level.MaxX, Level.MaxY);
|
||||||
FindUsedVertices (Level.Vertices, Level.NumVertices);
|
FindUsedVertices (Level.Vertices, Level.NumVertices);
|
||||||
|
@ -90,10 +90,9 @@ FNodeBuilder::~FNodeBuilder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FNodeBuilder::BuildMini(bool makeGLNodes, bool enableSSE2)
|
void FNodeBuilder::BuildMini(bool makeGLNodes)
|
||||||
{
|
{
|
||||||
GLNodes = makeGLNodes;
|
GLNodes = makeGLNodes;
|
||||||
EnableSSE2 = enableSSE2;
|
|
||||||
GroupSegPlanesSimple();
|
GroupSegPlanesSimple();
|
||||||
BuildTree();
|
BuildTree();
|
||||||
}
|
}
|
||||||
|
@ -540,7 +539,7 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit)
|
||||||
int realSegs[2] = { 0, 0 };
|
int realSegs[2] = { 0, 0 };
|
||||||
int specialSegs[2] = { 0, 0 };
|
int specialSegs[2] = { 0, 0 };
|
||||||
DWORD i = set;
|
DWORD i = set;
|
||||||
int sidev1, sidev2;
|
int sidev[2];
|
||||||
int side;
|
int side;
|
||||||
bool splitter = false;
|
bool splitter = false;
|
||||||
unsigned int max, m2, p, q;
|
unsigned int max, m2, p, q;
|
||||||
|
@ -559,7 +558,7 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
side = ClassifyLine (node, test, sidev1, sidev2);
|
side = ClassifyLine (node, &Vertices[test->v1], &Vertices[test->v2], sidev);
|
||||||
}
|
}
|
||||||
switch (side)
|
switch (side)
|
||||||
{
|
{
|
||||||
|
@ -569,9 +568,9 @@ int FNodeBuilder::Heuristic (node_t &node, DWORD set, bool honorNoSplit)
|
||||||
// The "right" thing to do in this case is to only reject it if there is
|
// The "right" thing to do in this case is to only reject it if there is
|
||||||
// another nosplit seg from the same sector at this vertex. Note that a line
|
// another nosplit seg from the same sector at this vertex. Note that a line
|
||||||
// that lies exactly on top of the splitter is okay.
|
// that lies exactly on top of the splitter is okay.
|
||||||
if (test->loopnum && honorNoSplit && (sidev1 == 0 || sidev2 == 0))
|
if (test->loopnum && honorNoSplit && (sidev[0] == 0 || sidev[1] == 0))
|
||||||
{
|
{
|
||||||
if ((sidev1 | sidev2) != 0)
|
if ((sidev[0] | sidev[1]) != 0)
|
||||||
{
|
{
|
||||||
max = Touched.Size();
|
max = Touched.Size();
|
||||||
for (p = 0; p < max; ++p)
|
for (p = 0; p < max; ++p)
|
||||||
|
@ -783,18 +782,18 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou
|
||||||
FPrivSeg *seg = &Segs[set];
|
FPrivSeg *seg = &Segs[set];
|
||||||
int next = seg->next;
|
int next = seg->next;
|
||||||
|
|
||||||
int sidev1, sidev2, side;
|
int sidev[2], side;
|
||||||
|
|
||||||
if (HackSeg == set)
|
if (HackSeg == set)
|
||||||
{
|
{
|
||||||
HackSeg = DWORD_MAX;
|
HackSeg = DWORD_MAX;
|
||||||
side = 1;
|
side = 1;
|
||||||
sidev1 = sidev2 = 0;
|
sidev[0] = sidev[1] = 0;
|
||||||
hack = true;
|
hack = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
side = ClassifyLine (node, seg, sidev1, sidev2);
|
side = ClassifyLine (node, &Vertices[seg->v1], &Vertices[seg->v2], sidev);
|
||||||
hack = false;
|
hack = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -837,7 +836,7 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou
|
||||||
Printf("SelectVertexClose selected endpoint of seg %u\n", set);
|
Printf("SelectVertexClose selected endpoint of seg %u\n", set);
|
||||||
}
|
}
|
||||||
|
|
||||||
seg2 = SplitSeg (set, vertnum, sidev1);
|
seg2 = SplitSeg (set, vertnum, sidev[0]);
|
||||||
|
|
||||||
Segs[seg2].next = outset0;
|
Segs[seg2].next = outset0;
|
||||||
outset0 = seg2;
|
outset0 = seg2;
|
||||||
|
@ -848,7 +847,7 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou
|
||||||
if (Segs[set].partner != DWORD_MAX)
|
if (Segs[set].partner != DWORD_MAX)
|
||||||
{
|
{
|
||||||
int partner1 = Segs[set].partner;
|
int partner1 = Segs[set].partner;
|
||||||
int partner2 = SplitSeg (partner1, vertnum, sidev2);
|
int partner2 = SplitSeg (partner1, vertnum, sidev[1]);
|
||||||
// The newly created seg stays in the same set as the
|
// The newly created seg stays in the same set as the
|
||||||
// back seg because it has not been considered for splitting
|
// back seg because it has not been considered for splitting
|
||||||
// yet. If it had been, then the front seg would have already
|
// yet. If it had been, then the front seg would have already
|
||||||
|
@ -869,17 +868,17 @@ void FNodeBuilder::SplitSegs (DWORD set, node_t &node, DWORD splitseg, DWORD &ou
|
||||||
}
|
}
|
||||||
if (side >= 0 && GLNodes)
|
if (side >= 0 && GLNodes)
|
||||||
{
|
{
|
||||||
if (sidev1 == 0)
|
if (sidev[0] == 0)
|
||||||
{
|
{
|
||||||
double dist1 = AddIntersection (node, seg->v1);
|
double dist1 = AddIntersection (node, seg->v1);
|
||||||
if (sidev2 == 0)
|
if (sidev[1] == 0)
|
||||||
{
|
{
|
||||||
double dist2 = AddIntersection (node, seg->v2);
|
double dist2 = AddIntersection (node, seg->v2);
|
||||||
FSplitSharer share = { dist1, set, dist2 > dist1 };
|
FSplitSharer share = { dist1, set, dist2 > dist1 };
|
||||||
SplitSharers.Push (share);
|
SplitSharers.Push (share);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sidev2 == 0)
|
else if (sidev[1] == 0)
|
||||||
{
|
{
|
||||||
AddIntersection (node, seg->v2);
|
AddIntersection (node, seg->v2);
|
||||||
}
|
}
|
||||||
|
@ -1072,3 +1071,92 @@ void FNodeBuilder::PrintSet (int l, DWORD set)
|
||||||
}
|
}
|
||||||
Printf (PRINT_LOG, "*\n");
|
Printf (PRINT_LOG, "*\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef BACKPATCH
|
||||||
|
#ifdef _WIN32
|
||||||
|
extern "C" {
|
||||||
|
__declspec(dllimport) int __stdcall VirtualProtect(void *, unsigned long, unsigned long, unsigned long *);
|
||||||
|
}
|
||||||
|
#define PAGE_EXECUTE_READWRITE 64
|
||||||
|
#else
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
extern "C" int ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2])
|
||||||
|
#else
|
||||||
|
static int *CallerOffset;
|
||||||
|
int ClassifyLineBackpatchC (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2])
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
// Select the routine based on SSE2 availability and patch the caller so that
|
||||||
|
// they call that routine directly next time instead of going through here.
|
||||||
|
int *calleroffset;
|
||||||
|
int diff;
|
||||||
|
int (*func)(node_t &, const FSimpleVert *, const FSimpleVert *, int[2]);
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
calleroffset = (int *)__builtin_return_address(0);
|
||||||
|
#else
|
||||||
|
calleroffset = CallerOffset;
|
||||||
|
#endif
|
||||||
|
// printf ("Patching for SSE %d @ %p %d\n", SSELevel, calleroffset, *calleroffset);
|
||||||
|
|
||||||
|
if (CPU.bSSE2)
|
||||||
|
{
|
||||||
|
func = ClassifyLineSSE2;
|
||||||
|
diff = (char *)ClassifyLineSSE2 - (char *)calleroffset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
func = ClassifyLine2;
|
||||||
|
diff = (char *)ClassifyLine2 - (char *)calleroffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
calleroffset--;
|
||||||
|
// Patch the caller.
|
||||||
|
#ifdef _WIN32
|
||||||
|
unsigned long oldprotect;
|
||||||
|
if (VirtualProtect (calleroffset, 4, PAGE_EXECUTE_READWRITE, &oldprotect))
|
||||||
|
#else
|
||||||
|
// must make this page-aligned for mprotect
|
||||||
|
long pagesize = sysconf(_SC_PAGESIZE);
|
||||||
|
char *callerpage = (char *)((intptr_t)calleroffset & ~(pagesize - 1));
|
||||||
|
size_t protectlen = (intptr_t)calleroffset + sizeof(void*) - (intptr_t)callerpage;
|
||||||
|
int ptect;
|
||||||
|
if (!(ptect = mprotect(callerpage, protectlen, PROT_READ|PROT_WRITE|PROT_EXEC)))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
*calleroffset = diff;
|
||||||
|
#ifdef _WIN32
|
||||||
|
VirtualProtect (calleroffset, sizeof(void*), oldprotect, &oldprotect);
|
||||||
|
#else
|
||||||
|
mprotect(callerpage, protectlen, PROT_READ|PROT_EXEC);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// And return by calling the real function.
|
||||||
|
return func (node, v1, v2, sidev);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef __GNUC__
|
||||||
|
// The ClassifyLineBackpatch() function here is a stub that uses inline assembly and nakedness
|
||||||
|
// to retrieve the return address of the stack before sending control to the real
|
||||||
|
// ClassifyLineBackpatchC() function. Since BACKPATCH shouldn't be defined on 64-bit builds,
|
||||||
|
// we're okay that VC++ can't do inline assembly on that target.
|
||||||
|
|
||||||
|
extern "C" __declspec(noinline) __declspec(naked) int ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2])
|
||||||
|
{
|
||||||
|
// We store the return address in a global, so as not to need to mess with the parameter list.
|
||||||
|
__asm
|
||||||
|
{
|
||||||
|
mov eax, [esp]
|
||||||
|
mov CallerOffset, eax
|
||||||
|
jmp ClassifyLineBackpatchC
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "doomdata.h"
|
#include "doomdata.h"
|
||||||
#include "tarray.h"
|
#include "tarray.h"
|
||||||
#include "r_defs.h"
|
#include "r_defs.h"
|
||||||
|
#include "x86.h"
|
||||||
|
|
||||||
struct FPolySeg;
|
struct FPolySeg;
|
||||||
struct FMiniBSP;
|
struct FMiniBSP;
|
||||||
|
@ -43,6 +44,27 @@ private:
|
||||||
FEvent *Predecessor (FEvent *event) const;
|
FEvent *Predecessor (FEvent *event) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FSimpleVert
|
||||||
|
{
|
||||||
|
fixed_t x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
int ClassifyLine2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]);
|
||||||
|
#ifndef DISABLE_SSE
|
||||||
|
int ClassifyLineSSE1 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]);
|
||||||
|
int ClassifyLineSSE2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]);
|
||||||
|
#ifdef BACKPATCH
|
||||||
|
#ifdef __GNUC__
|
||||||
|
int ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]) __attribute__((noinline));
|
||||||
|
#else
|
||||||
|
int __declspec(noinline) ClassifyLineBackpatch (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2]);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
class FNodeBuilder
|
class FNodeBuilder
|
||||||
{
|
{
|
||||||
struct FPrivSeg
|
struct FPrivSeg
|
||||||
|
@ -63,9 +85,8 @@ class FNodeBuilder
|
||||||
bool planefront;
|
bool planefront;
|
||||||
FPrivSeg *hashnext;
|
FPrivSeg *hashnext;
|
||||||
};
|
};
|
||||||
struct FPrivVert
|
struct FPrivVert : FSimpleVert
|
||||||
{
|
{
|
||||||
fixed_t x, y;
|
|
||||||
DWORD segs; // segs that use this vertex as v1
|
DWORD segs; // segs that use this vertex as v1
|
||||||
DWORD segs2; // segs that use this vertex as v2
|
DWORD segs2; // segs that use this vertex as v2
|
||||||
|
|
||||||
|
@ -175,7 +196,7 @@ public:
|
||||||
FNodeBuilder (FLevel &level);
|
FNodeBuilder (FLevel &level);
|
||||||
FNodeBuilder (FLevel &level,
|
FNodeBuilder (FLevel &level,
|
||||||
TArray<FPolyStart> &polyspots, TArray<FPolyStart> &anchors,
|
TArray<FPolyStart> &polyspots, TArray<FPolyStart> &anchors,
|
||||||
bool makeGLNodes, bool enableSSE2);
|
bool makeGLNodes);
|
||||||
~FNodeBuilder ();
|
~FNodeBuilder ();
|
||||||
|
|
||||||
void Extract (node_t *&nodes, int &nodeCount,
|
void Extract (node_t *&nodes, int &nodeCount,
|
||||||
|
@ -187,7 +208,7 @@ public:
|
||||||
void Clear();
|
void Clear();
|
||||||
void AddPolySegs(FPolySeg *segs, int numsegs);
|
void AddPolySegs(FPolySeg *segs, int numsegs);
|
||||||
void AddSegs(seg_t *segs, int numsegs);
|
void AddSegs(seg_t *segs, int numsegs);
|
||||||
void BuildMini(bool makeGLNodes, bool enableSSE2);
|
void BuildMini(bool makeGLNodes);
|
||||||
void ExtractMini(FMiniBSP *bsp);
|
void ExtractMini(FMiniBSP *bsp);
|
||||||
|
|
||||||
static angle_t PointToAngle (fixed_t dx, fixed_t dy);
|
static angle_t PointToAngle (fixed_t dx, fixed_t dy);
|
||||||
|
@ -220,7 +241,6 @@ private:
|
||||||
DWORD HackMate; // Seg to use in front of hack seg
|
DWORD HackMate; // Seg to use in front of hack seg
|
||||||
FLevel &Level;
|
FLevel &Level;
|
||||||
bool GLNodes; // Add minisegs to make GL nodes?
|
bool GLNodes; // Add minisegs to make GL nodes?
|
||||||
bool EnableSSE2;
|
|
||||||
|
|
||||||
// Progress meter stuff
|
// Progress meter stuff
|
||||||
int SegsStuffed;
|
int SegsStuffed;
|
||||||
|
@ -251,9 +271,7 @@ private:
|
||||||
// 1 = seg is in back
|
// 1 = seg is in back
|
||||||
// -1 = seg cuts the node
|
// -1 = seg cuts the node
|
||||||
|
|
||||||
inline int ClassifyLine (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2);
|
inline int ClassifyLine (node_t &node, const FPrivVert *v1, const FPrivVert *v2, int sidev[2]);
|
||||||
int ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2);
|
|
||||||
int ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2);
|
|
||||||
|
|
||||||
void FixSplitSharers (const node_t &node);
|
void FixSplitSharers (const node_t &node);
|
||||||
double AddIntersection (const node_t &node, int vertex);
|
double AddIntersection (const node_t &node, int vertex);
|
||||||
|
@ -313,21 +331,27 @@ inline int FNodeBuilder::PointOnSide (int x, int y, int x1, int y1, int dx, int
|
||||||
return s_num > 0.0 ? -1 : 1;
|
return s_num > 0.0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int FNodeBuilder::ClassifyLine (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2)
|
inline int FNodeBuilder::ClassifyLine (node_t &node, const FPrivVert *v1, const FPrivVert *v2, int sidev[2])
|
||||||
{
|
{
|
||||||
#if !defined(_M_IX86) && !defined(_M_X64) && !defined(__i386__) && !defined(__amd64__)
|
#ifdef DISABLE_SSE
|
||||||
return ClassifyLine2 (node, seg, sidev1, sidev2);
|
return ClassifyLine2 (node, v1, v2, sidev);
|
||||||
#elif defined(__SSE2__)
|
#else
|
||||||
|
#if defined(__SSE2__) || defined(_M_IX64)
|
||||||
// If compiling with SSE2 support everywhere, just use the SSE2 version.
|
// If compiling with SSE2 support everywhere, just use the SSE2 version.
|
||||||
return ClassifyLineSSE2 (node, seg, sidev1, sidev2);
|
return ClassifyLineSSE2 (node, v1, v2, sidev);
|
||||||
#elif defined(_MSC_VER) && _MSC_VER < 1300
|
#elif defined(_MSC_VER) && _MSC_VER < 1300
|
||||||
// VC 6 does not support SSE2 optimizations.
|
// VC 6 does not support SSE optimizations.
|
||||||
return ClassifyLine2 (node, seg, sidev1, sidev2);
|
return ClassifyLine2 (node, v1, v2, sidev);
|
||||||
#else
|
#else
|
||||||
// Select the routine based on our flag.
|
// Select the routine based on our flag.
|
||||||
if (EnableSSE2)
|
#ifdef BACKPATCH
|
||||||
return ClassifyLineSSE2 (node, seg, sidev1, sidev2);
|
return ClassifyLineBackpatch (node, v1, v2, sidev);
|
||||||
|
#else
|
||||||
|
if (CPU.bSSE2)
|
||||||
|
return ClassifyLineSSE2 (node, v1, v2, sidev);
|
||||||
else
|
else
|
||||||
return ClassifyLine2 (node, seg, sidev1, sidev2);
|
return ClassifyLine2 (node, v1, v2, sidev);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,8 @@
|
||||||
|
|
||||||
#define FAR_ENOUGH 17179869184.f // 4<<32
|
#define FAR_ENOUGH 17179869184.f // 4<<32
|
||||||
|
|
||||||
int FNodeBuilder::ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2)
|
extern "C" int ClassifyLine2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2])
|
||||||
{
|
{
|
||||||
const FPrivVert *v1 = &Vertices[seg->v1];
|
|
||||||
const FPrivVert *v2 = &Vertices[seg->v2];
|
|
||||||
|
|
||||||
double d_x1 = double(node.x);
|
double d_x1 = double(node.x);
|
||||||
double d_y1 = double(node.y);
|
double d_y1 = double(node.y);
|
||||||
double d_dx = double(node.dx);
|
double d_dx = double(node.dx);
|
||||||
|
@ -26,13 +23,13 @@ int FNodeBuilder::ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1,
|
||||||
{
|
{
|
||||||
if (s_num2 <= -FAR_ENOUGH)
|
if (s_num2 <= -FAR_ENOUGH)
|
||||||
{
|
{
|
||||||
sidev1 = sidev2 = 1;
|
sidev[0] = sidev[1] = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (s_num2 >= FAR_ENOUGH)
|
if (s_num2 >= FAR_ENOUGH)
|
||||||
{
|
{
|
||||||
sidev1 = 1;
|
sidev[0] = 1;
|
||||||
sidev2 = -1;
|
sidev[1] = -1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
nears = 1;
|
nears = 1;
|
||||||
|
@ -41,13 +38,13 @@ int FNodeBuilder::ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1,
|
||||||
{
|
{
|
||||||
if (s_num2 >= FAR_ENOUGH)
|
if (s_num2 >= FAR_ENOUGH)
|
||||||
{
|
{
|
||||||
sidev1 = sidev2 = -1;
|
sidev[0] = sidev[1] = -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (s_num2 <= -FAR_ENOUGH)
|
if (s_num2 <= -FAR_ENOUGH)
|
||||||
{
|
{
|
||||||
sidev1 = -1;
|
sidev[0] = -1;
|
||||||
sidev2 = 1;
|
sidev[1] = 1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
nears = 1;
|
nears = 1;
|
||||||
|
@ -65,41 +62,41 @@ int FNodeBuilder::ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1,
|
||||||
double dist = s_num1 * s_num1 * l;
|
double dist = s_num1 * s_num1 * l;
|
||||||
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
||||||
{
|
{
|
||||||
sidev1 = 0;
|
sidev[0] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sidev1 = s_num1 > 0.0 ? -1 : 1;
|
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sidev1 = s_num1 > 0.0 ? -1 : 1;
|
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
if (nears & 1)
|
if (nears & 1)
|
||||||
{
|
{
|
||||||
double dist = s_num2 * s_num2 * l;
|
double dist = s_num2 * s_num2 * l;
|
||||||
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
||||||
{
|
{
|
||||||
sidev2 = 0;
|
sidev[1] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sidev2 = s_num2 > 0.0 ? -1 : 1;
|
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sidev2 = s_num2 > 0.0 ? -1 : 1;
|
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sidev1 = s_num1 > 0.0 ? -1 : 1;
|
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||||
sidev2 = s_num2 > 0.0 ? -1 : 1;
|
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sidev1 | sidev2) == 0)
|
if ((sidev[0] | sidev[1]) == 0)
|
||||||
{ // seg is coplanar with the splitter, so use its orientation to determine
|
{ // seg is coplanar with the splitter, so use its orientation to determine
|
||||||
// which child it ends up in. If it faces the same direction as the splitter,
|
// which child it ends up in. If it faces the same direction as the splitter,
|
||||||
// it goes in front. Otherwise, it goes in back.
|
// it goes in front. Otherwise, it goes in back.
|
||||||
|
@ -127,11 +124,11 @@ int FNodeBuilder::ClassifyLine2 (node_t &node, const FPrivSeg *seg, int &sidev1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sidev1 <= 0 && sidev2 <= 0)
|
else if (sidev[0] <= 0 && sidev[1] <= 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (sidev1 >= 0 && sidev2 >= 0)
|
else if (sidev[0] >= 0 && sidev[1] >= 0)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
|
#ifndef DISABLE_SSE
|
||||||
|
|
||||||
#include "doomtype.h"
|
#include "doomtype.h"
|
||||||
#include "nodebuild.h"
|
#include "nodebuild.h"
|
||||||
|
|
||||||
#define FAR_ENOUGH 17179869184.f // 4<<32
|
#define FAR_ENOUGH 17179869184.f // 4<<32
|
||||||
|
|
||||||
// This function is identical to the ClassifyLine2 version. So how does it use SSE2?
|
// You may notice that this function is identical to ClassifyLine2.
|
||||||
// Easy! By explicitly enabling SSE2 in the configuration properties for this one
|
// The reason it is SSE2 is because this file is explicitly compiled
|
||||||
// file, we can build it with SSE2 enabled without forcing SSE2 on the rest of the
|
// with SSE2 math enabled, but the other files are not.
|
||||||
// project.
|
|
||||||
|
|
||||||
int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &sidev1, int &sidev2)
|
extern "C" int ClassifyLineSSE2 (node_t &node, const FSimpleVert *v1, const FSimpleVert *v2, int sidev[2])
|
||||||
{
|
{
|
||||||
const FPrivVert *v1 = &Vertices[seg->v1];
|
|
||||||
const FPrivVert *v2 = &Vertices[seg->v2];
|
|
||||||
|
|
||||||
double d_x1 = double(node.x);
|
double d_x1 = double(node.x);
|
||||||
double d_y1 = double(node.y);
|
double d_y1 = double(node.y);
|
||||||
double d_dx = double(node.dx);
|
double d_dx = double(node.dx);
|
||||||
|
@ -31,13 +29,13 @@ int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &side
|
||||||
{
|
{
|
||||||
if (s_num2 <= -FAR_ENOUGH)
|
if (s_num2 <= -FAR_ENOUGH)
|
||||||
{
|
{
|
||||||
sidev1 = sidev2 = 1;
|
sidev[0] = sidev[1] = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (s_num2 >= FAR_ENOUGH)
|
if (s_num2 >= FAR_ENOUGH)
|
||||||
{
|
{
|
||||||
sidev1 = 1;
|
sidev[0] = 1;
|
||||||
sidev2 = -1;
|
sidev[1] = -1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
nears = 1;
|
nears = 1;
|
||||||
|
@ -46,13 +44,13 @@ int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &side
|
||||||
{
|
{
|
||||||
if (s_num2 >= FAR_ENOUGH)
|
if (s_num2 >= FAR_ENOUGH)
|
||||||
{
|
{
|
||||||
sidev1 = sidev2 = -1;
|
sidev[0] = sidev[1] = -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (s_num2 <= -FAR_ENOUGH)
|
if (s_num2 <= -FAR_ENOUGH)
|
||||||
{
|
{
|
||||||
sidev1 = -1;
|
sidev[0] = -1;
|
||||||
sidev2 = 1;
|
sidev[1] = 1;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
nears = 1;
|
nears = 1;
|
||||||
|
@ -70,41 +68,41 @@ int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &side
|
||||||
double dist = s_num1 * s_num1 * l;
|
double dist = s_num1 * s_num1 * l;
|
||||||
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
||||||
{
|
{
|
||||||
sidev1 = 0;
|
sidev[0] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sidev1 = s_num1 > 0.0 ? -1 : 1;
|
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sidev1 = s_num1 > 0.0 ? -1 : 1;
|
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
if (nears & 1)
|
if (nears & 1)
|
||||||
{
|
{
|
||||||
double dist = s_num2 * s_num2 * l;
|
double dist = s_num2 * s_num2 * l;
|
||||||
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
if (dist < SIDE_EPSILON*SIDE_EPSILON)
|
||||||
{
|
{
|
||||||
sidev2 = 0;
|
sidev[1] = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sidev2 = s_num2 > 0.0 ? -1 : 1;
|
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sidev2 = s_num2 > 0.0 ? -1 : 1;
|
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sidev1 = s_num1 > 0.0 ? -1 : 1;
|
sidev[0] = s_num1 > 0.0 ? -1 : 1;
|
||||||
sidev2 = s_num2 > 0.0 ? -1 : 1;
|
sidev[1] = s_num2 > 0.0 ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sidev1 | sidev2) == 0)
|
if ((sidev[0] | sidev[1]) == 0)
|
||||||
{ // seg is coplanar with the splitter, so use its orientation to determine
|
{ // seg is coplanar with the splitter, so use its orientation to determine
|
||||||
// which child it ends up in. If it faces the same direction as the splitter,
|
// which child it ends up in. If it faces the same direction as the splitter,
|
||||||
// it goes in front. Otherwise, it goes in back.
|
// it goes in front. Otherwise, it goes in back.
|
||||||
|
@ -132,13 +130,15 @@ int FNodeBuilder::ClassifyLineSSE2 (node_t &node, const FPrivSeg *seg, int &side
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (sidev1 <= 0 && sidev2 <= 0)
|
else if (sidev[0] <= 0 && sidev[1] <= 0)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (sidev1 >= 0 && sidev2 >= 0)
|
else if (sidev[0] >= 0 && sidev[1] >= 0)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -3790,7 +3790,7 @@ void P_SetupLevel (char *lumpname, int position)
|
||||||
};
|
};
|
||||||
leveldata.FindMapBounds ();
|
leveldata.FindMapBounds ();
|
||||||
UsingGLNodes |= genglnodes;
|
UsingGLNodes |= genglnodes;
|
||||||
FNodeBuilder builder (leveldata, polyspots, anchors, UsingGLNodes, CPU.bSSE2);
|
FNodeBuilder builder (leveldata, polyspots, anchors, UsingGLNodes);
|
||||||
delete[] vertexes;
|
delete[] vertexes;
|
||||||
builder.Extract (nodes, numnodes,
|
builder.Extract (nodes, numnodes,
|
||||||
segs, numsegs,
|
segs, numsegs,
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
#include "a_sharedglobal.h"
|
#include "a_sharedglobal.h"
|
||||||
#include "g_level.h"
|
#include "g_level.h"
|
||||||
#include "nodebuild.h"
|
#include "nodebuild.h"
|
||||||
#include "x86.h"
|
|
||||||
|
|
||||||
// State.
|
// State.
|
||||||
#include "doomstat.h"
|
#include "doomstat.h"
|
||||||
|
@ -1050,7 +1049,7 @@ static void R_BuildPolyBSP(subsector_t *sub)
|
||||||
{
|
{
|
||||||
PolyNodeBuilder.AddPolySegs(&pn->segs[0], (int)pn->segs.Size());
|
PolyNodeBuilder.AddPolySegs(&pn->segs[0], (int)pn->segs.Size());
|
||||||
}
|
}
|
||||||
PolyNodeBuilder.BuildMini(false, CPU.bSSE2);
|
PolyNodeBuilder.BuildMini(false);
|
||||||
if (sub->BSP == NULL)
|
if (sub->BSP == NULL)
|
||||||
{
|
{
|
||||||
sub->BSP = new FMiniBSP;
|
sub->BSP = new FMiniBSP;
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
OmitFramePointers="true"
|
OmitFramePointers="true"
|
||||||
WholeProgramOptimization="false"
|
WholeProgramOptimization="false"
|
||||||
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;"jpeg-6b";game-music-emu\gme;gdtoa;bzip2;lzma\C"
|
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;"jpeg-6b";game-music-emu\gme;gdtoa;bzip2;lzma\C"
|
||||||
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY"
|
PreprocessorDefinitions="NDEBUG,WIN32,_WIN32,_WINDOWS,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY,BACKPATCH"
|
||||||
StringPooling="true"
|
StringPooling="true"
|
||||||
ExceptionHandling="1"
|
ExceptionHandling="1"
|
||||||
RuntimeLibrary="0"
|
RuntimeLibrary="0"
|
||||||
|
@ -287,7 +287,7 @@
|
||||||
Name="VCCLCompilerTool"
|
Name="VCCLCompilerTool"
|
||||||
Optimization="0"
|
Optimization="0"
|
||||||
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;"jpeg-6b";game-music-emu\gme;gdtoa;bzip2;lzma\C"
|
AdditionalIncludeDirectories="src\win32;src\sound;src;zlib;src\g_shared;src\g_doom;src\g_raven;src\g_heretic;src\g_hexen;src\g_strife;"jpeg-6b";game-music-emu\gme;gdtoa;bzip2;lzma\C"
|
||||||
PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY"
|
PreprocessorDefinitions="WIN32,_DEBUG,_WIN32,_WINDOWS,_CRTDBG_MAP_ALLOC,HAVE_STRUPR,HAVE_FILELENGTH;NO_VA_COPY,BACKPATCH"
|
||||||
MinimalRebuild="true"
|
MinimalRebuild="true"
|
||||||
RuntimeLibrary="1"
|
RuntimeLibrary="1"
|
||||||
EnableFunctionLevelLinking="true"
|
EnableFunctionLevelLinking="true"
|
||||||
|
|
Loading…
Reference in a new issue