- use the worker threads to clear the stencil buffer

This commit is contained in:
Magnus Norddahl 2018-06-10 12:42:19 +02:00
parent 8486cd2c0e
commit de67393b4e
7 changed files with 66 additions and 20 deletions

View file

@ -59,10 +59,9 @@ PolyStencilBuffer *PolyStencilBuffer::Instance()
return &buffer; return &buffer;
} }
void PolyStencilBuffer::Clear(int newwidth, int newheight, uint8_t stencil_value) void PolyStencilBuffer::Resize(int newwidth, int newheight)
{ {
width = newwidth; width = newwidth;
height = newheight; height = newheight;
values.resize(width * height); values.resize(width * height);
memset(Values(), stencil_value, width * height);
} }

View file

@ -45,7 +45,7 @@ class PolyStencilBuffer
{ {
public: public:
static PolyStencilBuffer *Instance(); static PolyStencilBuffer *Instance();
void Clear(int newwidth, int newheight, uint8_t stencil_value = 0); void Resize(int newwidth, int newheight);
int Width() const { return width; } int Width() const { return width; }
int Height() const { return height; } int Height() const { return height; }
uint8_t *Values() { return values.data(); } uint8_t *Values() { return values.data(); }

View file

@ -41,9 +41,9 @@
static bool isBgraRenderTarget = false; static bool isBgraRenderTarget = false;
void PolyTriangleDrawer::ClearBuffers(DCanvas *canvas) void PolyTriangleDrawer::ResizeBuffers(DCanvas *canvas)
{ {
PolyStencilBuffer::Instance()->Clear(canvas->GetWidth(), canvas->GetHeight(), 0); PolyStencilBuffer::Instance()->Resize(canvas->GetWidth(), canvas->GetHeight());
PolyZBuffer::Instance()->Resize(canvas->GetPitch(), canvas->GetHeight()); PolyZBuffer::Instance()->Resize(canvas->GetPitch(), canvas->GetHeight());
} }
@ -52,6 +52,11 @@ bool PolyTriangleDrawer::IsBgra()
return isBgraRenderTarget; return isBgraRenderTarget;
} }
void PolyTriangleDrawer::ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value)
{
queue->Push<PolyClearStencilCommand>(value);
}
void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas) void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas)
{ {
uint8_t *dest = (uint8_t*)canvas->GetPixels(); uint8_t *dest = (uint8_t*)canvas->GetPixels();
@ -99,6 +104,21 @@ void PolyTriangleDrawer::SetWeaponScene(const DrawerCommandQueuePtr &queue, bool
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
void PolyTriangleThreadData::ClearStencil(uint8_t value)
{
auto buffer = PolyStencilBuffer::Instance();
int width = buffer->Width();
int height = buffer->Height();
uint8_t *data = buffer->Values();
data += core * width;
for (int y = core; y < height; y += num_cores)
{
memset(data, value, width);
data += num_cores * width;
}
}
void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, uint8_t *new_dest, int new_dest_width, int new_dest_height, int new_dest_pitch, bool new_dest_bgra) void PolyTriangleThreadData::SetViewport(int x, int y, int width, int height, uint8_t *new_dest, int new_dest_width, int new_dest_height, int new_dest_pitch, bool new_dest_bgra)
{ {
viewport_x = x; viewport_x = x;
@ -633,6 +653,17 @@ void PolySetWeaponSceneCommand::Execute(DrawerThread *thread)
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
PolyClearStencilCommand::PolyClearStencilCommand(uint8_t value) : value(value)
{
}
void PolyClearStencilCommand::Execute(DrawerThread *thread)
{
PolyTriangleThreadData::Get(thread)->ClearStencil(value);
}
/////////////////////////////////////////////////////////////////////////////
PolySetViewportCommand::PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra) PolySetViewportCommand::PolySetViewportCommand(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra)
: x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra) : x(x), y(y), width(width), height(height), dest(dest), dest_width(dest_width), dest_height(dest_height), dest_pitch(dest_pitch), dest_bgra(dest_bgra)
{ {

View file

@ -32,7 +32,8 @@
class PolyTriangleDrawer class PolyTriangleDrawer
{ {
public: public:
static void ClearBuffers(DCanvas *canvas); static void ResizeBuffers(DCanvas *canvas);
static void ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value);
static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas); static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas);
static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw); static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw);
static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided); static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided);
@ -47,6 +48,7 @@ class PolyTriangleThreadData
public: public:
PolyTriangleThreadData(int32_t core, int32_t num_cores) : core(core), num_cores(num_cores) { } PolyTriangleThreadData(int32_t core, int32_t num_cores) : core(core), num_cores(num_cores) { }
void ClearStencil(uint8_t value);
void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra); void SetViewport(int x, int y, int width, int height, uint8_t *dest, int dest_width, int dest_height, int dest_pitch, bool dest_bgra);
void SetTransform(const Mat4f *objectToClip, const Mat4f *objectToWorld); void SetTransform(const Mat4f *objectToClip, const Mat4f *objectToWorld);
void SetCullCCW(bool value) { ccw = value; } void SetCullCCW(bool value) { ccw = value; }
@ -142,6 +144,18 @@ private:
bool value; bool value;
}; };
class PolyClearStencilCommand : public DrawerCommand
{
public:
PolyClearStencilCommand(uint8_t value);
void Execute(DrawerThread *thread) override;
FString DebugInfo() override { return "PolyClearStencilCommand"; }
private:
uint8_t value;
};
class PolySetViewportCommand : public DrawerCommand class PolySetViewportCommand : public DrawerCommand
{ {
public: public:

View file

@ -162,7 +162,14 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines)
r_modelscene = r_models && Models.Size() > 0; r_modelscene = r_models && Models.Size() > 0;
ClearBuffers(); NextStencilValue = 0;
Threads.Clear();
Threads.MainThread()->SectorPortals.clear();
Threads.MainThread()->LinePortals.clear();
Threads.MainThread()->TranslucentObjects.clear();
PolyTriangleDrawer::ResizeBuffers(RenderTarget);
PolyTriangleDrawer::ClearStencil(Threads.MainThread()->DrawQueue, 0);
SetSceneViewport(); SetSceneViewport();
PolyPortalViewpoint mainViewpoint = SetupPerspectiveMatrix(); PolyPortalViewpoint mainViewpoint = SetupPerspectiveMatrix();
@ -184,16 +191,6 @@ void PolyRenderer::RenderRemainingPlayerSprites()
PlayerSprites.RenderRemainingSprites(); PlayerSprites.RenderRemainingSprites();
} }
void PolyRenderer::ClearBuffers()
{
Threads.Clear();
PolyTriangleDrawer::ClearBuffers(RenderTarget);
NextStencilValue = 0;
Threads.MainThread()->SectorPortals.clear();
Threads.MainThread()->LinePortals.clear();
Threads.MainThread()->TranslucentObjects.clear();
}
void PolyRenderer::SetSceneViewport() void PolyRenderer::SetSceneViewport()
{ {
using namespace swrenderer; using namespace swrenderer;

View file

@ -71,7 +71,6 @@ public:
private: private:
void RenderActorView(AActor *actor, bool dontmaplines); void RenderActorView(AActor *actor, bool dontmaplines);
void ClearBuffers();
void SetSceneViewport(); void SetSceneViewport();
RenderPolyPlayerSprites PlayerSprites; RenderPolyPlayerSprites PlayerSprites;

View file

@ -106,7 +106,10 @@ namespace swrenderer
r_modelscene = r_models && Models.Size() > 0; r_modelscene = r_models && Models.Size() > 0;
if (r_modelscene) if (r_modelscene)
PolyTriangleDrawer::ClearBuffers(viewport->RenderTarget); {
PolyTriangleDrawer::ResizeBuffers(viewport->RenderTarget);
PolyTriangleDrawer::ClearStencil(MainThread()->DrawQueue, 0);
}
if (r_clearbuffer != 0 || r_debug_draw != 0) if (r_clearbuffer != 0 || r_debug_draw != 0)
{ {
@ -271,6 +274,9 @@ namespace swrenderer
thread->OpaquePass->ResetFakingUnderwater(); // [RH] Hack to make windows into underwater areas possible thread->OpaquePass->ResetFakingUnderwater(); // [RH] Hack to make windows into underwater areas possible
thread->Portal->SetMainPortal(); thread->Portal->SetMainPortal();
if (r_modelscene && thread->MainThread)
PolyTriangleDrawer::ClearStencil(MainThread()->DrawQueue, 0);
PolyTriangleDrawer::SetViewport(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight, thread->Viewport->RenderTarget); PolyTriangleDrawer::SetViewport(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight, thread->Viewport->RenderTarget);
// Cull things outside the range seen by this thread // Cull things outside the range seen by this thread
@ -376,7 +382,7 @@ namespace swrenderer
viewactive = true; viewactive = true;
viewport->SetViewport(MainThread(), width, height, MainThread()->Viewport->viewwindow.WidescreenRatio); viewport->SetViewport(MainThread(), width, height, MainThread()->Viewport->viewwindow.WidescreenRatio);
if (r_modelscene) if (r_modelscene)
PolyTriangleDrawer::ClearBuffers(viewport->RenderTarget); PolyTriangleDrawer::ResizeBuffers(viewport->RenderTarget);
// Render: // Render:
RenderActorView(actor, dontmaplines); RenderActorView(actor, dontmaplines);