mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-16 16:00:30 +02:00
The core and the headless tools no longer use mutexes, condition variables, spinlocks, std::atomic, std::thread or volatile flags. Threads hand off through libretro-common's retro_atomic and rthreads plus a few small pieces on top of them in Common/Thread: Thread, MpscQueue, EventCounter, ParkingLot waits and ReaderGate. Every wait blocks until it's woken; nothing polls on a timer. State that only one thread touches just loses its lock. The PSP filesystem, sceIo and the savedata dialog now belong to the emulation thread: async reads and writes run when they're queued and complete later in emulated time, and the IO and savedata threads are gone. The friend finder only talks to the adhoc server and hands what it gets to the emulation thread. GPU init always runs on the thread that starts the game. The Vulkan render and compile queues, pipeline and render pass caches, delete list and SPIR-V cache, the GL render queue, the software renderer's jit caches, the file loader caches, the web debugger, UPnP, input, savestates, logging and the GE debugger all hand off through queues and atomics. The IR jit's spinning profiler thread goes. A CPU thread with nothing to run now sleeps until work is queued instead of spinning. Headless with --debugger waits for a client while stopped, and ends the run once every client that connected has left. Web server shutdown keeps servicing the CPU queue until the server has finished.
164 lines
5.6 KiB
C++
164 lines
5.6 KiB
C++
// Copyright (c) 2016- PPSSPP Project.
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
// Official git repository and contact information can be found at
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
#pragma once
|
|
|
|
#include "ppsspp_config.h"
|
|
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <map>
|
|
#include <vector>
|
|
|
|
#include "Common/CommonFuncs.h"
|
|
#include "Common/CommonTypes.h"
|
|
#include "Common/MemoryUtil.h"
|
|
#include "Common/File/Path.h"
|
|
#include "Common/File/VFS/VFS.h"
|
|
#include "Common/GPU/DataFormat.h"
|
|
|
|
#include "GPU/Common/TextureDecoder.h"
|
|
#include "GPU/Common/ReplacedTexture.h"
|
|
#include "GPU/ge_constants.h"
|
|
|
|
class IniFile;
|
|
class TextureCacheCommon;
|
|
class TextureReplacer;
|
|
class ReplacedTextureTask;
|
|
class LimitedWaitable;
|
|
class VFSBackend;
|
|
|
|
struct SavedTextureCacheData {
|
|
int levelW[8]{};
|
|
int levelH[8]{};
|
|
bool levelSaved[8]{};
|
|
double lastTimeSaved = 0.0;
|
|
};
|
|
|
|
namespace std {
|
|
template <>
|
|
struct hash<ReplacementCacheKey> {
|
|
size_t operator()(const ReplacementCacheKey &k) const {
|
|
return std::hash<u64>()(k.cachekey ^ ((u64)k.hash << 32));
|
|
}
|
|
};
|
|
}
|
|
|
|
struct ReplacedTextureDecodeInfo {
|
|
u64 cachekey;
|
|
u32 hash;
|
|
u32 addr;
|
|
bool isVideo;
|
|
bool isFinal;
|
|
Draw::DataFormat fmt;
|
|
};
|
|
|
|
enum class ReplacerDecimateMode {
|
|
NEW_FRAME,
|
|
FORCE_PRESSURE,
|
|
ALL,
|
|
};
|
|
|
|
class TextureReplacer {
|
|
public:
|
|
TextureReplacer(const TextureReplacer &) = delete;
|
|
TextureReplacer &operator=(const TextureReplacer &) = delete;
|
|
// The draw context is checked for supported texture formats.
|
|
TextureReplacer(Draw::DrawContext *draw);
|
|
~TextureReplacer();
|
|
|
|
void NotifyConfigChanged();
|
|
|
|
bool Enabled() const { return replaceEnabled_ || saveEnabled_; } // used to check hashing method etc.
|
|
bool ReplaceEnabled() const { return replaceEnabled_; }
|
|
bool SaveEnabled() const { return saveEnabled_; }
|
|
|
|
u32 ComputeHash(u32 addr, int bufw, int w, int h, bool swizzled, GETextureFormat fmt, u16 maxSeenV);
|
|
|
|
// Returns nullptr if not found.
|
|
ReplacedTexture *FindReplacement(ReplacementCacheKey key, int w, int h);
|
|
|
|
// For testing: point the replacer at a texture pack directory and load its
|
|
// ini, without touching the global config. Returns true on success.
|
|
bool LoadPackForTesting(const Path &basePath, std::string *error);
|
|
|
|
// Check if a NotifyTextureDecoded for this texture is desired (used to avoid reads from write-combined memory.)
|
|
bool WillSave(const ReplacedTextureDecodeInfo &replacedInfo) const;
|
|
|
|
// Notify that a new texture was decoded. May already be upscaled, saves the data passed.
|
|
// If the replacer knows about this one already, texture will be passed in, otherwise nullptr.
|
|
void NotifyTextureDecoded(ReplacedTexture *texture, const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int origW, int origH, int scaledW, int scaledH);
|
|
|
|
void Decimate(ReplacerDecimateMode mode);
|
|
|
|
static bool GenerateIni(const std::string &gameID, Path &generatedFilename);
|
|
static bool IniExists(const std::string &gameID);
|
|
|
|
int GetNumTrackedTextures() const { return (int)cache_.size(); }
|
|
int GetNumCachedReplacedTextures() const { return (int)levelCache_.size(); }
|
|
|
|
static std::string HashName(ReplacementCacheKey key, int level);
|
|
|
|
protected:
|
|
bool FindFiltering(ReplacementCacheKey key, TextureFiltering *forceFiltering);
|
|
|
|
bool LoadIni(std::string *error, bool notify = true);
|
|
void DeleteVFS();
|
|
bool LoadIniValues(IniFile &ini, VFSBackend *dir, bool isOverride, std::string *error);
|
|
void ParseHashRange(const std::string &key, const std::string &value);
|
|
void ParseFiltering(const std::string &key, const std::string &value);
|
|
void ParseReduceHashRange(const std::string& key, const std::string& value);
|
|
bool LookupHashRange(u32 addr, int w, int h, int *newW, int *newH);
|
|
float LookupReduceHashRange(int w, int h);
|
|
std::string LookupHashFile(ReplacementCacheKey key, bool *foundAlias, bool *ignored);
|
|
|
|
bool replaceEnabled_ = false;
|
|
bool saveEnabled_ = false;
|
|
bool ignoreAddress_ = false;
|
|
bool reduceHash_ = false;
|
|
bool ignoreMipmap_ = false;
|
|
int skipLastDXT1Blocks128x64_ = 0;
|
|
int skipLastDXT1Blocks128x128_ = 0;
|
|
|
|
float reduceHashGlobalValue = 0.5f; // Global value for textures dump pngs of all sizes, 0.5 by default but can be set in textures.ini
|
|
|
|
double lastTextureCacheSizeGB_ = 0.0;
|
|
std::string gameID_;
|
|
Path basePath_;
|
|
Path newTextureDir_;
|
|
ReplacedTextureHash textureHash_ = ReplacedTextureHash::QUICK;
|
|
|
|
VFSBackend *vfs_ = nullptr;
|
|
bool vfsIsZip_ = false;
|
|
|
|
GPUFormatSupport formatSupport_{};
|
|
|
|
typedef std::pair<int, int> WidthHeightPair;
|
|
std::unordered_map<u64, WidthHeightPair> hashranges_;
|
|
std::unordered_map<u64, float> reducehashranges_;
|
|
|
|
std::unordered_map<ReplacementCacheKey, std::string> aliases_;
|
|
std::unordered_map<ReplacementCacheKey, TextureFiltering> filtering_;
|
|
|
|
std::unordered_map<ReplacementCacheKey, ReplacedTextureRef> cache_;
|
|
std::unordered_map<ReplacementCacheKey, SavedTextureCacheData> savedCache_;
|
|
|
|
// the key is either from aliases_, in which case it's a |-separated sequence of texture filenames of the levels of a texture.
|
|
// alternatively the key is from the generated texture filename.
|
|
std::unordered_map<std::string, ReplacedTexture *> levelCache_;
|
|
};
|