1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-11 01:52:32 +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;
constexpr uint32_t UNUSED_INDEX = 0xFFFFFFFF;
constexpr uint32_t kUnusedIndex = 0xFFFFFFFF;
TextureCache::TextureCache()
{
std::fill(_indexMap.begin(), _indexMap.end(), UNUSED_INDEX);
std::fill(_indexMap.begin(), _indexMap.end(), kUnusedIndex);
}
TextureCache::~TextureCache()
@@ -38,13 +38,13 @@ void TextureCache::InvalidateImage(ImageIndex image)
unique_lock lock(_mutex);
uint32_t index = _indexMap[image];
if (index == UNUSED_INDEX)
if (index == kUnusedIndex)
return;
AtlasTextureInfo& elem = _textureCache.at(index);
_atlases[elem.index].Free(elem);
_indexMap[image] = UNUSED_INDEX;
_indexMap[image] = kUnusedIndex;
if (index == _textureCache.size() - 1)
{
@@ -76,7 +76,7 @@ BasicTextureInfo TextureCache::GetOrLoadImageTexture(const ImageId imageId)
shared_lock lock(_mutex);
index = _indexMap[imageId.GetIndex()];
if (index != UNUSED_INDEX)
if (index != kUnusedIndex)
{
const auto& info = _textureCache[index];
return {
@@ -144,7 +144,7 @@ BasicTextureInfo TextureCache::GetOrLoadBitmapTexture(ImageIndex image, const vo
shared_lock lock(_mutex);
index = _indexMap[image];
if (index != UNUSED_INDEX)
if (index != kUnusedIndex)
{
const auto& info = _textureCache[index];
return {
@@ -394,7 +394,7 @@ void TextureCache::FreeTextures()
// Free array texture
glDeleteTextures(1, &_atlasesTexture);
_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)

View File

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

View File

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

View File

@@ -9,11 +9,11 @@
#pragma once
#include "../common.h"
#include "../core/String.hpp"
#include "../drawing/Drawing.h"
#include "../localisation/Currency.h"
#include <atomic>
#include <string>
enum class MeasurementFormat : int32_t;
@@ -42,7 +42,7 @@ struct GeneralConfiguration
bool UncapFPS;
bool UseVSync;
bool ShowFPS;
bool MultiThreading;
std::atomic_uint8_t MultiThreading;
bool MinimizeFullscreenFocusLoss;
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
# include "../OpenRCT2.h"
# include "../config/Config.h"
# include "../core/Numerics.hpp"
# include "../core/String.hpp"
# include "../localisation/LocalisationService.h"
# include "../platform/Platform.h"
# include "DrawingLock.hpp"
# include "TTF.h"
static bool _ttfInitialised = false;
# define TTF_SURFACE_CACHE_SIZE 256
# define TTF_GETWIDTH_CACHE_SIZE 1024
constexpr int32_t kTTFSurfaceCacheSize = 256;
constexpr int32_t kTTFGetWidthCacheSize = 1024;
struct ttf_cache_entry
{
@@ -45,12 +45,12 @@ struct ttf_getwidth_cache_entry
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 _ttfSurfaceCacheHitCount = 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 _ttfGetWidthCacheHitCount = 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 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)
{
if (!LocalisationService_UseTrueTypeFont())
@@ -108,7 +88,7 @@ static void TTFToggleHinting(bool)
bool TTFInitialise()
{
FontLockHelper<std::mutex> lock(_mutex);
DrawingUniqueLock<std::mutex> lock(_mutex);
if (_ttfInitialised)
return true;
@@ -147,7 +127,7 @@ bool TTFInitialise()
void TTFDispose()
{
FontLockHelper<std::mutex> lock(_mutex);
DrawingUniqueLock<std::mutex> lock(_mutex);
if (!_ttfInitialised)
return;
@@ -203,7 +183,7 @@ static void TTFSurfaceCacheDispose(ttf_cache_entry* entry)
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]);
_ttfSurfaceCacheCount--;
@@ -212,7 +192,7 @@ static void TTFSurfaceCacheDisposeAll()
void TTFToggleHinting()
{
FontLockHelper<std::mutex> lock(_mutex);
DrawingUniqueLock<std::mutex> lock(_mutex);
TTFToggleHinting(true);
}
@@ -221,11 +201,11 @@ TTFSurface* TTFSurfaceCacheGetOrAdd(TTF_Font* font, std::string_view text)
ttf_cache_entry* entry;
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];
@@ -246,7 +226,7 @@ TTFSurface* TTFSurfaceCacheGetOrAdd(TTF_Font* font, std::string_view text)
}
// Check if next entry is a hit
if (++index >= TTF_SURFACE_CACHE_SIZE)
if (++index >= kTTFSurfaceCacheSize)
index = 0;
}
@@ -283,7 +263,7 @@ static void TTFGetWidthCacheDispose(ttf_getwidth_cache_entry* entry)
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]);
_ttfGetWidthCacheCount--;
@@ -295,11 +275,11 @@ uint32_t TTFGetWidthCacheGetOrAdd(TTF_Font* font, std::string_view text)
ttf_getwidth_cache_entry* entry;
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];
@@ -320,7 +300,7 @@ uint32_t TTFGetWidthCacheGetOrAdd(TTF_Font* font, std::string_view text)
}
// Check if next entry is a hit
if (++index >= TTF_GETWIDTH_CACHE_SIZE)
if (++index >= kTTFGetWidthCacheSize)
index = 0;
}
@@ -343,7 +323,7 @@ uint32_t TTFGetWidthCacheGetOrAdd(TTF_Font* font, std::string_view text)
TTFFontDescriptor* TTFGetFontFromSpriteBase(FontStyle fontStyle)
{
FontLockHelper<std::mutex> lock(_mutex);
DrawingUniqueLock<std::mutex> lock(_mutex);
return &gCurrentTTFFontSet->size[EnumValue(fontStyle)];
}