diff --git a/src/polyrenderer/drawers/poly_buffer.cpp b/src/polyrenderer/drawers/poly_buffer.cpp index 2506bce7e..eb1b5e1e4 100644 --- a/src/polyrenderer/drawers/poly_buffer.cpp +++ b/src/polyrenderer/drawers/poly_buffer.cpp @@ -59,10 +59,9 @@ PolyStencilBuffer *PolyStencilBuffer::Instance() return &buffer; } -void PolyStencilBuffer::Clear(int newwidth, int newheight, uint8_t stencil_value) +void PolyStencilBuffer::Resize(int newwidth, int newheight) { width = newwidth; height = newheight; values.resize(width * height); - memset(Values(), stencil_value, width * height); } diff --git a/src/polyrenderer/drawers/poly_buffer.h b/src/polyrenderer/drawers/poly_buffer.h index af4a78b3a..160aa1067 100644 --- a/src/polyrenderer/drawers/poly_buffer.h +++ b/src/polyrenderer/drawers/poly_buffer.h @@ -45,7 +45,7 @@ class PolyStencilBuffer { public: 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 Height() const { return height; } uint8_t *Values() { return values.data(); } diff --git a/src/polyrenderer/drawers/poly_triangle.cpp b/src/polyrenderer/drawers/poly_triangle.cpp index 0a598ec2f..5b380da8d 100644 --- a/src/polyrenderer/drawers/poly_triangle.cpp +++ b/src/polyrenderer/drawers/poly_triangle.cpp @@ -41,9 +41,9 @@ 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()); } @@ -52,6 +52,11 @@ bool PolyTriangleDrawer::IsBgra() return isBgraRenderTarget; } +void PolyTriangleDrawer::ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value) +{ + queue->Push(value); +} + void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas) { 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) { 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) : 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) { diff --git a/src/polyrenderer/drawers/poly_triangle.h b/src/polyrenderer/drawers/poly_triangle.h index a323a941a..c63e2e6ac 100644 --- a/src/polyrenderer/drawers/poly_triangle.h +++ b/src/polyrenderer/drawers/poly_triangle.h @@ -32,7 +32,8 @@ class PolyTriangleDrawer { 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 SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw); static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided); @@ -47,6 +48,7 @@ class PolyTriangleThreadData public: 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 SetTransform(const Mat4f *objectToClip, const Mat4f *objectToWorld); void SetCullCCW(bool value) { ccw = value; } @@ -142,6 +144,18 @@ private: 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 { public: diff --git a/src/polyrenderer/poly_renderer.cpp b/src/polyrenderer/poly_renderer.cpp index ec2f7a628..43622b1b4 100644 --- a/src/polyrenderer/poly_renderer.cpp +++ b/src/polyrenderer/poly_renderer.cpp @@ -162,7 +162,14 @@ void PolyRenderer::RenderActorView(AActor *actor, bool dontmaplines) 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(); PolyPortalViewpoint mainViewpoint = SetupPerspectiveMatrix(); @@ -184,16 +191,6 @@ void PolyRenderer::RenderRemainingPlayerSprites() 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() { using namespace swrenderer; diff --git a/src/polyrenderer/poly_renderer.h b/src/polyrenderer/poly_renderer.h index 0a1f70024..20a5a61be 100644 --- a/src/polyrenderer/poly_renderer.h +++ b/src/polyrenderer/poly_renderer.h @@ -71,7 +71,6 @@ public: private: void RenderActorView(AActor *actor, bool dontmaplines); - void ClearBuffers(); void SetSceneViewport(); RenderPolyPlayerSprites PlayerSprites; diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index a50284ace..18808c4c6 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -106,7 +106,10 @@ namespace swrenderer r_modelscene = r_models && Models.Size() > 0; if (r_modelscene) - PolyTriangleDrawer::ClearBuffers(viewport->RenderTarget); + { + PolyTriangleDrawer::ResizeBuffers(viewport->RenderTarget); + PolyTriangleDrawer::ClearStencil(MainThread()->DrawQueue, 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->Portal->SetMainPortal(); + if (r_modelscene && thread->MainThread) + PolyTriangleDrawer::ClearStencil(MainThread()->DrawQueue, 0); + PolyTriangleDrawer::SetViewport(thread->DrawQueue, viewwindowx, viewwindowy, viewwidth, viewheight, thread->Viewport->RenderTarget); // Cull things outside the range seen by this thread @@ -376,7 +382,7 @@ namespace swrenderer viewactive = true; viewport->SetViewport(MainThread(), width, height, MainThread()->Viewport->viewwindow.WidescreenRatio); if (r_modelscene) - PolyTriangleDrawer::ClearBuffers(viewport->RenderTarget); + PolyTriangleDrawer::ResizeBuffers(viewport->RenderTarget); // Render: RenderActorView(actor, dontmaplines);