1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-15 03:52:40 +01:00

Close #21825: Only lock OpenGL texture cache when using multi-threading (#21952)

Fixes #21825 by making 'DrawingLocks' which lock only if multi threaded drawing is enabled. Refactors TTF.cpp to use this.

Also cleans up some header files, modernises constants, and removes code to avoid using shared_mutex on MacOS builds. This was originally added because older versions of MacOS didn't support this in the STL.
This commit is contained in:
mrmbernardi
2024-05-05 12:54:50 +02:00
committed by GitHub
parent f3bb57a54c
commit 489ae58c5c
6 changed files with 84 additions and 62 deletions

View File

@@ -21,11 +21,11 @@
using namespace OpenRCT2::Ui; using namespace OpenRCT2::Ui;
constexpr uint32_t UNUSED_INDEX = 0xFFFFFFFF; constexpr uint32_t kUnusedIndex = 0xFFFFFFFF;
TextureCache::TextureCache() TextureCache::TextureCache()
{ {
std::fill(_indexMap.begin(), _indexMap.end(), UNUSED_INDEX); std::fill(_indexMap.begin(), _indexMap.end(), kUnusedIndex);
} }
TextureCache::~TextureCache() TextureCache::~TextureCache()
@@ -38,13 +38,13 @@ void TextureCache::InvalidateImage(ImageIndex image)
unique_lock lock(_mutex); unique_lock lock(_mutex);
uint32_t index = _indexMap[image]; uint32_t index = _indexMap[image];
if (index == UNUSED_INDEX) if (index == kUnusedIndex)
return; return;
AtlasTextureInfo& elem = _textureCache.at(index); AtlasTextureInfo& elem = _textureCache.at(index);
_atlases[elem.index].Free(elem); _atlases[elem.index].Free(elem);
_indexMap[image] = UNUSED_INDEX; _indexMap[image] = kUnusedIndex;
if (index == _textureCache.size() - 1) if (index == _textureCache.size() - 1)
{ {
@@ -76,7 +76,7 @@ BasicTextureInfo TextureCache::GetOrLoadImageTexture(const ImageId imageId)
shared_lock lock(_mutex); shared_lock lock(_mutex);
index = _indexMap[imageId.GetIndex()]; index = _indexMap[imageId.GetIndex()];
if (index != UNUSED_INDEX) if (index != kUnusedIndex)
{ {
const auto& info = _textureCache[index]; const auto& info = _textureCache[index];
return { return {
@@ -144,7 +144,7 @@ BasicTextureInfo TextureCache::GetOrLoadBitmapTexture(ImageIndex image, const vo
shared_lock lock(_mutex); shared_lock lock(_mutex);
index = _indexMap[image]; index = _indexMap[image];
if (index != UNUSED_INDEX) if (index != kUnusedIndex)
{ {
const auto& info = _textureCache[index]; const auto& info = _textureCache[index];
return { return {
@@ -394,7 +394,7 @@ void TextureCache::FreeTextures()
// Free array texture // Free array texture
glDeleteTextures(1, &_atlasesTexture); glDeleteTextures(1, &_atlasesTexture);
_textureCache.clear(); _textureCache.clear();
std::fill(_indexMap.begin(), _indexMap.end(), UNUSED_INDEX); std::fill(_indexMap.begin(), _indexMap.end(), kUnusedIndex);
} }
DrawPixelInfo TextureCache::CreateDPI(int32_t width, int32_t height) DrawPixelInfo TextureCache::CreateDPI(int32_t width, int32_t height)

View File

@@ -10,17 +10,14 @@
#pragma once #pragma once
#include "GLSLTypes.h" #include "GLSLTypes.h"
#include "OpenGLAPI.h"
#include <SDL_pixels.h> #include <SDL_pixels.h>
#include <array> #include <array>
#include <mutex>
#include <openrct2/common.h> #include <openrct2/common.h>
#include <openrct2/drawing/Drawing.h> #include <openrct2/drawing/Drawing.h>
#include <openrct2/drawing/DrawingLock.hpp>
#include <openrct2/sprites.h> #include <openrct2/sprites.h>
#ifndef __MACOSX__ #include <shared_mutex>
# include <shared_mutex>
#endif
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@@ -209,15 +206,9 @@ namespace OpenRCT2::Ui
GLuint _paletteTexture = 0; GLuint _paletteTexture = 0;
GLuint _blendPaletteTexture = 0; GLuint _blendPaletteTexture = 0;
#ifndef __MACOSX__
std::shared_mutex _mutex; std::shared_mutex _mutex;
using shared_lock = std::shared_lock<std::shared_mutex>; using shared_lock = DrawingSharedLock<std::shared_mutex>;
using unique_lock = std::unique_lock<std::shared_mutex>; using unique_lock = DrawingUniqueLock<std::shared_mutex>;
#else
std::mutex _mutex;
using shared_lock = std::unique_lock<std::mutex>;
using unique_lock = std::unique_lock<std::mutex>;
#endif
public: public:
TextureCache(); TextureCache();

View File

@@ -20,7 +20,6 @@
#include "../drawing/IDrawingEngine.h" #include "../drawing/IDrawingEngine.h"
#include "../interface/Window.h" #include "../interface/Window.h"
#include "../localisation/Currency.h" #include "../localisation/Currency.h"
#include "../localisation/Date.h"
#include "../localisation/Language.h" #include "../localisation/Language.h"
#include "../localisation/Localisation.h" #include "../localisation/Localisation.h"
#include "../localisation/StringIds.h" #include "../localisation/StringIds.h"

View File

@@ -9,11 +9,11 @@
#pragma once #pragma once
#include "../common.h"
#include "../core/String.hpp" #include "../core/String.hpp"
#include "../drawing/Drawing.h" #include "../drawing/Drawing.h"
#include "../localisation/Currency.h" #include "../localisation/Currency.h"
#include <atomic>
#include <string> #include <string>
enum class MeasurementFormat : int32_t; enum class MeasurementFormat : int32_t;
@@ -42,7 +42,7 @@ struct GeneralConfiguration
bool UncapFPS; bool UncapFPS;
bool UseVSync; bool UseVSync;
bool ShowFPS; bool ShowFPS;
bool MultiThreading; std::atomic_uint8_t MultiThreading;
bool MinimizeFullscreenFocusLoss; bool MinimizeFullscreenFocusLoss;
bool DisableScreensaver; bool DisableScreensaver;

View File

@@ -0,0 +1,52 @@
/*****************************************************************************
* Copyright (c) 2014-2024 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#pragma once
#include "../config/Config.h"
template<typename T> class DrawingUniqueLock
{
T& _mutex;
const bool _enabled;
public:
DrawingUniqueLock(T& mutex)
: _mutex(mutex)
, _enabled(gConfigGeneral.MultiThreading)
{
if (_enabled)
_mutex.lock();
}
~DrawingUniqueLock()
{
if (_enabled)
_mutex.unlock();
}
};
template<typename T> class DrawingSharedLock
{
T& _mutex;
const bool _enabled;
public:
DrawingSharedLock(T& mutex)
: _mutex(mutex)
, _enabled(gConfigGeneral.MultiThreading)
{
if (_enabled)
_mutex.lock_shared();
}
~DrawingSharedLock()
{
if (_enabled)
_mutex.unlock_shared();
}
};

View File

@@ -17,17 +17,17 @@
# pragma clang diagnostic pop # pragma clang diagnostic pop
# include "../OpenRCT2.h" # include "../OpenRCT2.h"
# include "../config/Config.h"
# include "../core/Numerics.hpp" # include "../core/Numerics.hpp"
# include "../core/String.hpp" # include "../core/String.hpp"
# include "../localisation/LocalisationService.h" # include "../localisation/LocalisationService.h"
# include "../platform/Platform.h" # include "../platform/Platform.h"
# include "DrawingLock.hpp"
# include "TTF.h" # include "TTF.h"
static bool _ttfInitialised = false; static bool _ttfInitialised = false;
# define TTF_SURFACE_CACHE_SIZE 256 constexpr int32_t kTTFSurfaceCacheSize = 256;
# define TTF_GETWIDTH_CACHE_SIZE 1024 constexpr int32_t kTTFGetWidthCacheSize = 1024;
struct ttf_cache_entry struct ttf_cache_entry
{ {
@@ -45,12 +45,12 @@ struct ttf_getwidth_cache_entry
uint32_t lastUseTick; uint32_t lastUseTick;
}; };
static ttf_cache_entry _ttfSurfaceCache[TTF_SURFACE_CACHE_SIZE] = {}; static ttf_cache_entry _ttfSurfaceCache[kTTFSurfaceCacheSize] = {};
static int32_t _ttfSurfaceCacheCount = 0; static int32_t _ttfSurfaceCacheCount = 0;
static int32_t _ttfSurfaceCacheHitCount = 0; static int32_t _ttfSurfaceCacheHitCount = 0;
static int32_t _ttfSurfaceCacheMissCount = 0; static int32_t _ttfSurfaceCacheMissCount = 0;
static ttf_getwidth_cache_entry _ttfGetWidthCache[TTF_GETWIDTH_CACHE_SIZE] = {}; static ttf_getwidth_cache_entry _ttfGetWidthCache[kTTFGetWidthCacheSize] = {};
static int32_t _ttfGetWidthCacheCount = 0; static int32_t _ttfGetWidthCacheCount = 0;
static int32_t _ttfGetWidthCacheHitCount = 0; static int32_t _ttfGetWidthCacheHitCount = 0;
static int32_t _ttfGetWidthCacheMissCount = 0; static int32_t _ttfGetWidthCacheMissCount = 0;
@@ -66,26 +66,6 @@ static bool TTFGetSize(TTF_Font* font, std::string_view text, int32_t* outWidth,
static void TTFToggleHinting(bool); static void TTFToggleHinting(bool);
static TTFSurface* TTFRender(TTF_Font* font, std::string_view text); static TTFSurface* TTFRender(TTF_Font* font, std::string_view text);
template<typename T> class FontLockHelper
{
T& _mutex;
const bool _enabled;
public:
FontLockHelper(T& mutex)
: _mutex(mutex)
, _enabled(gConfigGeneral.MultiThreading)
{
if (_enabled)
_mutex.lock();
}
~FontLockHelper()
{
if (_enabled)
_mutex.unlock();
}
};
static void TTFToggleHinting(bool) static void TTFToggleHinting(bool)
{ {
if (!LocalisationService_UseTrueTypeFont()) if (!LocalisationService_UseTrueTypeFont())
@@ -108,7 +88,7 @@ static void TTFToggleHinting(bool)
bool TTFInitialise() bool TTFInitialise()
{ {
FontLockHelper<std::mutex> lock(_mutex); DrawingUniqueLock<std::mutex> lock(_mutex);
if (_ttfInitialised) if (_ttfInitialised)
return true; return true;
@@ -147,7 +127,7 @@ bool TTFInitialise()
void TTFDispose() void TTFDispose()
{ {
FontLockHelper<std::mutex> lock(_mutex); DrawingUniqueLock<std::mutex> lock(_mutex);
if (!_ttfInitialised) if (!_ttfInitialised)
return; return;
@@ -203,7 +183,7 @@ static void TTFSurfaceCacheDispose(ttf_cache_entry* entry)
static void TTFSurfaceCacheDisposeAll() static void TTFSurfaceCacheDisposeAll()
{ {
for (int32_t i = 0; i < TTF_SURFACE_CACHE_SIZE; i++) for (int32_t i = 0; i < kTTFSurfaceCacheSize; i++)
{ {
TTFSurfaceCacheDispose(&_ttfSurfaceCache[i]); TTFSurfaceCacheDispose(&_ttfSurfaceCache[i]);
_ttfSurfaceCacheCount--; _ttfSurfaceCacheCount--;
@@ -212,7 +192,7 @@ static void TTFSurfaceCacheDisposeAll()
void TTFToggleHinting() void TTFToggleHinting()
{ {
FontLockHelper<std::mutex> lock(_mutex); DrawingUniqueLock<std::mutex> lock(_mutex);
TTFToggleHinting(true); TTFToggleHinting(true);
} }
@@ -221,11 +201,11 @@ TTFSurface* TTFSurfaceCacheGetOrAdd(TTF_Font* font, std::string_view text)
ttf_cache_entry* entry; ttf_cache_entry* entry;
uint32_t hash = TTFSurfaceCacheHash(font, text); uint32_t hash = TTFSurfaceCacheHash(font, text);
int32_t index = hash % TTF_SURFACE_CACHE_SIZE; int32_t index = hash % kTTFSurfaceCacheSize;
FontLockHelper<std::mutex> lock(_mutex); DrawingUniqueLock<std::mutex> lock(_mutex);
for (int32_t i = 0; i < TTF_SURFACE_CACHE_SIZE; i++) for (int32_t i = 0; i < kTTFSurfaceCacheSize; i++)
{ {
entry = &_ttfSurfaceCache[index]; entry = &_ttfSurfaceCache[index];
@@ -246,7 +226,7 @@ TTFSurface* TTFSurfaceCacheGetOrAdd(TTF_Font* font, std::string_view text)
} }
// Check if next entry is a hit // Check if next entry is a hit
if (++index >= TTF_SURFACE_CACHE_SIZE) if (++index >= kTTFSurfaceCacheSize)
index = 0; index = 0;
} }
@@ -283,7 +263,7 @@ static void TTFGetWidthCacheDispose(ttf_getwidth_cache_entry* entry)
static void TTFGetWidthCacheDisposeAll() static void TTFGetWidthCacheDisposeAll()
{ {
for (int32_t i = 0; i < TTF_GETWIDTH_CACHE_SIZE; i++) for (int32_t i = 0; i < kTTFGetWidthCacheSize; i++)
{ {
TTFGetWidthCacheDispose(&_ttfGetWidthCache[i]); TTFGetWidthCacheDispose(&_ttfGetWidthCache[i]);
_ttfGetWidthCacheCount--; _ttfGetWidthCacheCount--;
@@ -295,11 +275,11 @@ uint32_t TTFGetWidthCacheGetOrAdd(TTF_Font* font, std::string_view text)
ttf_getwidth_cache_entry* entry; ttf_getwidth_cache_entry* entry;
uint32_t hash = TTFSurfaceCacheHash(font, text); uint32_t hash = TTFSurfaceCacheHash(font, text);
int32_t index = hash % TTF_GETWIDTH_CACHE_SIZE; int32_t index = hash % kTTFGetWidthCacheSize;
FontLockHelper<std::mutex> lock(_mutex); DrawingUniqueLock<std::mutex> lock(_mutex);
for (int32_t i = 0; i < TTF_GETWIDTH_CACHE_SIZE; i++) for (int32_t i = 0; i < kTTFGetWidthCacheSize; i++)
{ {
entry = &_ttfGetWidthCache[index]; entry = &_ttfGetWidthCache[index];
@@ -320,7 +300,7 @@ uint32_t TTFGetWidthCacheGetOrAdd(TTF_Font* font, std::string_view text)
} }
// Check if next entry is a hit // Check if next entry is a hit
if (++index >= TTF_GETWIDTH_CACHE_SIZE) if (++index >= kTTFGetWidthCacheSize)
index = 0; index = 0;
} }
@@ -343,7 +323,7 @@ uint32_t TTFGetWidthCacheGetOrAdd(TTF_Font* font, std::string_view text)
TTFFontDescriptor* TTFGetFontFromSpriteBase(FontStyle fontStyle) TTFFontDescriptor* TTFGetFontFromSpriteBase(FontStyle fontStyle)
{ {
FontLockHelper<std::mutex> lock(_mutex); DrawingUniqueLock<std::mutex> lock(_mutex);
return &gCurrentTTFFontSet->size[EnumValue(fontStyle)]; return &gCurrentTTFFontSet->size[EnumValue(fontStyle)];
} }