From cb6d4715601e9524fbf4bd0a1f596e1d6730c34f Mon Sep 17 00:00:00 2001 From: Ted John Date: Tue, 27 Apr 2021 01:27:49 +0100 Subject: [PATCH] Increase paint struct limit by using shared pool --- src/openrct2/interface/Viewport.cpp | 2 + src/openrct2/paint/Paint.cpp | 42 +++++++------- src/openrct2/paint/Paint.h | 88 ++++++++++++++++++++--------- src/openrct2/paint/Painter.cpp | 4 +- src/openrct2/paint/Painter.h | 1 + 5 files changed, 90 insertions(+), 47 deletions(-) diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index b99c5534f8..b4b46a1b8d 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -852,6 +852,7 @@ static void record_session(const paint_session* session, std::vectorat(record_index); @@ -867,6 +868,7 @@ static void record_session(const paint_session* session, std::vector( quad ? int(quad - &session->PaintStructs[0].basic) : std::size(session->Quadrants)); } + */ } static void viewport_fill_column(paint_session* session, std::vector* recorded_sessions, size_t record_index) diff --git a/src/openrct2/paint/Paint.cpp b/src/openrct2/paint/Paint.cpp index 0bb434b384..f51955f23b 100644 --- a/src/openrct2/paint/Paint.cpp +++ b/src/openrct2/paint/Paint.cpp @@ -139,9 +139,6 @@ static paint_struct* CreateNormalPaintStruct( paint_session* session, const uint32_t image_id, const CoordsXYZ& offset, const CoordsXYZ& boundBoxSize, const CoordsXYZ& boundBoxOffset) { - if (session->NoPaintStructsAvailable()) - return nullptr; - auto* const g1 = gfx_get_g1_element(image_id & 0x7FFFF); if (g1 == nullptr) { @@ -162,7 +159,12 @@ static paint_struct* CreateNormalPaintStruct( const auto rotBoundBoxOffset = CoordsXYZ{ boundBoxOffset.Rotate(swappedRotation), boundBoxOffset.z }; const auto rotBoundBoxSize = RotateBoundBoxSize(boundBoxSize, session->CurrentRotation); - paint_struct* ps = session->AllocateNormalPaintEntry(); + auto* ps = session->AllocateNormalPaintEntry(); + if (ps == nullptr) + { + return nullptr; + } + ps->image_id = image_id; ps->x = imagePos.x; ps->y = imagePos.y; @@ -847,18 +849,18 @@ paint_struct* PaintAddImageAsChild( */ bool PaintAttachToPreviousAttach(paint_session* session, uint32_t image_id, int16_t x, int16_t y) { - if (session->NoPaintStructsAvailable()) - { - return false; - } - - attached_paint_struct* previousAttachedPS = session->LastAttachedPS; + auto* previousAttachedPS = session->LastAttachedPS; if (previousAttachedPS == nullptr) { return PaintAttachToPreviousPS(session, image_id, x, y); } - attached_paint_struct* ps = session->AllocateAttachedPaintEntry(); + auto* ps = session->AllocateAttachedPaintEntry(); + if (ps == nullptr) + { + return false; + } + ps->image_id = image_id; ps->x = x; ps->y = y; @@ -880,18 +882,18 @@ bool PaintAttachToPreviousAttach(paint_session* session, uint32_t image_id, int1 */ bool PaintAttachToPreviousPS(paint_session* session, uint32_t image_id, int16_t x, int16_t y) { - if (session->NoPaintStructsAvailable()) - { - return false; - } - - paint_struct* masterPs = session->LastPS; + auto* masterPs = session->LastPS; if (masterPs == nullptr) { return false; } - attached_paint_struct* ps = session->AllocateAttachedPaintEntry(); + auto* ps = session->AllocateAttachedPaintEntry(); + if (ps == nullptr) + { + return false; + } + ps->image_id = image_id; ps->x = x; ps->y = y; @@ -918,7 +920,8 @@ void PaintFloatingMoneyEffect( paint_session* session, money32 amount, rct_string_id string_id, int16_t y, int16_t z, int8_t y_offsets[], int16_t offset_x, uint32_t rotation) { - if (session->NoPaintStructsAvailable()) + auto* ps = session->AllocateStringPaintEntry(); + if (ps == nullptr) { return; } @@ -930,7 +933,6 @@ void PaintFloatingMoneyEffect( }; const auto coord = translate_3d_to_2d_with_z(rotation, position); - paint_string_struct* ps = session->AllocateStringPaintEntry(); ps->string_id = string_id; ps->next = nullptr; ps->args[0] = amount; diff --git a/src/openrct2/paint/Paint.h b/src/openrct2/paint/Paint.h index 664017af54..47ba653f95 100644 --- a/src/openrct2/paint/Paint.h +++ b/src/openrct2/paint/Paint.h @@ -15,6 +15,9 @@ #include "../interface/Colour.h" #include "../world/Location.hpp" +#include +#include + struct TileElement; enum class ViewportInteractionItem : uint8_t; @@ -135,10 +138,33 @@ struct tunnel_entry #define MAX_PAINT_QUADRANTS 512 #define TUNNEL_MAX_COUNT 65 +struct PaintStructPool +{ + FixedVector PaintStructs; + std::mutex _mutex; + + paint_entry* Allocate() + { + std::lock_guard guard(_mutex); + + if (PaintStructs.size() < PaintStructs.capacity()) + { + return &PaintStructs.emplace_back(); + } + return nullptr; + } + + void Clear() + { + PaintStructs.clear(); + } +}; + struct paint_session { rct_drawpixelinfo DPI; - FixedVector PaintStructs; + // FixedVector PaintStructs; + PaintStructPool* SharedPaintStructPool; paint_struct* Quadrants[MAX_PAINT_QUADRANTS]; paint_struct* LastPS; paint_string_struct* PSStringHead; @@ -169,36 +195,46 @@ struct paint_session uint16_t WaterHeight; uint32_t TrackColours[4]; - constexpr bool NoPaintStructsAvailable() noexcept + paint_struct* AllocateNormalPaintEntry() noexcept { - return PaintStructs.size() >= PaintStructs.capacity(); - } - - constexpr paint_struct* AllocateNormalPaintEntry() noexcept - { - LastPS = &PaintStructs.emplace_back().basic; - return LastPS; - } - - constexpr attached_paint_struct* AllocateAttachedPaintEntry() noexcept - { - LastAttachedPS = &PaintStructs.emplace_back().attached; - return LastAttachedPS; - } - - constexpr paint_string_struct* AllocateStringPaintEntry() noexcept - { - auto* string = &PaintStructs.emplace_back().string; - if (LastPSString == nullptr) + auto* entry = SharedPaintStructPool->Allocate(); + if (entry != nullptr) { - PSStringHead = string; + LastPS = &entry->basic; + return LastPS; } - else + return nullptr; + } + + attached_paint_struct* AllocateAttachedPaintEntry() noexcept + { + auto* entry = SharedPaintStructPool->Allocate(); + if (entry != nullptr) { - LastPSString->next = string; + LastAttachedPS = &entry->attached; + return LastAttachedPS; } - LastPSString = string; - return LastPSString; + return nullptr; + } + + paint_string_struct* AllocateStringPaintEntry() noexcept + { + auto* entry = SharedPaintStructPool->Allocate(); + if (entry != nullptr) + { + auto* string = &entry->string; + if (LastPSString == nullptr) + { + PSStringHead = string; + } + else + { + LastPSString->next = string; + } + LastPSString = string; + return LastPSString; + } + return nullptr; } }; diff --git a/src/openrct2/paint/Painter.cpp b/src/openrct2/paint/Painter.cpp index b9d6d0a3c2..9364b01160 100644 --- a/src/openrct2/paint/Painter.cpp +++ b/src/openrct2/paint/Painter.cpp @@ -37,6 +37,8 @@ Painter::Painter(const std::shared_ptr& uiContext) void Painter::Paint(IDrawingEngine& de) { + _paintStructPool.Clear(); + auto dpi = de.GetDrawingPixelInfo(); if (gIntroState != IntroState::None) { @@ -151,7 +153,7 @@ paint_session* Painter::CreateSession(rct_drawpixelinfo* dpi, uint32_t viewFlags session->ViewFlags = viewFlags; session->QuadrantBackIndex = std::numeric_limits::max(); session->QuadrantFrontIndex = 0; - session->PaintStructs.clear(); + session->SharedPaintStructPool = &_paintStructPool; std::fill(std::begin(session->Quadrants), std::end(session->Quadrants), nullptr); session->LastPS = nullptr; diff --git a/src/openrct2/paint/Painter.h b/src/openrct2/paint/Painter.h index e479a0e93c..42528d5d0a 100644 --- a/src/openrct2/paint/Painter.h +++ b/src/openrct2/paint/Painter.h @@ -38,6 +38,7 @@ namespace OpenRCT2 std::shared_ptr const _uiContext; std::vector> _paintSessionPool; std::vector _freePaintSessions; + PaintStructPool _paintStructPool; time_t _lastSecond = 0; int32_t _currentFPS = 0; int32_t _frames = 0;