mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-11 15:21:51 +00:00
Hook up thread slices and eliminate some statics hiding in misc functions
This commit is contained in:
parent
f50532af8a
commit
d9e545a519
12 changed files with 154 additions and 76 deletions
|
@ -64,7 +64,6 @@ namespace swrenderer
|
|||
|
||||
void SWRenderLine::Render(seg_t *line, subsector_t *subsector, sector_t *sector, sector_t *fakebacksector, VisiblePlane *linefloorplane, VisiblePlane *lineceilingplane, bool infog, FDynamicColormap *colormap)
|
||||
{
|
||||
static sector_t tempsec; // killough 3/8/98: ceiling/water hack
|
||||
bool solid;
|
||||
DVector2 pt1, pt2;
|
||||
|
||||
|
@ -284,11 +283,7 @@ namespace swrenderer
|
|||
rw_floorstat = wallbottom.Project(frontsector->floorplane, &WallC, curline, renderportal->MirrorFlags & RF_XFLIP);
|
||||
}
|
||||
|
||||
static SWRenderLine *self = this;
|
||||
bool visible = Thread->ClipSegments->Clip(WallC.sx1, WallC.sx2, solid, [](int x1, int x2) -> bool
|
||||
{
|
||||
return self->RenderWallSegment(x1, x2);
|
||||
});
|
||||
bool visible = Thread->ClipSegments->Clip(WallC.sx1, WallC.sx2, solid, this);
|
||||
|
||||
if (visible)
|
||||
{
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "vectors.h"
|
||||
#include "r_wallsetup.h"
|
||||
#include "swrenderer/segments/r_clipsegment.h"
|
||||
|
||||
struct seg_t;
|
||||
struct subsector_t;
|
||||
|
@ -48,7 +49,7 @@ namespace swrenderer
|
|||
void InitFromLine(RenderThread *thread, const DVector2 &left, const DVector2 &right);
|
||||
};
|
||||
|
||||
class SWRenderLine
|
||||
class SWRenderLine : VisibleSegmentRenderer
|
||||
{
|
||||
public:
|
||||
SWRenderLine(RenderThread *thread);
|
||||
|
@ -57,7 +58,7 @@ namespace swrenderer
|
|||
RenderThread *Thread = nullptr;
|
||||
|
||||
private:
|
||||
bool RenderWallSegment(int x1, int x2);
|
||||
bool RenderWallSegment(int x1, int x2) override;
|
||||
void SetWallVariables(bool needlights);
|
||||
void RenderWallSegmentTextures(int x1, int x2);
|
||||
|
||||
|
@ -133,5 +134,7 @@ namespace swrenderer
|
|||
ProjectedWallLine wallupper;
|
||||
ProjectedWallLine walllower;
|
||||
ProjectedWallTexcoords walltexcoords;
|
||||
|
||||
sector_t tempsec; // killough 3/8/98: ceiling/water hack
|
||||
};
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "swrenderer/line/r_walldraw.h"
|
||||
#include "swrenderer/line/r_wallsetup.h"
|
||||
#include "swrenderer/r_renderthread.h"
|
||||
#include "swrenderer/r_memory.h"
|
||||
|
||||
namespace swrenderer
|
||||
{
|
||||
|
@ -188,14 +189,22 @@ namespace swrenderer
|
|||
drawerargs.dc_viewpos.Z = (float)((viewport->CenterY - y1 - 0.5) / viewport->InvZtoScale * zcol);
|
||||
drawerargs.dc_viewpos_step.Z = (float)(-zcol / viewport->InvZtoScale);
|
||||
|
||||
static TriLight lightbuffer[64 * 1024];
|
||||
static int nextlightindex = 0;
|
||||
// Calculate max lights that can touch column so we can allocate memory for the list
|
||||
int max_lights = 0;
|
||||
FLightNode *cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
max_lights++;
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
||||
drawerargs.dc_num_lights = 0;
|
||||
drawerargs.dc_lights = Thread->FrameMemory->AllocMemory<TriLight>(max_lights);
|
||||
|
||||
// Setup lights for column
|
||||
drawerargs.dc_num_lights = 0;
|
||||
drawerargs.dc_lights = lightbuffer + nextlightindex;
|
||||
FLightNode *cur_node = light_list;
|
||||
while (cur_node && nextlightindex < 64 * 1024)
|
||||
cur_node = light_list;
|
||||
while (cur_node)
|
||||
{
|
||||
if (!(cur_node->lightsource->flags2&MF2_DORMANT))
|
||||
{
|
||||
|
@ -220,7 +229,6 @@ namespace swrenderer
|
|||
uint32_t green = cur_node->lightsource->GetGreen();
|
||||
uint32_t blue = cur_node->lightsource->GetBlue();
|
||||
|
||||
nextlightindex++;
|
||||
auto &light = drawerargs.dc_lights[drawerargs.dc_num_lights++];
|
||||
light.x = lconstant;
|
||||
light.y = nlconstant;
|
||||
|
@ -232,9 +240,6 @@ namespace swrenderer
|
|||
|
||||
cur_node = cur_node->nextLight;
|
||||
}
|
||||
|
||||
if (nextlightindex == 64 * 1024)
|
||||
nextlightindex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -56,9 +56,10 @@
|
|||
|
||||
namespace swrenderer
|
||||
{
|
||||
RenderThread::RenderThread(RenderScene *scene)
|
||||
RenderThread::RenderThread(RenderScene *scene, bool mainThread)
|
||||
{
|
||||
Scene = scene;
|
||||
MainThread = mainThread;
|
||||
FrameMemory = std::make_unique<RenderMemory>();
|
||||
DrawQueue = std::make_shared<DrawerCommandQueue>(this);
|
||||
OpaquePass = std::make_unique<RenderOpaquePass>(this);
|
||||
|
|
|
@ -47,12 +47,13 @@ namespace swrenderer
|
|||
class RenderThread
|
||||
{
|
||||
public:
|
||||
RenderThread(RenderScene *scene);
|
||||
RenderThread(RenderScene *scene, bool mainThread = true);
|
||||
~RenderThread();
|
||||
|
||||
RenderScene *Scene;
|
||||
int X1 = 0;
|
||||
int X2 = MAXWIDTH;
|
||||
bool MainThread = false;
|
||||
|
||||
std::unique_ptr<RenderMemory> FrameMemory;
|
||||
std::unique_ptr<RenderOpaquePass> OpaquePass;
|
||||
|
@ -65,7 +66,11 @@ namespace swrenderer
|
|||
std::unique_ptr<DrawSegmentList> DrawSegments;
|
||||
std::unique_ptr<RenderClipSegment> ClipSegments;
|
||||
DrawerCommandQueuePtr DrawQueue;
|
||||
|
||||
|
||||
// VisibleSprite working buffers
|
||||
short clipbot[MAXWIDTH];
|
||||
short cliptop[MAXWIDTH];
|
||||
|
||||
SWPixelFormatDrawers *Drawers();
|
||||
|
||||
private:
|
||||
|
|
|
@ -52,6 +52,8 @@
|
|||
EXTERN_CVAR(Bool, r_shadercolormaps)
|
||||
EXTERN_CVAR(Int, r_clearbuffer)
|
||||
|
||||
CVAR(Bool, r_scene_multithreaded, false, 0);
|
||||
|
||||
namespace swrenderer
|
||||
{
|
||||
cycle_t WallCycles, PlaneCycles, MaskedCycles, WallScanCycles;
|
||||
|
@ -100,8 +102,19 @@ namespace swrenderer
|
|||
{
|
||||
MainThread()->DrawQueue->Push<ApplySpecialColormapRGBACommand>(CameraLight::Instance()->ShaderColormap(), screen);
|
||||
}
|
||||
|
||||
DrawerThreads::Execute({ MainThread()->DrawQueue });
|
||||
|
||||
RenderDrawQueues();
|
||||
}
|
||||
|
||||
void RenderScene::RenderDrawQueues()
|
||||
{
|
||||
// Use reverse order so main thread is drawn last
|
||||
std::vector<DrawerCommandQueuePtr> queues;
|
||||
for (auto it = Threads.rbegin(); it != Threads.rend(); ++it)
|
||||
{
|
||||
queues.push_back((*it)->DrawQueue);
|
||||
}
|
||||
DrawerThreads::Execute(queues);
|
||||
}
|
||||
|
||||
void RenderScene::RenderActorView(AActor *actor, bool dontmaplines)
|
||||
|
@ -132,48 +145,7 @@ namespace swrenderer
|
|||
camera->renderflags |= RF_INVISIBLE;
|
||||
}
|
||||
|
||||
MainThread()->FrameMemory->Clear();
|
||||
MainThread()->Clip3DFloors->Cleanup();
|
||||
MainThread()->Clip3DFloors->ResetClip(); // reset clips (floor/ceiling)
|
||||
MainThread()->Portal->CopyStackedViewParameters();
|
||||
MainThread()->ClipSegments->Clear(0, viewwidth);
|
||||
MainThread()->DrawSegments->Clear();
|
||||
MainThread()->PlaneList->Clear();
|
||||
MainThread()->TranslucentPass->Clear();
|
||||
MainThread()->OpaquePass->ClearClip();
|
||||
MainThread()->OpaquePass->ResetFakingUnderwater(); // [RH] Hack to make windows into underwater areas possible
|
||||
MainThread()->Portal->SetMainPortal();
|
||||
|
||||
// Cull things outside the range seen by this thread
|
||||
if (MainThread()->X1 > 0)
|
||||
MainThread()->ClipSegments->Clip(0, MainThread()->X1, true, [](int, int) { return true; });
|
||||
if (MainThread()->X2 < viewwidth)
|
||||
MainThread()->ClipSegments->Clip(MainThread()->X2, viewwidth, true, [](int, int) { return true; });
|
||||
|
||||
WallCycles.Clock();
|
||||
MainThread()->OpaquePass->RenderScene();
|
||||
MainThread()->Clip3DFloors->ResetClip(); // reset clips (floor/ceiling)
|
||||
WallCycles.Unclock();
|
||||
|
||||
NetUpdate();
|
||||
|
||||
if (viewactive)
|
||||
{
|
||||
PlaneCycles.Clock();
|
||||
MainThread()->PlaneList->Render();
|
||||
MainThread()->Portal->RenderPlanePortals();
|
||||
PlaneCycles.Unclock();
|
||||
|
||||
MainThread()->Portal->RenderLinePortals();
|
||||
|
||||
NetUpdate();
|
||||
|
||||
MaskedCycles.Clock();
|
||||
MainThread()->TranslucentPass->Render();
|
||||
MaskedCycles.Unclock();
|
||||
|
||||
NetUpdate();
|
||||
}
|
||||
RenderThreadSlices();
|
||||
|
||||
camera->renderflags = savedflags;
|
||||
interpolator.RestoreInterpolations();
|
||||
|
@ -186,6 +158,94 @@ namespace swrenderer
|
|||
}
|
||||
}
|
||||
|
||||
void RenderScene::RenderThreadSlices()
|
||||
{
|
||||
int numThreads = r_scene_multithreaded ? 8 : 1;
|
||||
|
||||
while (Threads.size() > (size_t)numThreads)
|
||||
{
|
||||
Threads.pop_back();
|
||||
}
|
||||
|
||||
while (Threads.size() < (size_t)numThreads)
|
||||
{
|
||||
Threads.push_back(std::make_unique<RenderThread>(this));
|
||||
}
|
||||
|
||||
for (int i = 0; i < numThreads; i++)
|
||||
{
|
||||
Threads[i]->X1 = viewwidth * i / numThreads;
|
||||
Threads[i]->X2 = viewwidth * (i + 1) / numThreads;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numThreads; i++)
|
||||
{
|
||||
RenderThreadSlice(Threads[i].get());
|
||||
}
|
||||
}
|
||||
|
||||
void RenderScene::RenderThreadSlice(RenderThread *thread)
|
||||
{
|
||||
thread->FrameMemory->Clear();
|
||||
thread->Clip3DFloors->Cleanup();
|
||||
thread->Clip3DFloors->ResetClip(); // reset clips (floor/ceiling)
|
||||
thread->Portal->CopyStackedViewParameters();
|
||||
thread->ClipSegments->Clear(0, viewwidth);
|
||||
thread->DrawSegments->Clear();
|
||||
thread->PlaneList->Clear();
|
||||
thread->TranslucentPass->Clear();
|
||||
thread->OpaquePass->ClearClip();
|
||||
thread->OpaquePass->ResetFakingUnderwater(); // [RH] Hack to make windows into underwater areas possible
|
||||
thread->Portal->SetMainPortal();
|
||||
|
||||
// Cull things outside the range seen by this thread
|
||||
VisibleSegmentRenderer visitor;
|
||||
if (thread->X1 > 0)
|
||||
thread->ClipSegments->Clip(0, thread->X1, true, &visitor);
|
||||
if (thread->X2 < viewwidth)
|
||||
thread->ClipSegments->Clip(thread->X2, viewwidth, true, &visitor);
|
||||
|
||||
if (thread->MainThread)
|
||||
WallCycles.Clock();
|
||||
|
||||
thread->OpaquePass->RenderScene();
|
||||
thread->Clip3DFloors->ResetClip(); // reset clips (floor/ceiling)
|
||||
|
||||
if (thread == MainThread())
|
||||
WallCycles.Unclock();
|
||||
|
||||
if (thread->MainThread)
|
||||
NetUpdate();
|
||||
|
||||
if (viewactive)
|
||||
{
|
||||
if (thread->MainThread)
|
||||
PlaneCycles.Clock();
|
||||
|
||||
thread->PlaneList->Render();
|
||||
thread->Portal->RenderPlanePortals();
|
||||
|
||||
if (thread->MainThread)
|
||||
PlaneCycles.Unclock();
|
||||
|
||||
thread->Portal->RenderLinePortals();
|
||||
|
||||
if (thread->MainThread)
|
||||
NetUpdate();
|
||||
|
||||
if (thread->MainThread)
|
||||
MaskedCycles.Clock();
|
||||
|
||||
thread->TranslucentPass->Render();
|
||||
|
||||
if (thread->MainThread)
|
||||
MaskedCycles.Unclock();
|
||||
|
||||
if (thread->MainThread)
|
||||
NetUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void RenderScene::RenderViewToCanvas(AActor *actor, DCanvas *canvas, int x, int y, int width, int height, bool dontmaplines)
|
||||
{
|
||||
auto viewport = RenderViewport::Instance();
|
||||
|
@ -202,8 +262,7 @@ namespace swrenderer
|
|||
viewport->SetViewport(width, height, WidescreenRatio);
|
||||
|
||||
RenderActorView(actor, dontmaplines);
|
||||
|
||||
DrawerThreads::Execute({ MainThread()->DrawQueue });
|
||||
RenderDrawQueues();
|
||||
|
||||
viewport->RenderTarget = screen;
|
||||
|
||||
|
|
|
@ -46,6 +46,9 @@ namespace swrenderer
|
|||
|
||||
private:
|
||||
void RenderActorView(AActor *actor, bool dontmaplines = false);
|
||||
void RenderDrawQueues();
|
||||
void RenderThreadSlices();
|
||||
void RenderThreadSlice(RenderThread *thread);
|
||||
|
||||
bool dontmaplines = false;
|
||||
int clearcolor = 0;
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace swrenderer
|
|||
return true;
|
||||
}
|
||||
|
||||
bool RenderClipSegment::Clip(int first, int last, bool solid, VisibleSegmentCallback callback)
|
||||
bool RenderClipSegment::Clip(int first, int last, bool solid, VisibleSegmentRenderer *visitor)
|
||||
{
|
||||
cliprange_t *next, *start;
|
||||
int i, j;
|
||||
|
@ -104,7 +104,7 @@ namespace swrenderer
|
|||
if (last <= start->first)
|
||||
{
|
||||
// Post is entirely visible (above start).
|
||||
if (!callback(first, last))
|
||||
if (!visitor->RenderWallSegment(first, last))
|
||||
return true;
|
||||
|
||||
// Insert a new clippost for solid walls.
|
||||
|
@ -131,7 +131,7 @@ namespace swrenderer
|
|||
}
|
||||
|
||||
// There is a fragment above *start.
|
||||
if (callback(first, start->first) && solid)
|
||||
if (visitor->RenderWallSegment(first, start->first) && solid)
|
||||
{
|
||||
start->first = first; // Adjust the clip size for solid walls
|
||||
}
|
||||
|
@ -146,7 +146,7 @@ namespace swrenderer
|
|||
while (last >= (next + 1)->first)
|
||||
{
|
||||
// There is a fragment between two posts.
|
||||
clipsegment = callback(next->last, (next + 1)->first);
|
||||
clipsegment = visitor->RenderWallSegment(next->last, (next + 1)->first);
|
||||
next++;
|
||||
|
||||
if (last <= next->last)
|
||||
|
@ -158,7 +158,7 @@ namespace swrenderer
|
|||
}
|
||||
|
||||
// There is a fragment after *next.
|
||||
clipsegment = callback(next->last, last);
|
||||
clipsegment = visitor->RenderWallSegment(next->last, last);
|
||||
|
||||
crunch:
|
||||
if (!clipsegment)
|
||||
|
|
|
@ -17,11 +17,18 @@ namespace swrenderer
|
|||
{
|
||||
typedef bool(*VisibleSegmentCallback)(int x1, int x2);
|
||||
|
||||
class VisibleSegmentRenderer
|
||||
{
|
||||
public:
|
||||
virtual ~VisibleSegmentRenderer() { }
|
||||
virtual bool RenderWallSegment(int x1, int x2) { return true; }
|
||||
};
|
||||
|
||||
class RenderClipSegment
|
||||
{
|
||||
public:
|
||||
void Clear(short left, short right);
|
||||
bool Clip(int x1, int x2, bool solid, VisibleSegmentCallback callback);
|
||||
bool Clip(int x1, int x2, bool solid, VisibleSegmentRenderer *visitor);
|
||||
bool Check(int first, int last);
|
||||
bool IsVisible(int x1, int x2);
|
||||
|
||||
|
|
|
@ -78,7 +78,6 @@ namespace swrenderer
|
|||
DPSprite* psp;
|
||||
DPSprite* weapon;
|
||||
sector_t* sec = NULL;
|
||||
static sector_t tempsec;
|
||||
int floorlight, ceilinglight;
|
||||
F3DFloor *rover;
|
||||
|
||||
|
|
|
@ -88,5 +88,6 @@ namespace swrenderer
|
|||
enum { BASEYCENTER = 100 };
|
||||
|
||||
TArray<HWAccelPlayerSprite> AcceleratedSprites;
|
||||
sector_t tempsec;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -43,8 +43,8 @@ namespace swrenderer
|
|||
{
|
||||
void VisibleSprite::Render(RenderThread *thread)
|
||||
{
|
||||
static short clipbot[MAXWIDTH];
|
||||
static short cliptop[MAXWIDTH];
|
||||
short *clipbot = thread->clipbot;
|
||||
short *cliptop = thread->cliptop;
|
||||
|
||||
VisibleSprite *spr = this;
|
||||
|
||||
|
|
Loading…
Reference in a new issue