Skip to content

Commit

Permalink
Add a new screen for managing installed Adreno drivers
Browse files Browse the repository at this point in the history
  • Loading branch information
hrydgard committed Jan 17, 2024
1 parent 72c4d34 commit 9253bf9
Show file tree
Hide file tree
Showing 24 changed files with 412 additions and 163 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Expand Up @@ -1455,6 +1455,8 @@ list(APPEND NativeAppSource
UI/GameScreen.cpp
UI/GameSettingsScreen.h
UI/GameSettingsScreen.cpp
UI/DriverManagerScreen.h
UI/DriverManagerScreen.cpp
UI/GPUDriverTestScreen.h
UI/GPUDriverTestScreen.cpp
UI/TiltAnalogSettingsScreen.h
Expand Down
13 changes: 11 additions & 2 deletions Common/Data/Format/JSONReader.cpp
Expand Up @@ -67,15 +67,24 @@ const JsonNode *JsonGet::get(const char *child_name, JsonTag type) const {
return nullptr;
}

const char *JsonGet::getStringOrDie(const char *child_name) const {
const char *JsonGet::getStringOrNull(const char *child_name) const {
const JsonNode *val = get(child_name, JSON_STRING);
if (val)
return val->value.toString();
ERROR_LOG(IO, "String '%s' missing from node", child_name);
return nullptr;
}

const char *JsonGet::getString(const char *child_name, const char *default_value) const {
bool JsonGet::getString(const char *child_name, std::string *output) const {
const JsonNode *val = get(child_name, JSON_STRING);
if (!val) {
return false;
}
*output = val->value.toString();
return true;
}

const char *JsonGet::getStringOr(const char *child_name, const char *default_value) const {
const JsonNode *val = get(child_name, JSON_STRING);
if (!val)
return default_value;
Expand Down
7 changes: 4 additions & 3 deletions Common/Data/Format/JSONReader.h
Expand Up @@ -21,8 +21,9 @@ struct JsonGet {
const JsonGet getDict(const char *child_name) const {
return JsonGet(get(child_name, JSON_OBJECT)->value);
}
const char *getStringOrDie(const char *child_name) const;
const char *getString(const char *child_name, const char *default_value) const;
const char *getStringOrNull(const char *child_name) const;
const char *getStringOr(const char *child_name, const char *default_value) const;
bool getString(const char *child_name, std::string *output) const;
bool getStringVector(std::vector<std::string> *vec) const;
double getFloat(const char *child_name) const;
double getFloat(const char *child_name, double default_value) const;
Expand All @@ -46,7 +47,7 @@ struct JsonGet {
class JsonReader {
public:
JsonReader(const std::string &filename);
// Makes a copy, after this returns you can free the input buffer.
// Makes a copy, after this returns you can free the input buffer. Zero termination is not necessary.
JsonReader(const char *data, size_t size) {
buffer_ = (char *)malloc(size + 1);
if (buffer_) {
Expand Down
14 changes: 14 additions & 0 deletions Common/File/FileUtil.cpp
Expand Up @@ -62,6 +62,7 @@
#include <dirent.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#endif

#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__)
Expand Down Expand Up @@ -990,6 +991,19 @@ bool OpenFileInEditor(const Path &fileName) {
return true;
}

const Path GetCurDirectory() {
#ifdef _WIN32
wchar_t buffer[4096];
size_t len = GetCurrentDirectory(sizeof(buffer) / sizeof(wchar_t), buffer);
std::string curDir = ConvertWStringToUTF8(buffer);
return Path(curDir);
#else
char temp[4096]{};
getcwd(temp, 4096);
return Path(temp);
#endif
}

const Path &GetExeDirectory() {
static Path ExePath;

Expand Down
2 changes: 2 additions & 0 deletions Common/File/FileUtil.h
Expand Up @@ -123,6 +123,8 @@ bool OpenFileInEditor(const Path &fileName);
// TODO: Belongs in System or something.
const Path &GetExeDirectory();

const Path GetCurDirectory();

// simple wrapper for cstdlib file functions to
// hopefully will make error checking easier
// and make forgetting an fclose() harder
Expand Down
2 changes: 1 addition & 1 deletion Common/GPU/Vulkan/VulkanContext.cpp
Expand Up @@ -133,7 +133,7 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
#endif
#endif

if ((flags_ & VULKAN_FLAG_VALIDATE) && g_Config.customDriver.empty()) {
if ((flags_ & VULKAN_FLAG_VALIDATE) && g_Config.sCustomDriver.empty()) {
if (IsInstanceExtensionAvailable(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
// Enable the validation layers
for (size_t i = 0; i < ARRAY_SIZE(validationLayers); i++) {
Expand Down
66 changes: 34 additions & 32 deletions Common/GPU/Vulkan/VulkanLoader.cpp
Expand Up @@ -300,40 +300,42 @@ static VulkanLibraryHandle VulkanLoadLibrary(std::string *errorString) {
void *lib = nullptr;

#if PPSSPP_PLATFORM(ANDROID) && PPSSPP_ARCH(ARM64)
if (!g_Config.customDriver.empty() && g_Config.customDriver != "Default") {
const Path driverPath = g_Config.internalDataDirectory / "drivers" / g_Config.customDriver;

json::JsonReader meta = json::JsonReader((driverPath / "meta.json").c_str());
if (meta.ok()) {
std::string driverLibName = meta.root().get("libraryName")->value.toString();

Path tempDir = g_Config.internalDataDirectory / "temp";
Path fileRedirectDir = g_Config.internalDataDirectory / "vk_file_redirect";

File::CreateDir(tempDir);
File::CreateDir(fileRedirectDir);

lib = adrenotools_open_libvulkan(
RTLD_NOW | RTLD_LOCAL, ADRENOTOOLS_DRIVER_FILE_REDIRECT | ADRENOTOOLS_DRIVER_CUSTOM,
(std::string(tempDir.c_str()) + "/").c_str(),g_nativeLibDir.c_str(),
(std::string(driverPath.c_str()) + "/").c_str(),driverLibName.c_str(),
(std::string(fileRedirectDir.c_str()) + "/").c_str(),nullptr);
if (!lib) {
ERROR_LOG(G3D, "Failed to load custom driver");
}
}
}
if (!g_Config.sCustomDriver.empty() && g_Config.sCustomDriver != "Default") {
const Path driverPath = g_Config.internalDataDirectory / "drivers" / g_Config.sCustomDriver;

json::JsonReader meta = json::JsonReader((driverPath / "meta.json").c_str());
if (meta.ok()) {
std::string driverLibName = meta.root().get("libraryName")->value.toString();

Path tempDir = g_Config.internalDataDirectory / "temp";
Path fileRedirectDir = g_Config.internalDataDirectory / "vk_file_redirect";

File::CreateDir(tempDir);
File::CreateDir(fileRedirectDir);

lib = adrenotools_open_libvulkan(
RTLD_NOW | RTLD_LOCAL, ADRENOTOOLS_DRIVER_FILE_REDIRECT | ADRENOTOOLS_DRIVER_CUSTOM,
(std::string(tempDir.c_str()) + "/").c_str(), g_nativeLibDir.c_str(),
(std::string(driverPath.c_str()) + "/").c_str(), driverLibName.c_str(),
(std::string(fileRedirectDir.c_str()) + "/").c_str(), nullptr);
if (!lib) {
ERROR_LOG(G3D, "Failed to load custom driver with AdrenoTools ('%s')", g_Config.sCustomDriver.c_str());
} else {
INFO_LOG(G3D, "Vulkan library loaded with AdrenoTools ('%s')", g_Config.sCustomDriver.c_str());
}
}
}
#endif

if (!lib) {
for (int i = 0; i < ARRAY_SIZE(so_names); i++) {
lib = dlopen(so_names[i], RTLD_NOW | RTLD_LOCAL);
if (lib) {
INFO_LOG(G3D, "Vulkan library loaded with AdrenoTools ('%s')", so_names[i]);
break;
}
}
}
if (!lib) {
for (int i = 0; i < ARRAY_SIZE(so_names); i++) {
lib = dlopen(so_names[i], RTLD_NOW | RTLD_LOCAL);
if (lib) {
INFO_LOG(G3D, "Vulkan library loaded ('%s')", so_names[i]);
break;
}
}
}
return lib;
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion Common/UI/View.cpp
Expand Up @@ -599,7 +599,7 @@ ItemHeader::ItemHeader(const std::string &text, LayoutParams *layoutParams)
}

void ItemHeader::Draw(UIContext &dc) {
dc.SetFontStyle(dc.theme->uiFontSmall);
dc.SetFontStyle(large_ ? dc.theme->uiFont : dc.theme->uiFontSmall);
dc.DrawText(text_.c_str(), bounds_.x + 4, bounds_.centerY(), dc.theme->headerStyle.fgColor, ALIGN_LEFT | ALIGN_VCENTER);
dc.Draw()->DrawImageCenterTexel(dc.theme->whiteImage, bounds_.x, bounds_.y2()-2, bounds_.x2(), bounds_.y2(), dc.theme->headerStyle.fgColor);
}
Expand Down
3 changes: 2 additions & 1 deletion Common/UI/View.h
Expand Up @@ -848,9 +848,10 @@ class ItemHeader : public Item {
void Draw(UIContext &dc) override;
std::string DescribeText() const override;
void GetContentDimensionsBySpec(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert, float &w, float &h) const override;

void SetLarge(bool large) { large_ = large; }
private:
std::string text_;
bool large_ = false;
};

class PopupHeader : public Item {
Expand Down
10 changes: 8 additions & 2 deletions Core/Config.cpp
Expand Up @@ -592,7 +592,7 @@ static const ConfigSetting graphicsSettings[] = {
ConfigSetting("iShowStatusFlags", &g_Config.iShowStatusFlags, 0, CfgFlag::PER_GAME),
ConfigSetting("GraphicsBackend", &g_Config.iGPUBackend, &DefaultGPUBackend, &GPUBackendTranslator::To, &GPUBackendTranslator::From, CfgFlag::DEFAULT | CfgFlag::REPORT),
#if PPSSPP_PLATFORM(ANDROID) && PPSSPP_ARCH(ARM64)
ConfigSetting("CustomDriver", &g_Config.customDriver, "", CfgFlag::DEFAULT),
ConfigSetting("CustomDriver", &g_Config.sCustomDriver, "", CfgFlag::DEFAULT),
#endif
ConfigSetting("FailedGraphicsBackends", &g_Config.sFailedGPUBackends, "", CfgFlag::DEFAULT),
ConfigSetting("DisabledGraphicsBackends", &g_Config.sDisabledGPUBackends, "", CfgFlag::DEFAULT),
Expand Down Expand Up @@ -1399,6 +1399,11 @@ void Config::PostLoadCleanup(bool gameSpecific) {
if (iTexScalingLevel <= 0) {
iTexScalingLevel = 1;
}

// Remove a legacy value.
if (g_Config.sCustomDriver == "Default") {
g_Config.sCustomDriver = "";
}
}

void Config::PreSaveCleanup(bool gameSpecific) {
Expand Down Expand Up @@ -1448,7 +1453,8 @@ void Config::DownloadCompletedCallback(http::Request &download) {
return;
}

std::string version = root.getString("version", "");
std::string version;
root.getString("version", &version);

const char *gitVer = PPSSPP_GIT_VERSION;
Version installed(gitVer);
Expand Down
2 changes: 1 addition & 1 deletion Core/Config.h
Expand Up @@ -149,7 +149,7 @@ struct Config {

// GFX
int iGPUBackend;
std::string customDriver;
std::string sCustomDriver;
std::string sFailedGPUBackends;
std::string sDisabledGPUBackends;
// We have separate device parameters for each backend so it doesn't get erased if you switch backends.
Expand Down
2 changes: 1 addition & 1 deletion Core/Debugger/WebSocket.cpp
Expand Up @@ -165,7 +165,7 @@ void HandleDebuggerRequest(const http::ServerRequest &request) {
}

const JsonGet root = reader.root();
const char *event = root ? root.getString("event", nullptr) : nullptr;
const char *event = root ? root.getStringOr("event", nullptr) : nullptr;
if (!event) {
ws->Send(DebuggerErrorEvent("Bad message: no event property", LogLevel::LERROR, root));
return;
Expand Down
2 changes: 1 addition & 1 deletion Core/Debugger/WebSocket/CPUCoreSubscriber.cpp
Expand Up @@ -219,7 +219,7 @@ static DebuggerRegType ValidateRegName(DebuggerRequest &req, const std::string &
}

static DebuggerRegType ValidateCatReg(DebuggerRequest &req, int *cat, int *reg) {
const char *name = req.data.getString("name", nullptr);
const char *name = req.data.getStringOr("name", nullptr);
if (name)
return ValidateRegName(req, name, cat, reg);

Expand Down

0 comments on commit 9253bf9

Please sign in to comment.