Merge branch 'shadps4-emu:main' into main

This commit is contained in:
Daniel Nylander 2025-01-13 17:23:03 +01:00 committed by GitHub
commit d7dfcbbe6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
91 changed files with 10715 additions and 411 deletions

View File

@ -254,6 +254,8 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
set(NETWORK_LIBS src/core/libraries/network/http.cpp
src/core/libraries/network/http.h
src/core/libraries/network/http2.cpp
src/core/libraries/network/http2.h
src/core/libraries/network/net.cpp
src/core/libraries/network/netctl.cpp
src/core/libraries/network/netctl.h
@ -263,6 +265,8 @@ set(NETWORK_LIBS src/core/libraries/network/http.cpp
src/core/libraries/network/net.h
src/core/libraries/network/ssl.cpp
src/core/libraries/network/ssl.h
src/core/libraries/network/ssl2.cpp
src/core/libraries/network/ssl2.h
)
set(AVPLAYER_LIB src/core/libraries/avplayer/avplayer_common.cpp
@ -415,7 +419,9 @@ set(VDEC_LIB src/core/libraries/videodec/videodec2_impl.cpp
src/core/libraries/videodec/videodec_impl.h
)
set(NP_LIBS src/core/libraries/np_manager/np_manager.cpp
set(NP_LIBS src/core/libraries/np_common/np_common.cpp
src/core/libraries/np_common/np_common.h
src/core/libraries/np_manager/np_manager.cpp
src/core/libraries/np_manager/np_manager.h
src/core/libraries/np_score/np_score.cpp
src/core/libraries/np_score/np_score.h

View File

@ -26,7 +26,7 @@
</screenshot>
<screenshot>
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/3.png</image>
<caption>Yakuza Kiwami</caption>
<caption>Yakuza 0</caption>
</screenshot>
<screenshot>
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/4.png</image>

2
externals/sdl3 vendored

@ -1 +1 @@
Subproject commit 3a1d76d298db023f6cf37fb08ee766f20a4e12ab
Subproject commit 22422f7748d5128135995ed34c8f8012861c7332

2
externals/sirit vendored

@ -1 +1 @@
Subproject commit 1e74f4ef8d2a0e3221a4de51977663f342b53c35
Subproject commit 26ad5a9d0fe13260b0d7d6c64419d01a196b2e32

View File

@ -72,6 +72,7 @@ static bool checkCompatibilityOnStartup = false;
static std::string trophyKey;
// Gui
static bool load_game_size = true;
std::vector<std::filesystem::path> settings_install_dirs = {};
std::filesystem::path settings_addon_install_dir = {};
u32 main_window_geometry_x = 400;
@ -102,6 +103,14 @@ void setTrophyKey(std::string key) {
trophyKey = key;
}
bool GetLoadGameSizeEnabled() {
return load_game_size;
}
void setLoadGameSizeEnabled(bool enable) {
load_game_size = enable;
}
bool isNeoModeConsole() {
return isNeo;
}
@ -650,6 +659,7 @@ void load(const std::filesystem::path& path) {
if (data.contains("GUI")) {
const toml::value& gui = data.at("GUI");
load_game_size = toml::find_or<bool>(gui, "loadGameSizeEnabled", true);
m_icon_size = toml::find_or<int>(gui, "iconSize", 0);
m_icon_size_grid = toml::find_or<int>(gui, "iconSizeGrid", 0);
m_slider_pos = toml::find_or<int>(gui, "sliderPos", 0);
@ -755,6 +765,7 @@ void save(const std::filesystem::path& path) {
install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data});
}
data["GUI"]["installDirs"] = install_dirs;
data["GUI"]["loadGameSizeEnabled"] = load_game_size;
data["GUI"]["addonInstallDir"] =
std::string{fmt::UTF(settings_addon_install_dir.u8string()).data};

View File

@ -17,6 +17,8 @@ void saveMainWindow(const std::filesystem::path& path);
std::string getTrophyKey();
void setTrophyKey(std::string key);
bool GetLoadGameSizeEnabled();
void setLoadGameSizeEnabled(bool enable);
bool getIsFullscreen();
std::string getFullscreenMode();
bool isNeoModeConsole();

View File

@ -95,9 +95,12 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
SUB(Lib, SaveData) \
SUB(Lib, SaveDataDialog) \
SUB(Lib, Http) \
SUB(Lib, Http2) \
SUB(Lib, Ssl) \
SUB(Lib, Ssl2) \
SUB(Lib, SysModule) \
SUB(Lib, Move) \
SUB(Lib, NpCommon) \
SUB(Lib, NpManager) \
SUB(Lib, NpScore) \
SUB(Lib, NpTrophy) \

View File

@ -63,8 +63,11 @@ enum class Class : u8 {
Lib_SaveData, ///< The LibSceSaveData implementation.
Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation.
Lib_Ssl, ///< The LibSceSsl implementation.
Lib_Ssl2, ///< The LibSceSsl2 implementation.
Lib_Http, ///< The LibSceHttp implementation.
Lib_Http2, ///< The LibSceHttp2 implementation.
Lib_SysModule, ///< The LibSceSysModule implementation
Lib_NpCommon, ///< The LibSceNpCommon implementation
Lib_NpManager, ///< The LibSceNpManager implementation
Lib_NpScore, ///< The LibSceNpScore implementation
Lib_NpTrophy, ///< The LibSceNpTrophy implementation

View File

@ -386,6 +386,9 @@ int PS4_SYSV_ABI posix_sched_get_priority_min() {
}
int PS4_SYSV_ABI posix_pthread_rename_np(PthreadT thread, const char* name) {
if (thread == nullptr) {
return POSIX_EINVAL;
}
LOG_INFO(Kernel_Pthread, "name = {}", name);
Common::SetThreadName(reinterpret_cast<void*>(thread->native_thr.GetHandle()), name);
thread->name = name;

View File

@ -21,9 +21,12 @@
#include "core/libraries/mouse/mouse.h"
#include "core/libraries/move/move.h"
#include "core/libraries/network/http.h"
#include "core/libraries/network/http2.h"
#include "core/libraries/network/net.h"
#include "core/libraries/network/netctl.h"
#include "core/libraries/network/ssl.h"
#include "core/libraries/network/ssl2.h"
#include "core/libraries/np_common/np_common.h"
#include "core/libraries/np_manager/np_manager.h"
#include "core/libraries/np_score/np_score.h"
#include "core/libraries/np_trophy/np_trophy.h"
@ -64,14 +67,17 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
Libraries::MsgDialog::RegisterlibSceMsgDialog(sym);
Libraries::AudioOut::RegisterlibSceAudioOut(sym);
Libraries::Http::RegisterlibSceHttp(sym);
Libraries::Http2::RegisterlibSceHttp2(sym);
Libraries::Net::RegisterlibSceNet(sym);
Libraries::NetCtl::RegisterlibSceNetCtl(sym);
Libraries::SaveData::RegisterlibSceSaveData(sym);
Libraries::SaveData::Dialog::RegisterlibSceSaveDataDialog(sym);
Libraries::Ssl::RegisterlibSceSsl(sym);
Libraries::Ssl2::RegisterlibSceSsl2(sym);
Libraries::SysModule::RegisterlibSceSysmodule(sym);
Libraries::Posix::Registerlibsceposix(sym);
Libraries::AudioIn::RegisterlibSceAudioIn(sym);
Libraries::NpCommon::RegisterlibSceNpCommon(sym);
Libraries::NpManager::RegisterlibSceNpManager(sym);
Libraries::NpScore::RegisterlibSceNpScore(sym);
Libraries::NpTrophy::RegisterlibSceNpTrophy(sym);

View File

@ -0,0 +1,360 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
#include "core/libraries/network/http2.h"
namespace Libraries::Http2 {
int PS4_SYSV_ABI _Z5dummyv() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2AbortRequest() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2AddCookie() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2AddRequestHeader() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2AuthCacheFlush() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2CookieExport() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2CookieFlush() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2CookieImport() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2CreateCookieBox() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2CreateRequestWithURL() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2CreateTemplate() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2DeleteCookieBox() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2DeleteRequest() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2DeleteTemplate() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2GetAllResponseHeaders() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2GetAuthEnabled() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2GetAutoRedirect() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2GetCookie() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2GetCookieBox() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2GetCookieStats() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2GetMemoryPoolStats() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2GetResponseContentLength() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2GetStatusCode() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2Init(int net_id, int ssl_id, size_t pool_size, int max_requests) {
LOG_ERROR(Lib_Http2, "(DUMMY) called");
static int id = 0;
return ++id;
}
int PS4_SYSV_ABI sceHttp2ReadData() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2ReadDataAsync() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2RedirectCacheFlush() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2RemoveRequestHeader() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SendRequest() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SendRequestAsync() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetAuthEnabled() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetAuthInfoCallback() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetAutoRedirect() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetConnectionWaitTimeOut() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetConnectTimeOut() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetCookieBox() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetCookieMaxNum() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetCookieMaxNumPerDomain() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetCookieMaxSize() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetCookieRecvCallback() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetCookieSendCallback() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetInflateGZIPEnabled() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetMinSslVersion() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetPreSendCallback() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetRecvTimeOut() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetRedirectCallback() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetRequestContentLength() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetResolveRetry() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetResolveTimeOut() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetSendTimeOut() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetSslCallback() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SetTimeOut() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SslDisableOption() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2SslEnableOption() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2Term() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceHttp2WaitAsync() {
LOG_ERROR(Lib_Http2, "(STUBBED) called");
return ORBIS_OK;
}
void RegisterlibSceHttp2(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("AS45QoYHjc4", "libSceHttp2", 1, "libSceHttp2", 1, 1, _Z5dummyv);
LIB_FUNCTION("IZ-qjhRqvjk", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2AbortRequest);
LIB_FUNCTION("flPxnowtvWY", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2AddCookie);
LIB_FUNCTION("nrPfOE8TQu0", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2AddRequestHeader);
LIB_FUNCTION("WeuDjj5m4YU", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2AuthCacheFlush);
LIB_FUNCTION("JlFGR4v50Kw", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2CookieExport);
LIB_FUNCTION("5VlQSzXW-SQ", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2CookieFlush);
LIB_FUNCTION("B5ibZI5UlzU", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2CookieImport);
LIB_FUNCTION("N4UfjvWJsMw", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2CreateCookieBox);
LIB_FUNCTION("mmyOCxQMVYQ", "libSceHttp2", 1, "libSceHttp2", 1, 1,
sceHttp2CreateRequestWithURL);
LIB_FUNCTION("+wCt7fCijgk", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2CreateTemplate);
LIB_FUNCTION("O9ync3F-JVI", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2DeleteCookieBox);
LIB_FUNCTION("c8D9qIjo8EY", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2DeleteRequest);
LIB_FUNCTION("pDom5-078DA", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2DeleteTemplate);
LIB_FUNCTION("-rdXUi2XW90", "libSceHttp2", 1, "libSceHttp2", 1, 1,
sceHttp2GetAllResponseHeaders);
LIB_FUNCTION("m-OL13q8AI8", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2GetAuthEnabled);
LIB_FUNCTION("od5QCZhZSfw", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2GetAutoRedirect);
LIB_FUNCTION("GQFGj0rYX+A", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2GetCookie);
LIB_FUNCTION("IX23slKvtQI", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2GetCookieBox);
LIB_FUNCTION("eij7UzkUqK8", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2GetCookieStats);
LIB_FUNCTION("otUQuZa-mv0", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2GetMemoryPoolStats);
LIB_FUNCTION("o0DBQpFE13o", "libSceHttp2", 1, "libSceHttp2", 1, 1,
sceHttp2GetResponseContentLength);
LIB_FUNCTION("9XYJwCf3lEA", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2GetStatusCode);
LIB_FUNCTION("3JCe3lCbQ8A", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2Init);
LIB_FUNCTION("QygCNNmbGss", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2ReadData);
LIB_FUNCTION("bGN-6zbo7ms", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2ReadDataAsync);
LIB_FUNCTION("klwUy2Wg+q8", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2RedirectCacheFlush);
LIB_FUNCTION("jHdP0CS4ZlA", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2RemoveRequestHeader);
LIB_FUNCTION("rbqZig38AT8", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SendRequest);
LIB_FUNCTION("A+NVAFu4eCg", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SendRequestAsync);
LIB_FUNCTION("jjFahkBPCYs", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetAuthEnabled);
LIB_FUNCTION("Wwj6HbB2mOo", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetAuthInfoCallback);
LIB_FUNCTION("b9AvoIaOuHI", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetAutoRedirect);
LIB_FUNCTION("n8hMLe31OPA", "libSceHttp2", 1, "libSceHttp2", 1, 1,
sceHttp2SetConnectionWaitTimeOut);
LIB_FUNCTION("-HIO4VT87v8", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetConnectTimeOut);
LIB_FUNCTION("jrVHsKCXA0g", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetCookieBox);
LIB_FUNCTION("mPKVhQqh2Es", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetCookieMaxNum);
LIB_FUNCTION("o7+WXe4WadE", "libSceHttp2", 1, "libSceHttp2", 1, 1,
sceHttp2SetCookieMaxNumPerDomain);
LIB_FUNCTION("6a0N6GPD7RM", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetCookieMaxSize);
LIB_FUNCTION("zdtXKn9X7no", "libSceHttp2", 1, "libSceHttp2", 1, 1,
sceHttp2SetCookieRecvCallback);
LIB_FUNCTION("McYmUpQ3-DY", "libSceHttp2", 1, "libSceHttp2", 1, 1,
sceHttp2SetCookieSendCallback);
LIB_FUNCTION("uRosf8GQbHQ", "libSceHttp2", 1, "libSceHttp2", 1, 1,
sceHttp2SetInflateGZIPEnabled);
LIB_FUNCTION("09tk+kIA1Ns", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetMinSslVersion);
LIB_FUNCTION("UL4Fviw+IAM", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetPreSendCallback);
LIB_FUNCTION("izvHhqgDt44", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetRecvTimeOut);
LIB_FUNCTION("BJgi0CH7al4", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetRedirectCallback);
LIB_FUNCTION("FSAFOzi0FpM", "libSceHttp2", 1, "libSceHttp2", 1, 1,
sceHttp2SetRequestContentLength);
LIB_FUNCTION("Gcjh+CisAZM", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetResolveRetry);
LIB_FUNCTION("ACjtE27aErY", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetResolveTimeOut);
LIB_FUNCTION("XPtW45xiLHk", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetSendTimeOut);
LIB_FUNCTION("YrWX+DhPHQY", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetSslCallback);
LIB_FUNCTION("VYMxTcBqSE0", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SetTimeOut);
LIB_FUNCTION("B37SruheQ5Y", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SslDisableOption);
LIB_FUNCTION("EWcwMpbr5F8", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2SslEnableOption);
LIB_FUNCTION("YiBUtz-pGkc", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2Term);
LIB_FUNCTION("MOp-AUhdfi8", "libSceHttp2", 1, "libSceHttp2", 1, 1, sceHttp2WaitAsync);
};
} // namespace Libraries::Http2

View File

@ -0,0 +1,72 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/types.h"
namespace Core::Loader {
class SymbolsResolver;
}
namespace Libraries::Http2 {
int PS4_SYSV_ABI _Z5dummyv();
int PS4_SYSV_ABI sceHttp2AbortRequest();
int PS4_SYSV_ABI sceHttp2AddCookie();
int PS4_SYSV_ABI sceHttp2AddRequestHeader();
int PS4_SYSV_ABI sceHttp2AuthCacheFlush();
int PS4_SYSV_ABI sceHttp2CookieExport();
int PS4_SYSV_ABI sceHttp2CookieFlush();
int PS4_SYSV_ABI sceHttp2CookieImport();
int PS4_SYSV_ABI sceHttp2CreateCookieBox();
int PS4_SYSV_ABI sceHttp2CreateRequestWithURL();
int PS4_SYSV_ABI sceHttp2CreateTemplate();
int PS4_SYSV_ABI sceHttp2DeleteCookieBox();
int PS4_SYSV_ABI sceHttp2DeleteRequest();
int PS4_SYSV_ABI sceHttp2DeleteTemplate();
int PS4_SYSV_ABI sceHttp2GetAllResponseHeaders();
int PS4_SYSV_ABI sceHttp2GetAuthEnabled();
int PS4_SYSV_ABI sceHttp2GetAutoRedirect();
int PS4_SYSV_ABI sceHttp2GetCookie();
int PS4_SYSV_ABI sceHttp2GetCookieBox();
int PS4_SYSV_ABI sceHttp2GetCookieStats();
int PS4_SYSV_ABI sceHttp2GetMemoryPoolStats();
int PS4_SYSV_ABI sceHttp2GetResponseContentLength();
int PS4_SYSV_ABI sceHttp2GetStatusCode();
int PS4_SYSV_ABI sceHttp2Init(int net_id, int ssl_id, size_t pool_size, int max_requests);
int PS4_SYSV_ABI sceHttp2ReadData();
int PS4_SYSV_ABI sceHttp2ReadDataAsync();
int PS4_SYSV_ABI sceHttp2RedirectCacheFlush();
int PS4_SYSV_ABI sceHttp2RemoveRequestHeader();
int PS4_SYSV_ABI sceHttp2SendRequest();
int PS4_SYSV_ABI sceHttp2SendRequestAsync();
int PS4_SYSV_ABI sceHttp2SetAuthEnabled();
int PS4_SYSV_ABI sceHttp2SetAuthInfoCallback();
int PS4_SYSV_ABI sceHttp2SetAutoRedirect();
int PS4_SYSV_ABI sceHttp2SetConnectionWaitTimeOut();
int PS4_SYSV_ABI sceHttp2SetConnectTimeOut();
int PS4_SYSV_ABI sceHttp2SetCookieBox();
int PS4_SYSV_ABI sceHttp2SetCookieMaxNum();
int PS4_SYSV_ABI sceHttp2SetCookieMaxNumPerDomain();
int PS4_SYSV_ABI sceHttp2SetCookieMaxSize();
int PS4_SYSV_ABI sceHttp2SetCookieRecvCallback();
int PS4_SYSV_ABI sceHttp2SetCookieSendCallback();
int PS4_SYSV_ABI sceHttp2SetInflateGZIPEnabled();
int PS4_SYSV_ABI sceHttp2SetMinSslVersion();
int PS4_SYSV_ABI sceHttp2SetPreSendCallback();
int PS4_SYSV_ABI sceHttp2SetRecvTimeOut();
int PS4_SYSV_ABI sceHttp2SetRedirectCallback();
int PS4_SYSV_ABI sceHttp2SetRequestContentLength();
int PS4_SYSV_ABI sceHttp2SetResolveRetry();
int PS4_SYSV_ABI sceHttp2SetResolveTimeOut();
int PS4_SYSV_ABI sceHttp2SetSendTimeOut();
int PS4_SYSV_ABI sceHttp2SetSslCallback();
int PS4_SYSV_ABI sceHttp2SetTimeOut();
int PS4_SYSV_ABI sceHttp2SslDisableOption();
int PS4_SYSV_ABI sceHttp2SslEnableOption();
int PS4_SYSV_ABI sceHttp2Term();
int PS4_SYSV_ABI sceHttp2WaitAsync();
void RegisterlibSceHttp2(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Http2

View File

@ -0,0 +1,353 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"
#include "core/libraries/network/ssl2.h"
namespace Libraries::Ssl2 {
int PS4_SYSV_ABI CA_MGMT_extractKeyBlobEx() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI CA_MGMT_extractPublicKeyInfo() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI CA_MGMT_freeKeyBlob() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI CRYPTO_initAsymmetricKey() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI CRYPTO_uninitAsymmetricKey() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI RSA_verifySignature() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslCheckRecvPending() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslClose() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslConnect() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslCreateConnection() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslCreateSslConnection() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslDeleteConnection() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslDeleteSslConnection() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslDisableOption() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslDisableOptionInternal() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslDisableOptionInternalInsecure() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslDisableVerifyOption() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslEnableOption() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslEnableOptionInternal() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslEnableVerifyOption() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslFreeCaCerts() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslFreeCaList() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslFreeSslCertName() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetAlpnSelected() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetCaCerts() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetCaList() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetFingerprint() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetIssuerName() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetMemoryPoolStats() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetNameEntryCount() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetNameEntryInfo() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetNanoSSLModuleId() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetNotAfter() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetNotBefore() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetPeerCert() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetPem() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetSerialNumber() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetSslError() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslGetSubjectName() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslInit(std::size_t poolSize) {
LOG_ERROR(Lib_Ssl2, "(DUMMY) called poolSize = {}", poolSize);
// return a value >1
static int id = 0;
return ++id;
}
int PS4_SYSV_ABI sceSslLoadCert() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslLoadRootCACert() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslRead() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslRecv() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslReuseConnection() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslSend() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslSetAlpn() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslSetMinSslVersion() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslSetSslVersion() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslSetVerifyCallback() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslTerm() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslUnloadCert() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceSslWrite() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI VLONG_freeVlongQueue() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI Func_22E76E60BC0587D7() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI Func_28F8791A771D39C7() {
LOG_ERROR(Lib_Ssl2, "(STUBBED) called");
return ORBIS_OK;
}
void RegisterlibSceSsl2(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("Md+HYkCBZB4", "libSceSsl", 1, "libSceSsl", 2, 1, CA_MGMT_extractKeyBlobEx);
LIB_FUNCTION("9bKYzKP6kYU", "libSceSsl", 1, "libSceSsl", 2, 1, CA_MGMT_extractPublicKeyInfo);
LIB_FUNCTION("ipLIammTj2Q", "libSceSsl", 1, "libSceSsl", 2, 1, CA_MGMT_freeKeyBlob);
LIB_FUNCTION("PRWr3-ytpdg", "libSceSsl", 1, "libSceSsl", 2, 1, CRYPTO_initAsymmetricKey);
LIB_FUNCTION("cW7VCIMCh9A", "libSceSsl", 1, "libSceSsl", 2, 1, CRYPTO_uninitAsymmetricKey);
LIB_FUNCTION("pBwtarKd7eg", "libSceSsl", 1, "libSceSsl", 2, 1, RSA_verifySignature);
LIB_FUNCTION("1VM0h1JrUfA", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslCheckRecvPending);
LIB_FUNCTION("viRXSHZYd0c", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslClose);
LIB_FUNCTION("zXvd6iNyfgc", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslConnect);
LIB_FUNCTION("tuscfitnhEo", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslCreateConnection);
LIB_FUNCTION("P14ATpXc4J8", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslCreateSslConnection);
LIB_FUNCTION("HJ1n138CQ2g", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslDeleteConnection);
LIB_FUNCTION("hwrHV6Pprk4", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslDeleteSslConnection);
LIB_FUNCTION("iLKz4+ukLqk", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslDisableOption);
LIB_FUNCTION("-WqxBRAUVM4", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslDisableOptionInternal);
LIB_FUNCTION("w1+L-27nYas", "libSceSsl", 1, "libSceSsl", 2, 1,
sceSslDisableOptionInternalInsecure);
LIB_FUNCTION("PwsHbErG+e8", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslDisableVerifyOption);
LIB_FUNCTION("m-zPyAsIpco", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslEnableOption);
LIB_FUNCTION("g-zCwUKstEQ", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslEnableOptionInternal);
LIB_FUNCTION("po1X86mgHDU", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslEnableVerifyOption);
LIB_FUNCTION("qIvLs0gYxi0", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslFreeCaCerts);
LIB_FUNCTION("+DzXseDVkeI", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslFreeCaList);
LIB_FUNCTION("RwXD8grHZHM", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslFreeSslCertName);
LIB_FUNCTION("4O7+bRkRUe8", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetAlpnSelected);
LIB_FUNCTION("TDfQqO-gMbY", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetCaCerts);
LIB_FUNCTION("qOn+wm28wmA", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetCaList);
LIB_FUNCTION("brRtwGBu4A8", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetFingerprint);
LIB_FUNCTION("7whYpYfHP74", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetIssuerName);
LIB_FUNCTION("-PoIzr3PEk0", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetMemoryPoolStats);
LIB_FUNCTION("R1ePzopYPYM", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetNameEntryCount);
LIB_FUNCTION("7RBSTKGrmDA", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetNameEntryInfo);
LIB_FUNCTION("AzUipl-DpIw", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetNanoSSLModuleId);
LIB_FUNCTION("xHpt6+2pGYk", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetNotAfter);
LIB_FUNCTION("Eo0S65Jy28Q", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetNotBefore);
LIB_FUNCTION("-TbZc8pwPNc", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetPeerCert);
LIB_FUNCTION("kLB5aGoUJXg", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetPem);
LIB_FUNCTION("DOwXL+FQMEY", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetSerialNumber);
LIB_FUNCTION("0XcZknp7-Wc", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetSslError);
LIB_FUNCTION("dQReuBX9sD8", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslGetSubjectName);
LIB_FUNCTION("hdpVEUDFW3s", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslInit);
LIB_FUNCTION("Ab7+DH+gYyM", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslLoadCert);
LIB_FUNCTION("3-643mGVFJo", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslLoadRootCACert);
LIB_FUNCTION("jltWpVKtetg", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslRead);
LIB_FUNCTION("hi0veU3L2pU", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslRecv);
LIB_FUNCTION("50R2xYaYZwE", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslReuseConnection);
LIB_FUNCTION("p5bM5PPufFY", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslSend);
LIB_FUNCTION("TL86glUrmUw", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslSetAlpn);
LIB_FUNCTION("QWSxBzf6lAg", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslSetMinSslVersion);
LIB_FUNCTION("bKaEtQnoUuQ", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslSetSslVersion);
LIB_FUNCTION("E4a-ahM57QQ", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslSetVerifyCallback);
LIB_FUNCTION("0K1yQ6Lv-Yc", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslTerm);
LIB_FUNCTION("UQ+3Qu7v3cA", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslUnloadCert);
LIB_FUNCTION("iNjkt9Poblw", "libSceSsl", 1, "libSceSsl", 2, 1, sceSslWrite);
LIB_FUNCTION("wcVuyTUr5ys", "libSceSsl", 1, "libSceSsl", 2, 1, VLONG_freeVlongQueue);
LIB_FUNCTION("IuduYLwFh9c", "libSceSsl", 1, "libSceSsl", 2, 1, Func_22E76E60BC0587D7);
LIB_FUNCTION("KPh5GncdOcc", "libSceSsl", 1, "libSceSsl", 2, 1, Func_28F8791A771D39C7);
};
} // namespace Libraries::Ssl2

View File

@ -0,0 +1,14 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/types.h"
namespace Core::Loader {
class SymbolsResolver;
}
namespace Libraries::Ssl2 {
void RegisterlibSceSsl2(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Ssl2

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/libraries/error_codes.h"
constexpr int ORBIS_NP_ERROR_INVALID_ARGUMENT = 0x80550003;
constexpr int ORBIS_NP_UTIL_ERROR_NOT_MATCH = 0x80550609;

View File

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/config.h"
#include "common/logging/log.h"
#include "core/libraries/error_codes.h"
#include "core/libraries/libs.h"

View File

@ -11,7 +11,6 @@
#include <SDL3/SDL.h>
#if defined(__APPLE__)
#include <TargetConditionals.h>
#include <dispatch/dispatch.h>
#endif
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
@ -72,33 +71,25 @@ static void PlatformSetImeData(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlat
auto window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle;
SDL_Window* window = SDL_GetWindowFromID(window_id);
if ((!data->WantVisible || bd->ime_window != window) && bd->ime_window != nullptr) {
auto stop_input = [&bd] { SDL_StopTextInput(bd->ime_window); };
#ifdef __APPLE__
dispatch_sync(dispatch_get_main_queue(), ^{
stop_input();
});
#else
stop_input();
#endif
SDL_RunOnMainThread(
[](void* userdata) { SDL_StopTextInput(static_cast<SDL_Window*>(userdata)); },
bd->ime_window, true);
bd->ime_window = nullptr;
}
if (data->WantVisible) {
SDL_Rect r;
r.x = (int)data->InputPos.x;
r.y = (int)data->InputPos.y;
r.w = 1;
r.h = (int)data->InputLineHeight;
const auto start_input = [&window, &r] {
SDL_SetTextInputArea(window, &r, 0);
SDL_StartTextInput(window);
};
#ifdef __APPLE__
dispatch_sync(dispatch_get_main_queue(), ^{
start_input();
});
#else
start_input();
#endif
std::pair<SDL_Window*, SDL_Rect> usr_data;
usr_data.first = window;
usr_data.second.x = (int)data->InputPos.x;
usr_data.second.y = (int)data->InputPos.y;
usr_data.second.w = 1;
usr_data.second.h = (int)data->InputLineHeight;
SDL_RunOnMainThread(
[](void* userdata) {
auto* params = static_cast<std::pair<SDL_Window*, SDL_Rect>*>(userdata);
SDL_SetTextInputArea(params->first, &params->second, 0);
SDL_StartTextInput(params->first);
},
&usr_data, true);
bd->ime_window = window;
}
}

View File

@ -106,6 +106,8 @@ void GameListFrame::PlayBackgroundMusic(QTableWidgetItem* item) {
void GameListFrame::PopulateGameList() {
// Do not show status column if it is not enabled
this->setColumnHidden(2, !Config::getCompatibilityEnabled());
this->setColumnHidden(6, !Config::GetLoadGameSizeEnabled());
this->setRowCount(m_game_info->m_games.size());
ResizeIcons(icon_size);

View File

@ -62,11 +62,46 @@ public:
QDir dir(dirPath);
QDirIterator it(dir.absolutePath(), QDirIterator::Subdirectories);
qint64 total = 0;
if (!Config::GetLoadGameSizeEnabled()) {
game.size = FormatSize(0).toStdString();
return;
}
// Cache path
QFile size_cache_file(Common::FS::GetUserPath(Common::FS::PathType::MetaDataDir) /
game.serial / "size_cache.txt");
QFileInfo cacheInfo(size_cache_file);
QFileInfo dirInfo(dirPath);
// Check if cache file exists and is valid
if (size_cache_file.exists() && cacheInfo.lastModified() >= dirInfo.lastModified()) {
if (size_cache_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&size_cache_file);
QString cachedSize = in.readLine();
size_cache_file.close();
if (!cachedSize.isEmpty()) {
game.size = cachedSize.toStdString();
return;
}
}
}
// Cache is invalid or does not exist; calculate size
while (it.hasNext()) {
it.next();
total += it.fileInfo().size();
}
game.size = FormatSize(total).toStdString();
// Save new cache
if (size_cache_file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&size_cache_file);
out << QString::fromStdString(game.size) << "\n";
size_cache_file.close();
}
}
static QString GetRegion(char region) {

View File

@ -283,7 +283,7 @@ public:
#ifdef Q_OS_WIN
if (createShortcutWin(linkPath, ebootPath, icoPath, exePath)) {
#else
if (createShortcutLinux(linkPath, ebootPath, iconPath)) {
if (createShortcutLinux(linkPath, m_games[itemID].name, ebootPath, iconPath)) {
#endif
QMessageBox::information(
nullptr, tr("Shortcut creation"),
@ -301,7 +301,7 @@ public:
#ifdef Q_OS_WIN
if (createShortcutWin(linkPath, ebootPath, iconPath, exePath)) {
#else
if (createShortcutLinux(linkPath, ebootPath, iconPath)) {
if (createShortcutLinux(linkPath, m_games[itemID].name, ebootPath, iconPath)) {
#endif
QMessageBox::information(
nullptr, tr("Shortcut creation"),
@ -510,8 +510,8 @@ private:
return SUCCEEDED(hres);
}
#else
bool createShortcutLinux(const QString& linkPath, const QString& targetPath,
const QString& iconPath) {
bool createShortcutLinux(const QString& linkPath, const std::string& name,
const QString& targetPath, const QString& iconPath) {
QFile shortcutFile(linkPath);
if (!shortcutFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
QMessageBox::critical(nullptr, "Error",
@ -522,7 +522,7 @@ private:
QTextStream out(&shortcutFile);
out << "[Desktop Entry]\n";
out << "Version=1.0\n";
out << "Name=" << QFileInfo(linkPath).baseName() << "\n";
out << "Name=" << QString::fromStdString(name) << "\n";
out << "Exec=" << QCoreApplication::applicationFilePath() << " \"" << targetPath << "\"\n";
out << "Icon=" << iconPath << "\n";
out << "Terminal=false\n";

View File

@ -47,6 +47,9 @@ PKGViewer::PKGViewer(std::shared_ptr<GameInfoClass> game_info_get, QWidget* pare
connect(treeWidget, &QTreeWidget::customContextMenuRequested, this,
[=, this](const QPoint& pos) {
if (treeWidget->selectedItems().isEmpty()) {
return;
}
m_gui_context_menus.RequestGameMenuPKGViewer(pos, m_full_pkg_list, treeWidget,
InstallDragDropPkg);
});

View File

@ -315,6 +315,7 @@ void SettingsDialog::LoadValuesFromConfig() {
toml::find_or<std::string>(data, "General", "FullscreenMode", "Borderless")));
ui->separateUpdatesCheckBox->setChecked(
toml::find_or<bool>(data, "General", "separateUpdateEnabled", false));
ui->gameSizeCheckBox->setChecked(toml::find_or<bool>(data, "GUI", "loadGameSizeEnabled", true));
ui->showSplashCheckBox->setChecked(toml::find_or<bool>(data, "General", "showSplash", false));
ui->logTypeComboBox->setCurrentText(
QString::fromStdString(toml::find_or<std::string>(data, "General", "logType", "async")));
@ -568,6 +569,7 @@ void SettingsDialog::UpdateSettings() {
Config::setDumpShaders(ui->dumpShadersCheckBox->isChecked());
Config::setNullGpu(ui->nullGpuCheckBox->isChecked());
Config::setSeparateUpdateEnabled(ui->separateUpdatesCheckBox->isChecked());
Config::setLoadGameSizeEnabled(ui->gameSizeCheckBox->isChecked());
Config::setShowSplash(ui->showSplashCheckBox->isChecked());
Config::setDebugDump(ui->debugDump->isChecked());
Config::setVkValidation(ui->vkValidationCheckBox->isChecked());

View File

@ -68,7 +68,7 @@
<x>0</x>
<y>0</y>
<width>946</width>
<height>536</height>
<height>586</height>
</rect>
</property>
<layout class="QVBoxLayout" name="generalTabVLayout" stretch="0">
@ -134,7 +134,7 @@
</property>
</widget>
</item>
<item>
<item>
<widget class="QGroupBox" name="fullscreenModeGroupBox">
<property name="title">
<string>Fullscreen Mode</string>
@ -483,6 +483,13 @@
<property name="bottomMargin">
<number>11</number>
</property>
<item>
<widget class="QCheckBox" name="gameSizeCheckBox">
<property name="text">
<string>Show Game Size In List</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="playBGMCheckBox">
<property name="sizePolicy">
@ -557,59 +564,59 @@
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="vLayoutTrophy">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>50</number>
</property>
<item>
<layout class="QVBoxLayout" name="vLayoutTrophy">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>80</number>
</property>
<layout class="QHBoxLayout" name="hLayoutTrophy">
<item>
<layout class="QHBoxLayout" name="hLayoutTrophy">
<item>
<widget class="QGroupBox" name="trophyGroupBox">
<property name="title">
<string>Trophy</string>
</property>
<layout class="QVBoxLayout" name="userNameLayout">
<item>
<widget class="QCheckBox" name="disableTrophycheckBox">
<property name="text">
<string>Disable Trophy Pop-ups</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_Trophy">
<property name="text">
<string>Trophy Key</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="trophyKeyLineEdit">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
<bold>false</bold>
</font>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
<widget class="QGroupBox" name="trophyGroupBox">
<property name="title">
<string>Trophy</string>
</property>
<layout class="QVBoxLayout" name="userNameLayout">
<item>
<widget class="QCheckBox" name="disableTrophycheckBox">
<property name="text">
<string>Disable Trophy Pop-ups</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_Trophy">
<property name="text">
<string>Trophy Key</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="trophyKeyLineEdit">
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>10</pointsize>
<bold>false</bold>
</font>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
@ -637,8 +644,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>926</width>
<height>536</height>
<width>946</width>
<height>586</height>
</rect>
</property>
<layout class="QVBoxLayout" name="inputTabVLayout" stretch="0,0">
@ -853,13 +860,13 @@
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="motionControlsCheckBox">
<property name="text">
<string>Enable Motion Controls</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="motionControlsCheckBox">
<property name="text">
<string>Enable Motion Controls</string>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="controllerWidgetSpacer" native="true">
<property name="enabled">
@ -935,8 +942,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>926</width>
<height>536</height>
<width>946</width>
<height>586</height>
</rect>
</property>
<layout class="QVBoxLayout" name="graphicsTabVLayout" stretch="0,0">
@ -1186,8 +1193,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>926</width>
<height>536</height>
<width>946</width>
<height>586</height>
</rect>
</property>
<layout class="QVBoxLayout" name="pathsTabLayout" stretch="0">
@ -1259,8 +1266,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>926</width>
<height>536</height>
<width>946</width>
<height>586</height>
</rect>
</property>
<layout class="QVBoxLayout" name="debugTabVLayout" stretch="0,1">

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>عرض حجم اللعبة في القائمة</translation>
</message>
<message>
<source>Show Splash</source>
<translation>إظهار شاشة البداية</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Vis vis spilstørrelse i listen</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Show Splash</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Zeigen Sie die Spielgröße in der Liste</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Startbildschirm anzeigen</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Εμφάνιση Μεγέθους Παιχνιδιού στη Λίστα</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Show Splash</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Show Game Size In List</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Show Splash</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Mostrar Tamaño del Juego en la Lista</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Mostrar splash</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>فعالسازی پوشه جداگانه برای بهروزرسانی</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>نمایش اندازه بازی در لیست</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Splash نمایش</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Ota Käyttöön Erillinen Päivityshakemisto</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Näytä pelin koko luettelossa</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Näytä Aloitusnäyttö</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Dossier séparé pour les mises à jours</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Afficher la taille du jeu dans la liste</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Afficher l'image du jeu</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Külön Frissítési Mappa Engedélyezése</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Játékméret megjelenítése a listában</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Indítóképernyő Mutatása</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Tampilkan Ukuran Game di Daftar</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Show Splash</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Abilita Cartella Aggiornamenti Separata</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Mostra la dimensione del gioco nell'elenco</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Mostra Schermata Iniziale</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation></translation>
</message>
<message>
<source>Show Splash</source>
<translation></translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation> </translation>
</message>
<message>
<source>Show Splash</source>
<translation>Show Splash</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Rodyti žaidimo dydį sąraše</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Show Splash</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Aktiver seperat oppdateringsmappe</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Vis spillstørrelse i listen</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Vis velkomstbilde</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Toon grootte van het spel in de lijst</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Show Splash</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Pokaż rozmiar gry na liście</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Pokaż ekran powitania</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Habilitar pasta de atualização separada</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Mostrar Tamanho do Jogo na Lista</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Mostrar Splash Inicial</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Afișează dimensiunea jocului în listă</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Show Splash</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Отдельная папка обновлений</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Показать размер игры в списке</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Показывать заставку</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Aktivizo dosjen e ndarë përditësimit</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Shfaq madhësinë e lojës listë</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Shfaq Pamjen e nisjes</translation>

View File

@ -1032,6 +1032,10 @@
<source>Enable Separate Update Folder</source>
<translation>Aktivera separat uppdateringsmapp</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Visa spelstorlek i listan</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Visa startskärm</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Göster oyun boyutunu listede</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Başlangıç Ekranını Göster</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Увімкнути окрему папку оновлень</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Показати розмір гри в списку</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Показувати заставку</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation>Hiển thị Kích thước Game trong Danh sách</translation>
</message>
<message>
<source>Show Splash</source>
<translation>Show Splash</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation></translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation></translation>
</message>
<message>
<source>Show Splash</source>
<translation></translation>
@ -558,11 +562,11 @@
</message>
<message>
<source>Trophy Key</source>
<translation>Trophy Key</translation>
<translation></translation>
</message>
<message>
<source>Trophy</source>
<translation>Trophy</translation>
<translation></translation>
</message>
<message>
<source>Logger</source>
@ -782,7 +786,7 @@
</message>
<message>
<source>TrophyKey</source>
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
<translation>\n用于解密奖杯的密钥\n仅包含十六进制字符</translation>
</message>
<message>
<source>logTypeGroupBox</source>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation>
</message>
<message>
<source>Show Game Size In List</source>
<translation></translation>
</message>
<message>
<source>Show Splash</source>
<translation>Show Splash</translation>

View File

@ -205,7 +205,9 @@ void WindowSDL::InitTimers() {
void WindowSDL::RequestKeyboard() {
if (keyboard_grab == 0) {
SDL_StartTextInput(window);
SDL_RunOnMainThread(
[](void* userdata) { SDL_StartTextInput(static_cast<SDL_Window*>(userdata)); }, window,
true);
}
keyboard_grab++;
}
@ -214,7 +216,9 @@ void WindowSDL::ReleaseKeyboard() {
ASSERT(keyboard_grab > 0);
keyboard_grab--;
if (keyboard_grab == 0) {
SDL_StopTextInput(window);
SDL_RunOnMainThread(
[](void* userdata) { SDL_StopTextInput(static_cast<SDL_Window*>(userdata)); }, window,
true);
}
}

View File

@ -172,20 +172,18 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, u32 handle, Id lod
const auto& texture = ctx.images[handle & 0xFFFF];
const Id image = ctx.OpLoad(texture.image_type, texture.id);
const auto sharp = ctx.info.images[handle & 0xFFFF].GetSharp(ctx.info);
const auto type = sharp.GetBoundType();
const Id zero = ctx.u32_zero_value;
const auto mips{[&] { return has_mips ? ctx.OpImageQueryLevels(ctx.U32[1], image) : zero; }};
const bool uses_lod{type != AmdGpu::ImageType::Color2DMsaa && !texture.is_storage};
const bool uses_lod{texture.view_type != AmdGpu::ImageType::Color2DMsaa && !texture.is_storage};
const auto query{[&](Id type) {
return uses_lod ? ctx.OpImageQuerySizeLod(type, image, lod)
: ctx.OpImageQuerySize(type, image);
}};
switch (type) {
switch (texture.view_type) {
case AmdGpu::ImageType::Color1D:
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips());
case AmdGpu::ImageType::Color1DArray:
case AmdGpu::ImageType::Color2D:
case AmdGpu::ImageType::Cube:
case AmdGpu::ImageType::Color2DMsaa:
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[2]), zero, mips());
case AmdGpu::ImageType::Color2DArray:
@ -257,4 +255,12 @@ void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id
ctx.OpImageWrite(image, coords, texel, operands.mask, operands.operands);
}
Id EmitCubeFaceIndex(EmitContext& ctx, IR::Inst* inst, Id cube_coords) {
if (ctx.profile.supports_native_cube_calc) {
return ctx.OpCubeFaceIndexAMD(ctx.F32[1], cube_coords);
} else {
UNREACHABLE_MSG("SPIR-V Instruction");
}
}
} // namespace Shader::Backend::SPIRV

View File

@ -439,6 +439,7 @@ Id EmitImageAtomicAnd32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords,
Id EmitImageAtomicOr32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
Id EmitImageAtomicXor32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
Id EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id value);
Id EmitCubeFaceIndex(EmitContext& ctx, IR::Inst* inst, Id cube_coords);
Id EmitLaneId(EmitContext& ctx);
Id EmitWarpId(EmitContext& ctx);
Id EmitQuadShuffle(EmitContext& ctx, Id value, Id index);

View File

@ -773,8 +773,8 @@ spv::ImageFormat GetFormat(const AmdGpu::Image& image) {
Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) {
const auto image = desc.GetSharp(ctx.info);
const auto format = desc.is_atomic ? GetFormat(image) : spv::ImageFormat::Unknown;
const auto type = image.GetBoundType();
const u32 sampled = desc.IsStorage(image) ? 2 : 1;
const auto type = image.GetViewType(desc.is_array);
const u32 sampled = desc.is_written ? 2 : 1;
switch (type) {
case AmdGpu::ImageType::Color1D:
return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, false, false, sampled, format);
@ -788,9 +788,6 @@ Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) {
return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, false, true, sampled, format);
case AmdGpu::ImageType::Color3D:
return ctx.TypeImage(sampled_type, spv::Dim::Dim3D, false, false, false, sampled, format);
case AmdGpu::ImageType::Cube:
return ctx.TypeImage(sampled_type, spv::Dim::Cube, false, desc.is_array, false, sampled,
format);
default:
break;
}
@ -802,7 +799,7 @@ void EmitContext::DefineImagesAndSamplers() {
const auto sharp = image_desc.GetSharp(info);
const auto nfmt = sharp.GetNumberFmt();
const bool is_integer = AmdGpu::IsInteger(nfmt);
const bool is_storage = image_desc.IsStorage(sharp);
const bool is_storage = image_desc.is_written;
const VectorIds& data_types = GetAttributeType(*this, nfmt);
const Id sampled_type = data_types[1];
const Id image_type{ImageType(*this, image_desc, sampled_type)};
@ -817,6 +814,7 @@ void EmitContext::DefineImagesAndSamplers() {
.sampled_type = is_storage ? sampled_type : TypeSampledImage(image_type),
.pointer_type = pointer_type,
.image_type = image_type,
.view_type = sharp.GetViewType(image_desc.is_array),
.is_integer = is_integer,
.is_storage = is_storage,
});

View File

@ -222,6 +222,7 @@ public:
Id sampled_type;
Id pointer_type;
Id image_type;
AmdGpu::ImageType view_type;
bool is_integer = false;
bool is_storage = false;
};

View File

@ -301,6 +301,9 @@ private:
IR::U32 VMovRelSHelper(u32 src_vgprno, const IR::U32 m0);
void VMovRelDHelper(u32 dst_vgprno, const IR::U32 src_val, const IR::U32 m0);
IR::F32 SelectCubeResult(const IR::F32& x, const IR::F32& y, const IR::F32& z,
const IR::F32& x_res, const IR::F32& y_res, const IR::F32& z_res);
void LogMissingOpcode(const GcnInst& inst);
private:

View File

@ -3,6 +3,7 @@
#include "shader_recompiler/frontend/opcodes.h"
#include "shader_recompiler/frontend/translate/translate.h"
#include "shader_recompiler/profile.h"
namespace Shader::Gcn {
@ -1042,20 +1043,81 @@ void Translator::V_MAD_U32_U24(const GcnInst& inst) {
V_MAD_I32_I24(inst, false);
}
IR::F32 Translator::SelectCubeResult(const IR::F32& x, const IR::F32& y, const IR::F32& z,
const IR::F32& x_res, const IR::F32& y_res,
const IR::F32& z_res) {
const auto abs_x = ir.FPAbs(x);
const auto abs_y = ir.FPAbs(y);
const auto abs_z = ir.FPAbs(z);
const auto z_face_cond{
ir.LogicalAnd(ir.FPGreaterThanEqual(abs_z, abs_x), ir.FPGreaterThanEqual(abs_z, abs_y))};
const auto y_face_cond{ir.FPGreaterThanEqual(abs_y, abs_x)};
return IR::F32{ir.Select(z_face_cond, z_res, ir.Select(y_face_cond, y_res, x_res))};
}
void Translator::V_CUBEID_F32(const GcnInst& inst) {
SetDst(inst.dst[0], GetSrc<IR::F32>(inst.src[2]));
const auto x = GetSrc<IR::F32>(inst.src[0]);
const auto y = GetSrc<IR::F32>(inst.src[1]);
const auto z = GetSrc<IR::F32>(inst.src[2]);
IR::F32 result;
if (profile.supports_native_cube_calc) {
result = ir.CubeFaceIndex(ir.CompositeConstruct(x, y, z));
} else {
const auto x_neg_cond{ir.FPLessThan(x, ir.Imm32(0.f))};
const auto y_neg_cond{ir.FPLessThan(y, ir.Imm32(0.f))};
const auto z_neg_cond{ir.FPLessThan(z, ir.Imm32(0.f))};
const IR::F32 x_face{ir.Select(x_neg_cond, ir.Imm32(1.f), ir.Imm32(0.f))};
const IR::F32 y_face{ir.Select(y_neg_cond, ir.Imm32(3.f), ir.Imm32(2.f))};
const IR::F32 z_face{ir.Select(z_neg_cond, ir.Imm32(5.f), ir.Imm32(4.f))};
result = SelectCubeResult(x, y, z, x_face, y_face, z_face);
}
SetDst(inst.dst[0], result);
}
void Translator::V_CUBESC_F32(const GcnInst& inst) {
SetDst(inst.dst[0], GetSrc<IR::F32>(inst.src[0]));
const auto x = GetSrc<IR::F32>(inst.src[0]);
const auto y = GetSrc<IR::F32>(inst.src[1]);
const auto z = GetSrc<IR::F32>(inst.src[2]);
const auto x_neg_cond{ir.FPLessThan(x, ir.Imm32(0.f))};
const auto z_neg_cond{ir.FPLessThan(z, ir.Imm32(0.f))};
const IR::F32 x_sc{ir.Select(x_neg_cond, z, ir.FPNeg(z))};
const IR::F32 y_sc{x};
const IR::F32 z_sc{ir.Select(z_neg_cond, ir.FPNeg(x), x)};
const auto result{SelectCubeResult(x, y, z, x_sc, y_sc, z_sc)};
SetDst(inst.dst[0], result);
}
void Translator::V_CUBETC_F32(const GcnInst& inst) {
SetDst(inst.dst[0], GetSrc<IR::F32>(inst.src[1]));
const auto x = GetSrc<IR::F32>(inst.src[0]);
const auto y = GetSrc<IR::F32>(inst.src[1]);
const auto z = GetSrc<IR::F32>(inst.src[2]);
const auto y_neg_cond{ir.FPLessThan(y, ir.Imm32(0.f))};
const IR::F32 x_z_tc{ir.FPNeg(y)};
const IR::F32 y_tc{ir.Select(y_neg_cond, ir.FPNeg(z), z)};
const auto result{SelectCubeResult(x, y, z, x_z_tc, y_tc, x_z_tc)};
SetDst(inst.dst[0], result);
}
void Translator::V_CUBEMA_F32(const GcnInst& inst) {
SetDst(inst.dst[0], ir.Imm32(1.f));
const auto x = GetSrc<IR::F32>(inst.src[0]);
const auto y = GetSrc<IR::F32>(inst.src[1]);
const auto z = GetSrc<IR::F32>(inst.src[2]);
const auto two{ir.Imm32(2.f)};
const IR::F32 x_major_axis{ir.FPMul(x, two)};
const IR::F32 y_major_axis{ir.FPMul(y, two)};
const IR::F32 z_major_axis{ir.FPMul(z, two)};
const auto result{SelectCubeResult(x, y, z, x_major_axis, y_major_axis, z_major_axis)};
SetDst(inst.dst[0], result);
}
void Translator::V_BFE_U32(bool is_signed, const GcnInst& inst) {

View File

@ -418,6 +418,7 @@ void Translator::IMAGE_LOAD(bool has_mip, const GcnInst& inst) {
IR::TextureInstInfo info{};
info.has_lod.Assign(has_mip);
info.is_array.Assign(mimg.da);
const IR::Value texel = ir.ImageRead(handle, body, {}, {}, info);
for (u32 i = 0; i < 4; i++) {
@ -442,6 +443,7 @@ void Translator::IMAGE_STORE(bool has_mip, const GcnInst& inst) {
IR::TextureInstInfo info{};
info.has_lod.Assign(has_mip);
info.is_array.Assign(mimg.da);
boost::container::static_vector<IR::F32, 4> comps;
for (u32 i = 0; i < 4; i++) {
@ -456,13 +458,18 @@ void Translator::IMAGE_STORE(bool has_mip, const GcnInst& inst) {
}
void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) {
const auto& mimg = inst.control.mimg;
IR::VectorReg dst_reg{inst.dst[0].code};
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4};
const auto flags = ImageResFlags(inst.control.mimg.dmask);
const bool has_mips = flags.test(ImageResComponent::MipCount);
const IR::U32 lod = ir.GetVectorReg(IR::VectorReg(inst.src[0].code));
const IR::Value tsharp = ir.GetScalarReg(tsharp_reg);
const IR::Value size = ir.ImageQueryDimension(tsharp, lod, ir.Imm1(has_mips));
IR::TextureInstInfo info{};
info.is_array.Assign(mimg.da);
const IR::Value size = ir.ImageQueryDimension(tsharp, lod, ir.Imm1(has_mips), info);
if (flags.test(ImageResComponent::Width)) {
ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 0)});
@ -484,6 +491,9 @@ void Translator::IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst) {
IR::VectorReg addr_reg{inst.src[0].code};
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4};
IR::TextureInstInfo info{};
info.is_array.Assign(mimg.da);
const IR::Value value = ir.GetVectorReg(val_reg);
const IR::Value handle = ir.GetScalarReg(tsharp_reg);
const IR::Value body =
@ -494,25 +504,25 @@ void Translator::IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst) {
case AtomicOp::Swap:
return ir.ImageAtomicExchange(handle, body, value, {});
case AtomicOp::Add:
return ir.ImageAtomicIAdd(handle, body, value, {});
return ir.ImageAtomicIAdd(handle, body, value, info);
case AtomicOp::Smin:
return ir.ImageAtomicIMin(handle, body, value, true, {});
return ir.ImageAtomicIMin(handle, body, value, true, info);
case AtomicOp::Umin:
return ir.ImageAtomicUMin(handle, body, value, {});
return ir.ImageAtomicUMin(handle, body, value, info);
case AtomicOp::Smax:
return ir.ImageAtomicIMax(handle, body, value, true, {});
return ir.ImageAtomicIMax(handle, body, value, true, info);
case AtomicOp::Umax:
return ir.ImageAtomicUMax(handle, body, value, {});
return ir.ImageAtomicUMax(handle, body, value, info);
case AtomicOp::And:
return ir.ImageAtomicAnd(handle, body, value, {});
return ir.ImageAtomicAnd(handle, body, value, info);
case AtomicOp::Or:
return ir.ImageAtomicOr(handle, body, value, {});
return ir.ImageAtomicOr(handle, body, value, info);
case AtomicOp::Xor:
return ir.ImageAtomicXor(handle, body, value, {});
return ir.ImageAtomicXor(handle, body, value, info);
case AtomicOp::Inc:
return ir.ImageAtomicInc(handle, body, value, {});
return ir.ImageAtomicInc(handle, body, value, info);
case AtomicOp::Dec:
return ir.ImageAtomicDec(handle, body, value, {});
return ir.ImageAtomicDec(handle, body, value, info);
default:
UNREACHABLE();
}
@ -643,11 +653,14 @@ void Translator::IMAGE_GET_LOD(const GcnInst& inst) {
IR::VectorReg addr_reg{inst.src[0].code};
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4};
IR::TextureInstInfo info{};
info.is_array.Assign(mimg.da);
const IR::Value handle = ir.GetScalarReg(tsharp_reg);
const IR::Value body = ir.CompositeConstruct(
ir.GetVectorReg<IR::F32>(addr_reg), ir.GetVectorReg<IR::F32>(addr_reg + 1),
ir.GetVectorReg<IR::F32>(addr_reg + 2), ir.GetVectorReg<IR::F32>(addr_reg + 3));
const IR::Value lod = ir.ImageQueryLod(handle, body, {});
const IR::Value lod = ir.ImageQueryLod(handle, body, info);
ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 0)});
ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 1)});
}

View File

@ -70,14 +70,8 @@ struct ImageResource {
bool is_depth{};
bool is_atomic{};
bool is_array{};
bool is_read{};
bool is_written{};
[[nodiscard]] bool IsStorage(const AmdGpu::Image& image) const noexcept {
// Need cube as storage when used with ImageRead.
return is_written || (is_read && image.GetBoundType() == AmdGpu::ImageType::Cube);
}
[[nodiscard]] constexpr AmdGpu::Image GetSharp(const Info& info) const noexcept;
};
using ImageResourceList = boost::container::small_vector<ImageResource, 16>;

View File

@ -1732,11 +1732,6 @@ Value IREmitter::ImageGatherDref(const Value& handle, const Value& coords, const
return Inst(Opcode::ImageGatherDref, Flags{info}, handle, coords, offset, dref);
}
Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod,
const IR::U1& skip_mips) {
return Inst(Opcode::ImageQueryDimensions, handle, lod, skip_mips);
}
Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod,
const IR::U1& skip_mips, TextureInstInfo info) {
return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod, skip_mips);
@ -1763,6 +1758,10 @@ void IREmitter::ImageWrite(const Value& handle, const Value& coords, const U32&
Inst(Opcode::ImageWrite, Flags{info}, handle, coords, lod, multisampling, color);
}
[[nodiscard]] F32 IREmitter::CubeFaceIndex(const Value& cube_coords) {
return Inst<F32>(Opcode::CubeFaceIndex, cube_coords);
}
// Debug print maps to SPIRV's NonSemantic DebugPrintf instruction
// Renderdoc will hook in its own implementation of the SPIRV instruction
// Renderdoc accepts format specifiers, e.g. %u, listed here:

View File

@ -324,8 +324,6 @@ public:
const F32& dref, const F32& lod,
const Value& offset, TextureInstInfo info);
[[nodiscard]] Value ImageQueryDimension(const Value& handle, const U32& lod,
const U1& skip_mips);
[[nodiscard]] Value ImageQueryDimension(const Value& handle, const U32& lod,
const U1& skip_mips, TextureInstInfo info);
@ -344,6 +342,8 @@ public:
void ImageWrite(const Value& handle, const Value& coords, const U32& lod,
const U32& multisampling, const Value& color, TextureInstInfo info);
[[nodiscard]] F32 CubeFaceIndex(const Value& cube_coords);
void EmitVertex();
void EmitPrimitive();

View File

@ -374,6 +374,9 @@ OPCODE(ImageAtomicOr32, U32, Opaq
OPCODE(ImageAtomicXor32, U32, Opaque, Opaque, U32, )
OPCODE(ImageAtomicExchange32, U32, Opaque, Opaque, U32, )
// Cube operations - optional, usable if profile.supports_native_cube_calc
OPCODE(CubeFaceIndex, F32, F32x3, )
// Warp operations
OPCODE(LaneId, U32, )
OPCODE(WarpId, U32, )

View File

@ -161,10 +161,9 @@ public:
u32 Add(const ImageResource& desc) {
const u32 index{Add(image_resources, desc, [&desc](const auto& existing) {
return desc.sharp_idx == existing.sharp_idx;
return desc.sharp_idx == existing.sharp_idx && desc.is_array == existing.is_array;
})};
auto& image = image_resources[index];
image.is_read |= desc.is_read;
image.is_written |= desc.is_written;
return index;
}
@ -361,7 +360,6 @@ void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors&
image = AmdGpu::Image::Null();
}
ASSERT(image.GetType() != AmdGpu::ImageType::Invalid);
const bool is_read = inst.GetOpcode() == IR::Opcode::ImageRead;
const bool is_written = inst.GetOpcode() == IR::Opcode::ImageWrite;
// Patch image instruction if image is FMask.
@ -402,7 +400,6 @@ void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors&
.is_depth = bool(inst_info.is_depth),
.is_atomic = IsImageAtomicInstruction(inst),
.is_array = bool(inst_info.is_array),
.is_read = is_read,
.is_written = is_written,
});
@ -560,40 +557,15 @@ void PatchTextureBufferArgs(IR::Block& block, IR::Inst& inst, Info& info) {
}
}
IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value& t,
const IR::Value& z, bool is_written, bool is_array) {
// When cubemap is written with imageStore it is treated like 2DArray.
if (is_written) {
return ir.CompositeConstruct(s, t, z);
}
ASSERT(s.Type() == IR::Type::F32); // in case of fetched image need to adjust the code below
// We need to fix x and y coordinate,
// because the s and t coordinate will be scaled and plus 1.5 by v_madak_f32.
// We already force the scale value to be 1.0 when handling v_cubema_f32,
// here we subtract 1.5 to recover the original value.
const IR::Value x = ir.FPSub(IR::F32{s}, ir.Imm32(1.5f));
const IR::Value y = ir.FPSub(IR::F32{t}, ir.Imm32(1.5f));
if (is_array) {
const IR::U32 array_index = ir.ConvertFToU(32, IR::F32{z});
const IR::U32 face_id = ir.BitwiseAnd(array_index, ir.Imm32(7u));
const IR::U32 slice_id = ir.ShiftRightLogical(array_index, ir.Imm32(3u));
return ir.CompositeConstruct(x, y, ir.ConvertIToF(32, 32, false, face_id),
ir.ConvertIToF(32, 32, false, slice_id));
} else {
return ir.CompositeConstruct(x, y, z);
}
}
void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info,
const AmdGpu::Image& image) {
const ImageResource& image_res, const AmdGpu::Image& image) {
const auto handle = inst.Arg(0);
const auto sampler_res = info.samplers[(handle.U32() >> 16) & 0xFFFF];
auto sampler = sampler_res.GetSharp(info);
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
const auto inst_info = inst.Flags<IR::TextureInstInfo>();
const auto view_type = image.GetViewType(image_res.is_array);
IR::Inst* body1 = inst.Arg(1).InstRecursive();
IR::Inst* body2 = inst.Arg(2).InstRecursive();
@ -640,7 +612,7 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info,
return ir.BitFieldExtract(IR::U32{arg}, ir.Imm32(off), ir.Imm32(6), true);
};
switch (image.GetType()) {
switch (view_type) {
case AmdGpu::ImageType::Color1D:
case AmdGpu::ImageType::Color1DArray:
return read(0);
@ -649,7 +621,6 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info,
case AmdGpu::ImageType::Color2DMsaa:
return ir.CompositeConstruct(read(0), read(8));
case AmdGpu::ImageType::Color3D:
case AmdGpu::ImageType::Cube:
return ir.CompositeConstruct(read(0), read(8), read(16));
default:
UNREACHABLE();
@ -661,7 +632,7 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info,
if (!inst_info.has_derivatives) {
return {};
}
switch (image.GetType()) {
switch (view_type) {
case AmdGpu::ImageType::Color1D:
case AmdGpu::ImageType::Color1DArray:
// du/dx, du/dy
@ -675,7 +646,6 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info,
return {ir.CompositeConstruct(get_addr_reg(addr_reg - 4), get_addr_reg(addr_reg - 3)),
ir.CompositeConstruct(get_addr_reg(addr_reg - 2), get_addr_reg(addr_reg - 1))};
case AmdGpu::ImageType::Color3D:
case AmdGpu::ImageType::Cube:
// (du/dx, dv/dx, dw/dx), (du/dy, dv/dy, dw/dy)
addr_reg = addr_reg + 6;
return {ir.CompositeConstruct(get_addr_reg(addr_reg - 6), get_addr_reg(addr_reg - 5),
@ -691,7 +661,8 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info,
// Query dimensions of image if needed for normalization.
// We can't use the image sharp because it could be bound to a different image later.
const auto dimensions =
unnormalized ? ir.ImageQueryDimension(handle, ir.Imm32(0u), ir.Imm1(false)) : IR::Value{};
unnormalized ? ir.ImageQueryDimension(handle, ir.Imm32(0u), ir.Imm1(false), inst_info)
: IR::Value{};
const auto get_coord = [&](u32 coord_idx, u32 dim_idx) -> IR::Value {
const auto coord = get_addr_reg(coord_idx);
if (unnormalized) {
@ -705,7 +676,7 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info,
// Now we can load body components as noted in Table 8.9 Image Opcodes with Sampler
const IR::Value coords = [&] -> IR::Value {
switch (image.GetType()) {
switch (view_type) {
case AmdGpu::ImageType::Color1D: // x
addr_reg = addr_reg + 1;
return get_coord(addr_reg - 1, 0);
@ -724,10 +695,6 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info,
addr_reg = addr_reg + 3;
return ir.CompositeConstruct(get_coord(addr_reg - 3, 0), get_coord(addr_reg - 2, 1),
get_coord(addr_reg - 1, 2));
case AmdGpu::ImageType::Cube: // x, y, face
addr_reg = addr_reg + 3;
return PatchCubeCoord(ir, get_coord(addr_reg - 3, 0), get_coord(addr_reg - 2, 1),
get_addr_reg(addr_reg - 1), false, inst_info.is_array);
default:
UNREACHABLE();
}
@ -779,17 +746,18 @@ void PatchImageArgs(IR::Block& block, IR::Inst& inst, Info& info) {
// Sample instructions must be handled separately using address register data.
if (inst.GetOpcode() == IR::Opcode::ImageSampleRaw) {
PatchImageSampleArgs(block, inst, info, image);
PatchImageSampleArgs(block, inst, info, image_res, image);
return;
}
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
const auto inst_info = inst.Flags<IR::TextureInstInfo>();
const auto view_type = image.GetViewType(image_res.is_array);
// Now that we know the image type, adjust texture coordinate vector.
IR::Inst* body = inst.Arg(1).InstRecursive();
const auto [coords, arg] = [&] -> std::pair<IR::Value, IR::Value> {
switch (image.GetType()) {
switch (view_type) {
case AmdGpu::ImageType::Color1D: // x, [lod]
return {body->Arg(0), body->Arg(1)};
case AmdGpu::ImageType::Color1DArray: // x, slice, [lod]
@ -805,22 +773,18 @@ void PatchImageArgs(IR::Block& block, IR::Inst& inst, Info& info) {
[[fallthrough]];
case AmdGpu::ImageType::Color3D: // x, y, z, [lod]
return {ir.CompositeConstruct(body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)};
case AmdGpu::ImageType::Cube: // x, y, face, [lod]
return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2),
inst.GetOpcode() == IR::Opcode::ImageWrite, inst_info.is_array),
body->Arg(3)};
default:
UNREACHABLE_MSG("Unknown image type {}", image.GetType());
UNREACHABLE_MSG("Unknown image type {}", view_type);
}
}();
const auto has_ms = image.GetType() == AmdGpu::ImageType::Color2DMsaa ||
image.GetType() == AmdGpu::ImageType::Color2DMsaaArray;
const auto has_ms = view_type == AmdGpu::ImageType::Color2DMsaa ||
view_type == AmdGpu::ImageType::Color2DMsaaArray;
ASSERT(!inst_info.has_lod || !has_ms);
const auto lod = inst_info.has_lod ? IR::U32{arg} : IR::U32{};
const auto ms = has_ms ? IR::U32{arg} : IR::U32{};
const auto is_storage = image_res.IsStorage(image);
const auto is_storage = image_res.is_written;
if (inst.GetOpcode() == IR::Opcode::ImageRead) {
auto texel = ir.ImageRead(handle, coords, lod, ms, inst_info);
if (is_storage) {

View File

@ -5,7 +5,7 @@
namespace Shader::Optimization {
void Visit(Info& info, IR::Inst& inst) {
void Visit(Info& info, const IR::Inst& inst) {
switch (inst.GetOpcode()) {
case IR::Opcode::GetAttribute:
case IR::Opcode::GetAttributeU32:

View File

@ -24,6 +24,7 @@ struct Profile {
bool support_explicit_workgroup_layout{};
bool support_legacy_vertex_attributes{};
bool supports_image_load_store_lod{};
bool supports_native_cube_calc{};
bool has_broken_spirv_clamp{};
bool lower_left_origin_mode{};
bool needs_manual_interpolation{};

View File

@ -113,9 +113,9 @@ struct StageSpecialization {
});
ForEachSharp(binding, images, info->images,
[](auto& spec, const auto& desc, AmdGpu::Image sharp) {
spec.type = sharp.GetBoundType();
spec.type = sharp.GetViewType(desc.is_array);
spec.is_integer = AmdGpu::IsInteger(sharp.GetNumberFmt());
spec.is_storage = desc.IsStorage(sharp);
spec.is_storage = desc.is_written;
if (spec.is_storage) {
spec.dst_select = sharp.DstSelect();
}

View File

@ -899,7 +899,8 @@ struct Liverpool {
// There is a small difference between T# and CB number types, account for it.
return RemapNumberFormat(info.number_type == NumberFormat::SnormNz
? NumberFormat::Srgb
: info.number_type.Value());
: info.number_type.Value(),
info.format);
}
[[nodiscard]] NumberConversion GetNumberConversion() const {

View File

@ -54,7 +54,7 @@ struct Buffer {
}
NumberFormat GetNumberFmt() const noexcept {
return RemapNumberFormat(NumberFormat(num_format));
return RemapNumberFormat(NumberFormat(num_format), DataFormat(data_format));
}
DataFormat GetDataFmt() const noexcept {
@ -119,6 +119,7 @@ constexpr std::string_view NameOf(ImageType type) {
enum class TilingMode : u32 {
Depth_MacroTiled = 0u,
Display_Linear = 0x8u,
Display_MicroTiled = 0x9u,
Display_MacroTiled = 0xAu,
Texture_MicroTiled = 0xDu,
Texture_MacroTiled = 0xEu,
@ -131,6 +132,8 @@ constexpr std::string_view NameOf(TilingMode type) {
return "Depth_MacroTiled";
case TilingMode::Display_Linear:
return "Display_Linear";
case TilingMode::Display_MicroTiled:
return "Display_MicroTiled";
case TilingMode::Display_MacroTiled:
return "Display_MacroTiled";
case TilingMode::Texture_MicroTiled:
@ -226,15 +229,15 @@ struct Image {
return pitch + 1;
}
u32 NumLayers(bool is_array) const {
u32 slices = GetType() == ImageType::Color3D ? 1 : depth + 1;
if (GetType() == ImageType::Cube) {
if (is_array) {
slices = last_array + 1;
ASSERT(slices % 6 == 0);
} else {
slices = 6;
}
[[nodiscard]] u32 NumLayers() const noexcept {
// Depth is the number of layers for Array images.
u32 slices = depth + 1;
if (GetType() == ImageType::Color3D) {
// Depth is the actual texture depth for 3D images.
slices = 1;
} else if (IsCube()) {
// Depth is the number of full cubes for Cube images.
slices *= 6;
}
if (pow2pad) {
slices = std::bit_ceil(slices);
@ -256,8 +259,12 @@ struct Image {
return 1;
}
bool IsCube() const noexcept {
return static_cast<ImageType>(type) == ImageType::Cube;
}
ImageType GetType() const noexcept {
return static_cast<ImageType>(type);
return IsCube() ? ImageType::Color2DArray : static_cast<ImageType>(type);
}
DataFormat GetDataFmt() const noexcept {
@ -265,7 +272,7 @@ struct Image {
}
NumberFormat GetNumberFmt() const noexcept {
return RemapNumberFormat(NumberFormat(num_format));
return RemapNumberFormat(NumberFormat(num_format), DataFormat(data_format));
}
NumberConversion GetNumberConversion() const noexcept {
@ -289,13 +296,48 @@ struct Image {
GetDataFmt() <= DataFormat::FormatFmask64_8;
}
bool IsPartialCubemap() const {
const auto viewed_slice = last_array - base_array + 1;
return GetType() == ImageType::Cube && viewed_slice < 6;
[[nodiscard]] ImageType GetViewType(const bool is_array) const noexcept {
const auto base_type = GetType();
if (IsCube()) {
// Cube needs to remain array type regardless of instruction array specifier.
return base_type;
}
if (base_type == ImageType::Color1DArray && !is_array) {
return ImageType::Color1D;
}
if (base_type == ImageType::Color2DArray && !is_array) {
return ImageType::Color2D;
}
if (base_type == ImageType::Color2DMsaaArray && !is_array) {
return ImageType::Color2DMsaa;
}
return base_type;
}
ImageType GetBoundType() const noexcept {
return IsPartialCubemap() ? ImageType::Color2DArray : GetType();
[[nodiscard]] u32 NumViewLevels(const bool is_array) const noexcept {
switch (GetViewType(is_array)) {
case ImageType::Color2DMsaa:
case ImageType::Color2DMsaaArray:
return 1;
default:
// Constrain to actual number of available levels.
const auto max_level = std::min<u32>(last_level + 1, NumLevels());
return max_level > base_level ? max_level - base_level : 1;
}
}
[[nodiscard]] u32 NumViewLayers(const bool is_array) const noexcept {
switch (GetViewType(is_array)) {
case ImageType::Color1D:
case ImageType::Color2D:
case ImageType::Color2DMsaa:
case ImageType::Color3D:
return 1;
default:
// Constrain to actual number of available layers.
const auto max_array = std::min<u32>(last_array + 1, NumLayers());
return max_array > base_array ? max_array - base_array : 1;
}
}
};
static_assert(sizeof(Image) == 32); // 256bits

View File

@ -252,7 +252,7 @@ inline DataFormat RemapDataFormat(const DataFormat format) {
}
}
inline NumberFormat RemapNumberFormat(const NumberFormat format) {
inline NumberFormat RemapNumberFormat(const NumberFormat format, const DataFormat data_format) {
switch (format) {
case NumberFormat::Uscaled:
return NumberFormat::Uint;
@ -260,6 +260,14 @@ inline NumberFormat RemapNumberFormat(const NumberFormat format) {
return NumberFormat::Sint;
case NumberFormat::Ubnorm:
return NumberFormat::Unorm;
case NumberFormat::Float:
if (data_format == DataFormat::Format8) {
// Games may ask for 8-bit float when they want to access the stencil component
// of a depth-stencil image. Change to unsigned int to match the stencil format.
// This is also the closest approximation to pass the bits through unconverted.
return NumberFormat::Uint;
}
[[fallthrough]];
default:
return format;
}

View File

@ -10,13 +10,13 @@
#include "video_core/amdgpu/liverpool.h"
#include "video_core/buffer_cache/buffer_cache.h"
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
#include "video_core/renderer_vulkan/vk_graphics_pipeline.h"
#include "video_core/renderer_vulkan/vk_instance.h"
#include "video_core/renderer_vulkan/vk_scheduler.h"
#include "video_core/texture_cache/texture_cache.h"
namespace VideoCore {
static constexpr size_t NumVertexBuffers = 32;
static constexpr size_t GdsBufferSize = 64_KB;
static constexpr size_t StagingBufferSize = 1_GB;
static constexpr size_t UboStreamBufferSize = 64_MB;
@ -89,35 +89,22 @@ void BufferCache::DownloadBufferMemory(Buffer& buffer, VAddr device_addr, u64 si
}
}
bool BufferCache::BindVertexBuffers(
const Shader::Info& vs_info, const std::optional<Shader::Gcn::FetchShaderData>& fetch_shader) {
boost::container::small_vector<vk::VertexInputAttributeDescription2EXT, 16> attributes;
boost::container::small_vector<vk::VertexInputBindingDescription2EXT, 16> bindings;
SCOPE_EXIT {
if (instance.IsVertexInputDynamicState()) {
const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.setVertexInputEXT(bindings, attributes);
} else if (bindings.empty()) {
// Required to call bindVertexBuffers2EXT at least once in the current command buffer
// with non-null strides without a non-dynamic stride pipeline in between. Thus even
// when nothing is bound we still need to make a dummy call. Non-null strides in turn
// requires a count greater than 0.
const auto cmdbuf = scheduler.CommandBuffer();
const std::array null_buffers = {GetBuffer(NULL_BUFFER_ID).buffer.buffer};
constexpr std::array null_offsets = {static_cast<vk::DeviceSize>(0)};
cmdbuf.bindVertexBuffers2EXT(0, null_buffers, null_offsets, null_offsets, null_offsets);
}
};
void BufferCache::BindVertexBuffers(const Vulkan::GraphicsPipeline& pipeline) {
Vulkan::VertexInputs<vk::VertexInputAttributeDescription2EXT> attributes;
Vulkan::VertexInputs<vk::VertexInputBindingDescription2EXT> bindings;
Vulkan::VertexInputs<AmdGpu::Buffer> guest_buffers;
pipeline.GetVertexInputs(attributes, bindings, guest_buffers);
if (!fetch_shader || fetch_shader->attributes.empty()) {
return false;
if (instance.IsVertexInputDynamicState()) {
// Update current vertex inputs.
const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.setVertexInputEXT(bindings, attributes);
}
std::array<vk::Buffer, NumVertexBuffers> host_buffers;
std::array<vk::DeviceSize, NumVertexBuffers> host_offsets;
std::array<vk::DeviceSize, NumVertexBuffers> host_sizes;
std::array<vk::DeviceSize, NumVertexBuffers> host_strides;
boost::container::static_vector<AmdGpu::Buffer, NumVertexBuffers> guest_buffers;
if (bindings.empty()) {
// If there are no bindings, there is nothing further to do.
return;
}
struct BufferRange {
VAddr base_address;
@ -125,61 +112,37 @@ bool BufferCache::BindVertexBuffers(
vk::Buffer vk_buffer;
u64 offset;
size_t GetSize() const {
[[nodiscard]] size_t GetSize() const {
return end_address - base_address;
}
};
// Calculate buffers memory overlaps
bool has_step_rate = false;
boost::container::static_vector<BufferRange, NumVertexBuffers> ranges{};
for (const auto& attrib : fetch_shader->attributes) {
if (attrib.UsesStepRates()) {
has_step_rate = true;
continue;
// Build list of ranges covering the requested buffers
Vulkan::VertexInputs<BufferRange> ranges{};
for (const auto& buffer : guest_buffers) {
if (buffer.GetSize() > 0) {
ranges.emplace_back(buffer.base_address, buffer.base_address + buffer.GetSize());
}
}
const auto& buffer = attrib.GetSharp(vs_info);
if (buffer.GetSize() == 0) {
continue;
}
guest_buffers.emplace_back(buffer);
ranges.emplace_back(buffer.base_address, buffer.base_address + buffer.GetSize());
attributes.push_back({
.location = attrib.semantic,
.binding = attrib.semantic,
.format =
Vulkan::LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()),
.offset = 0,
// Merge connecting ranges together
Vulkan::VertexInputs<BufferRange> ranges_merged{};
if (!ranges.empty()) {
std::ranges::sort(ranges, [](const BufferRange& lhv, const BufferRange& rhv) {
return lhv.base_address < rhv.base_address;
});
bindings.push_back({
.binding = attrib.semantic,
.stride = buffer.GetStride(),
.inputRate = attrib.GetStepRate() == Shader::Gcn::VertexAttribute::InstanceIdType::None
? vk::VertexInputRate::eVertex
: vk::VertexInputRate::eInstance,
.divisor = 1,
});
}
if (ranges.empty()) {
return false;
}
std::ranges::sort(ranges, [](const BufferRange& lhv, const BufferRange& rhv) {
return lhv.base_address < rhv.base_address;
});
boost::container::static_vector<BufferRange, NumVertexBuffers> ranges_merged{ranges[0]};
for (auto range : ranges) {
auto& prev_range = ranges_merged.back();
if (prev_range.end_address < range.base_address) {
ranges_merged.emplace_back(range);
} else {
prev_range.end_address = std::max(prev_range.end_address, range.end_address);
ranges_merged.emplace_back(ranges[0]);
for (auto range : ranges) {
auto& prev_range = ranges_merged.back();
if (prev_range.end_address < range.base_address) {
ranges_merged.emplace_back(range);
} else {
prev_range.end_address = std::max(prev_range.end_address, range.end_address);
}
}
}
// Map buffers
// Map buffers for merged ranges
for (auto& range : ranges_merged) {
const auto [buffer, offset] = ObtainBuffer(range.base_address, range.GetSize(), false);
range.vk_buffer = buffer->buffer;
@ -187,32 +150,39 @@ bool BufferCache::BindVertexBuffers(
}
// Bind vertex buffers
const size_t num_buffers = guest_buffers.size();
for (u32 i = 0; i < num_buffers; ++i) {
const auto& buffer = guest_buffers[i];
const auto host_buffer = std::ranges::find_if(ranges_merged, [&](const BufferRange& range) {
return (buffer.base_address >= range.base_address &&
buffer.base_address < range.end_address);
});
ASSERT(host_buffer != ranges_merged.cend());
host_buffers[i] = host_buffer->vk_buffer;
host_offsets[i] = host_buffer->offset + buffer.base_address - host_buffer->base_address;
host_sizes[i] = buffer.GetSize();
host_strides[i] = buffer.GetStride();
}
if (num_buffers > 0) {
const auto cmdbuf = scheduler.CommandBuffer();
if (instance.IsVertexInputDynamicState()) {
cmdbuf.bindVertexBuffers(0, num_buffers, host_buffers.data(), host_offsets.data());
Vulkan::VertexInputs<vk::Buffer> host_buffers;
Vulkan::VertexInputs<vk::DeviceSize> host_offsets;
Vulkan::VertexInputs<vk::DeviceSize> host_sizes;
Vulkan::VertexInputs<vk::DeviceSize> host_strides;
const auto null_buffer =
instance.IsNullDescriptorSupported() ? VK_NULL_HANDLE : GetBuffer(NULL_BUFFER_ID).Handle();
for (const auto& buffer : guest_buffers) {
if (buffer.GetSize() > 0) {
const auto host_buffer_info =
std::ranges::find_if(ranges_merged, [&](const BufferRange& range) {
return buffer.base_address >= range.base_address &&
buffer.base_address < range.end_address;
});
ASSERT(host_buffer_info != ranges_merged.cend());
host_buffers.emplace_back(host_buffer_info->vk_buffer);
host_offsets.push_back(host_buffer_info->offset + buffer.base_address -
host_buffer_info->base_address);
} else {
cmdbuf.bindVertexBuffers2EXT(0, num_buffers, host_buffers.data(), host_offsets.data(),
host_sizes.data(), host_strides.data());
host_buffers.emplace_back(null_buffer);
host_offsets.push_back(0);
}
host_sizes.push_back(buffer.GetSize());
host_strides.push_back(buffer.GetStride());
}
return has_step_rate;
const auto cmdbuf = scheduler.CommandBuffer();
const auto num_buffers = guest_buffers.size();
if (instance.IsVertexInputDynamicState()) {
cmdbuf.bindVertexBuffers(0, num_buffers, host_buffers.data(), host_offsets.data());
} else {
cmdbuf.bindVertexBuffers2EXT(0, num_buffers, host_buffers.data(), host_offsets.data(),
host_sizes.data(), host_strides.data());
}
}
void BufferCache::BindIndexBuffer(u32 index_offset) {

View File

@ -5,8 +5,6 @@
#include <shared_mutex>
#include <boost/container/small_vector.hpp>
#include <boost/icl/interval_map.hpp>
#include <tsl/robin_map.h>
#include "common/div_ceil.h"
#include "common/slot_vector.h"
#include "common/types.h"
@ -26,6 +24,10 @@ struct FetchShaderData;
struct Info;
} // namespace Shader
namespace Vulkan {
class GraphicsPipeline;
}
namespace VideoCore {
using BufferId = Common::SlotId;
@ -75,8 +77,7 @@ public:
void InvalidateMemory(VAddr device_addr, u64 size);
/// Binds host vertex buffers for the current draw.
bool BindVertexBuffers(const Shader::Info& vs_info,
const std::optional<Shader::Gcn::FetchShaderData>& fetch_shader);
void BindVertexBuffers(const Vulkan::GraphicsPipeline& pipeline);
/// Bind host index buffer for the current draw.
void BindIndexBuffer(u32 index_offset);

View File

@ -2,6 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
set(SHADER_FILES
detilers/display_micro_64bpp.comp
detilers/macro_32bpp.comp
detilers/macro_64bpp.comp
detilers/macro_8bpp.comp

View File

@ -0,0 +1,60 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#version 450
layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in;
layout(std430, binding = 0) buffer input_buf {
uint in_data[];
};
layout(std430, binding = 1) buffer output_buf {
uint out_data[];
};
layout(push_constant) uniform image_info {
uint num_levels;
uint pitch;
uint height;
uint c0;
uint c1;
} info;
const uint lut_64bpp[16] = {
0x05040100, 0x0d0c0908,
0x07060302, 0x0f0e0b0a,
0x15141110, 0x1d1c1918,
0x17161312, 0x1f1e1b1a,
0x25242120, 0x2d2c2928,
0x27262322, 0x2f2e2b2a,
0x35343130, 0x3d3c3938,
0x37363332, 0x3f3e3b3a,
};
#define MICRO_TILE_DIM (8)
#define MICRO_TILE_SZ (512)
#define TEXELS_PER_ELEMENT (1)
#define BPP (64)
void main() {
uint x = gl_GlobalInvocationID.x % info.pitch;
uint y = (gl_GlobalInvocationID.x / info.pitch) % info.height;
uint z = gl_GlobalInvocationID.x / (info.pitch * info.height);
uint col = bitfieldExtract(x, 0, 3);
uint row = bitfieldExtract(y, 0, 3);
uint idx_dw = lut_64bpp[(col + row * MICRO_TILE_DIM) >> 2u];
uint byte_ofs = gl_LocalInvocationID.x & 3u;
uint idx = bitfieldExtract(idx_dw >> (8 * byte_ofs), 0, 8);
uint slice_offs = z * info.c1 * MICRO_TILE_SZ;
uint tile_row = y / MICRO_TILE_DIM;
uint tile_column = x / MICRO_TILE_DIM;
uint tile_offs = ((tile_row * info.c0) + tile_column) * MICRO_TILE_SZ;
uint offs = slice_offs + tile_offs + ((idx * BPP) / 8u);
uint p0 = in_data[(offs >> 2) + 0];
uint p1 = in_data[(offs >> 2) + 1];
out_data[2 * gl_GlobalInvocationID.x + 0] = p0;
out_data[2 * gl_GlobalInvocationID.x + 1] = p1;
}

View File

@ -59,9 +59,8 @@ ComputePipeline::ComputePipeline(const Instance& instance_, Scheduler& scheduler
for (const auto& image : info->images) {
bindings.push_back({
.binding = binding++,
.descriptorType = image.IsStorage(image.GetSharp(*info))
? vk::DescriptorType::eStorageImage
: vk::DescriptorType::eSampledImage,
.descriptorType = image.is_written ? vk::DescriptorType::eStorageImage
: vk::DescriptorType::eSampledImage,
.descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute,
});

View File

@ -57,35 +57,11 @@ GraphicsPipeline::GraphicsPipeline(
pipeline_layout = std::move(layout);
SetObjectName(device, *pipeline_layout, "Graphics PipelineLayout {}", debug_str);
boost::container::static_vector<vk::VertexInputBindingDescription, 32> vertex_bindings;
boost::container::static_vector<vk::VertexInputAttributeDescription, 32> vertex_attributes;
if (fetch_shader && !instance.IsVertexInputDynamicState()) {
const auto& vs_info = GetStage(Shader::LogicalStage::Vertex);
for (const auto& attrib : fetch_shader->attributes) {
if (attrib.UsesStepRates()) {
// Skip attribute binding as the data will be pulled by shader
continue;
}
const auto buffer = attrib.GetSharp(vs_info);
if (buffer.GetSize() == 0) {
continue;
}
vertex_attributes.push_back({
.location = attrib.semantic,
.binding = attrib.semantic,
.format = LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()),
.offset = 0,
});
vertex_bindings.push_back({
.binding = attrib.semantic,
.stride = buffer.GetStride(),
.inputRate =
attrib.GetStepRate() == Shader::Gcn::VertexAttribute::InstanceIdType::None
? vk::VertexInputRate::eVertex
: vk::VertexInputRate::eInstance,
});
}
VertexInputs<vk::VertexInputAttributeDescription> vertex_attributes;
VertexInputs<vk::VertexInputBindingDescription> vertex_bindings;
VertexInputs<AmdGpu::Buffer> guest_buffers;
if (!instance.IsVertexInputDynamicState()) {
GetVertexInputs(vertex_attributes, vertex_bindings, guest_buffers);
}
const vk::PipelineVertexInputStateCreateInfo vertex_input_info = {
@ -161,7 +137,7 @@ GraphicsPipeline::GraphicsPipeline(
}
if (instance.IsVertexInputDynamicState()) {
dynamic_states.push_back(vk::DynamicState::eVertexInputEXT);
} else {
} else if (!vertex_bindings.empty()) {
dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStrideEXT);
}
@ -329,6 +305,51 @@ GraphicsPipeline::GraphicsPipeline(
GraphicsPipeline::~GraphicsPipeline() = default;
template <typename Attribute, typename Binding>
void GraphicsPipeline::GetVertexInputs(VertexInputs<Attribute>& attributes,
VertexInputs<Binding>& bindings,
VertexInputs<AmdGpu::Buffer>& guest_buffers) const {
if (!fetch_shader || fetch_shader->attributes.empty()) {
return;
}
const auto& vs_info = GetStage(Shader::LogicalStage::Vertex);
for (const auto& attrib : fetch_shader->attributes) {
if (attrib.UsesStepRates()) {
// Skip attribute binding as the data will be pulled by shader.
continue;
}
const auto& buffer = attrib.GetSharp(vs_info);
attributes.push_back(Attribute{
.location = attrib.semantic,
.binding = attrib.semantic,
.format = LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()),
.offset = 0,
});
bindings.push_back(Binding{
.binding = attrib.semantic,
.stride = buffer.GetStride(),
.inputRate = attrib.GetStepRate() == Shader::Gcn::VertexAttribute::InstanceIdType::None
? vk::VertexInputRate::eVertex
: vk::VertexInputRate::eInstance,
});
if constexpr (std::is_same_v<Binding, vk::VertexInputBindingDescription2EXT>) {
bindings.back().divisor = 1;
}
guest_buffers.emplace_back(buffer);
}
}
// Declare templated GetVertexInputs for necessary types.
template void GraphicsPipeline::GetVertexInputs(
VertexInputs<vk::VertexInputAttributeDescription>& attributes,
VertexInputs<vk::VertexInputBindingDescription>& bindings,
VertexInputs<AmdGpu::Buffer>& guest_buffers) const;
template void GraphicsPipeline::GetVertexInputs(
VertexInputs<vk::VertexInputAttributeDescription2EXT>& attributes,
VertexInputs<vk::VertexInputBindingDescription2EXT>& bindings,
VertexInputs<AmdGpu::Buffer>& guest_buffers) const;
void GraphicsPipeline::BuildDescSetLayout() {
boost::container::small_vector<vk::DescriptorSetLayoutBinding, 32> bindings;
u32 binding{};
@ -367,9 +388,8 @@ void GraphicsPipeline::BuildDescSetLayout() {
for (const auto& image : stage->images) {
bindings.push_back({
.binding = binding++,
.descriptorType = image.IsStorage(image.GetSharp(*stage))
? vk::DescriptorType::eStorageImage
: vk::DescriptorType::eSampledImage,
.descriptorType = image.is_written ? vk::DescriptorType::eStorageImage
: vk::DescriptorType::eSampledImage,
.descriptorCount = 1,
.stageFlags = gp_stage_flags,
});

View File

@ -3,6 +3,7 @@
#pragma once
#include <boost/container/static_vector.hpp>
#include <xxhash.h>
#include "common/types.h"
@ -27,6 +28,9 @@ class DescriptorHeap;
using Liverpool = AmdGpu::Liverpool;
template <typename T>
using VertexInputs = boost::container::static_vector<T, MaxVertexBufferCount>;
struct GraphicsPipelineKey {
std::array<size_t, MaxShaderStages> stage_hashes;
u32 num_color_attachments;
@ -100,6 +104,11 @@ public:
key.prim_type == AmdGpu::PrimitiveType::QuadList;
}
/// Gets the attributes and bindings for vertex inputs.
template <typename Attribute, typename Binding>
void GetVertexInputs(VertexInputs<Attribute>& attributes, VertexInputs<Binding>& bindings,
VertexInputs<AmdGpu::Buffer>& guest_buffers) const;
private:
void BuildDescSetLayout();

View File

@ -271,6 +271,7 @@ bool Instance::CreateDevice() {
maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
legacy_vertex_attributes = add_extension(VK_EXT_LEGACY_VERTEX_ATTRIBUTES_EXTENSION_NAME);
image_load_store_lod = add_extension(VK_AMD_SHADER_IMAGE_LOAD_STORE_LOD_EXTENSION_NAME);
amd_gcn_shader = add_extension(VK_AMD_GCN_SHADER_EXTENSION_NAME);
// These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2
// with extensions.

View File

@ -159,6 +159,11 @@ public:
return image_load_store_lod;
}
/// Returns true when VK_AMD_gcn_shader is supported.
bool IsAmdGcnShaderSupported() const {
return amd_gcn_shader;
}
/// Returns true when geometry shaders are supported by the device
bool IsGeometryStageSupported() const {
return features.geometryShader;
@ -334,6 +339,7 @@ private:
bool list_restart{};
bool legacy_vertex_attributes{};
bool image_load_store_lod{};
bool amd_gcn_shader{};
u64 min_imported_host_pointer_alignment{};
u32 subgroup_size{};
bool tooling_info{};

View File

@ -204,6 +204,7 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
.support_explicit_workgroup_layout = true,
.support_legacy_vertex_attributes = instance_.IsLegacyVertexAttributesSupported(),
.supports_image_load_store_lod = instance_.IsImageLoadStoreLodSupported(),
.supports_native_cube_calc = instance_.IsAmdGcnShaderSupported(),
.needs_manual_interpolation = instance.IsFragmentShaderBarycentricSupported() &&
instance.GetDriverID() == vk::DriverId::eNvidiaProprietary,
.needs_lds_barriers = instance.GetDriverID() == vk::DriverId::eNvidiaProprietary ||
@ -419,17 +420,17 @@ bool PipelineCache::RefreshGraphicsKey() {
}
}
const auto vs_info = infos[static_cast<u32>(Shader::LogicalStage::Vertex)];
const auto* vs_info = infos[static_cast<u32>(Shader::LogicalStage::Vertex)];
if (vs_info && fetch_shader && !instance.IsVertexInputDynamicState()) {
// Without vertex input dynamic state, the pipeline needs to specialize on format.
// Stride will still be handled outside the pipeline using dynamic state.
u32 vertex_binding = 0;
for (const auto& attrib : fetch_shader->attributes) {
if (attrib.UsesStepRates()) {
// Skip attribute binding as the data will be pulled by shader.
continue;
}
const auto& buffer = attrib.GetSharp(*vs_info);
if (buffer.GetSize() == 0) {
continue;
}
ASSERT(vertex_binding < MaxVertexBufferCount);
key.vertex_buffer_formats[vertex_binding++] =
Vulkan::LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt());

View File

@ -248,9 +248,7 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
return;
}
const auto& vs_info = pipeline->GetStage(Shader::LogicalStage::Vertex);
const auto& fetch_shader = pipeline->GetFetchShader();
buffer_cache.BindVertexBuffers(vs_info, fetch_shader);
buffer_cache.BindVertexBuffers(*pipeline);
if (is_indexed) {
buffer_cache.BindIndexBuffer(index_offset);
}
@ -258,6 +256,8 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
BeginRendering(*pipeline, state);
UpdateDynamicState(*pipeline);
const auto& vs_info = pipeline->GetStage(Shader::LogicalStage::Vertex);
const auto& fetch_shader = pipeline->GetFetchShader();
const auto [vertex_offset, instance_offset] = GetDrawOffsets(regs, vs_info, fetch_shader);
const auto cmdbuf = scheduler.CommandBuffer();
@ -292,9 +292,7 @@ void Rasterizer::DrawIndirect(bool is_indexed, VAddr arg_address, u32 offset, u3
return;
}
const auto& vs_info = pipeline->GetStage(Shader::LogicalStage::Vertex);
const auto& fetch_shader = pipeline->GetFetchShader();
buffer_cache.BindVertexBuffers(vs_info, fetch_shader);
buffer_cache.BindVertexBuffers(*pipeline);
if (is_indexed) {
buffer_cache.BindIndexBuffer(0);
}
@ -661,7 +659,7 @@ void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindin
if (image->binding.is_bound) {
// The image is already bound. In case if it is about to be used as storage we need
// to force general layout on it.
image->binding.force_general |= image_desc.IsStorage(tsharp);
image->binding.force_general |= image_desc.is_written;
}
if (image->binding.is_target) {
// The image is already bound as target. Since we read and output to it need to force

View File

@ -153,13 +153,7 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
// the texture cache should re-create the resource with the usage requested
vk::ImageCreateFlags flags{vk::ImageCreateFlagBits::eMutableFormat |
vk::ImageCreateFlagBits::eExtendedUsage};
const bool can_be_cube =
(info.type == vk::ImageType::e2D) &&
((info.props.is_pow2 ? (info.resources.layers % 8) : (info.resources.layers % 6)) == 0) &&
(info.size.width == info.size.height);
if (info.props.is_cube || can_be_cube) {
flags |= vk::ImageCreateFlagBits::eCubeCompatible;
} else if (info.props.is_volume) {
if (info.props.is_volume) {
flags |= vk::ImageCreateFlagBits::e2DArrayCompatible;
}

View File

@ -37,7 +37,6 @@ static vk::ImageType ConvertImageType(AmdGpu::ImageType type) noexcept {
return vk::ImageType::e1D;
case AmdGpu::ImageType::Color2D:
case AmdGpu::ImageType::Color2DMsaa:
case AmdGpu::ImageType::Cube:
case AmdGpu::ImageType::Color2DArray:
return vk::ImageType::e2D;
case AmdGpu::ImageType::Color3D:
@ -130,7 +129,6 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& de
}
type = ConvertImageType(image.GetType());
props.is_tiled = image.IsTiled();
props.is_cube = image.GetType() == AmdGpu::ImageType::Cube;
props.is_volume = image.GetType() == AmdGpu::ImageType::Color3D;
props.is_pow2 = image.pow2pad;
props.is_block = IsBlockCoded();
@ -139,7 +137,7 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image, const Shader::ImageResource& de
size.depth = props.is_volume ? image.depth + 1 : 1;
pitch = image.Pitch();
resources.levels = image.NumLevels();
resources.layers = image.NumLayers(desc.is_array);
resources.layers = image.NumLayers();
num_samples = image.NumSamples();
num_bits = NumBits(image.GetDataFmt());
@ -184,6 +182,7 @@ void ImageInfo::UpdateSize() {
case AmdGpu::TilingMode::Texture_Volume:
mip_d += (-mip_d) & 3u;
[[fallthrough]];
case AmdGpu::TilingMode::Display_MicroTiled:
case AmdGpu::TilingMode::Texture_MicroTiled: {
std::tie(mip_info.pitch, mip_info.size) =
ImageSizeMicroTiled(mip_w, mip_h, bpp, num_samples);

View File

@ -61,7 +61,6 @@ struct ImageInfo {
} meta_info{};
struct {
u32 is_cube : 1;
u32 is_volume : 1;
u32 is_tiled : 1;
u32 is_pow2 : 1;

View File

@ -20,8 +20,6 @@ vk::ImageViewType ConvertImageViewType(AmdGpu::ImageType type) {
case AmdGpu::ImageType::Color2D:
case AmdGpu::ImageType::Color2DMsaa:
return vk::ImageViewType::e2D;
case AmdGpu::ImageType::Cube:
return vk::ImageViewType::eCube;
case AmdGpu::ImageType::Color2DArray:
return vk::ImageViewType::e2DArray;
case AmdGpu::ImageType::Color3D:
@ -32,7 +30,7 @@ vk::ImageViewType ConvertImageViewType(AmdGpu::ImageType type) {
}
ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageResource& desc) noexcept
: is_storage{desc.IsStorage(image)} {
: is_storage{desc.is_written} {
const auto dfmt = image.GetDataFmt();
auto nfmt = image.GetNumberFmt();
if (is_storage && nfmt == AmdGpu::NumberFormat::Srgb) {
@ -42,30 +40,12 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageReso
if (desc.is_depth) {
format = Vulkan::LiverpoolToVK::PromoteFormatToDepth(format);
}
range.base.level = image.base_level;
range.base.layer = image.base_array;
if (image.GetType() == AmdGpu::ImageType::Color2DMsaa ||
image.GetType() == AmdGpu::ImageType::Color2DMsaaArray) {
range.extent.levels = 1;
} else {
range.extent.levels = image.last_level - image.base_level + 1;
}
range.extent.layers = image.last_array - image.base_array + 1;
type = ConvertImageViewType(image.GetBoundType());
// Adjust view type for arrays
if (type == vk::ImageViewType::eCube) {
if (desc.is_array) {
type = vk::ImageViewType::eCubeArray;
} else {
// Some games try to bind an array of cubemaps while shader reads only single one.
range.extent.layers = std::min(range.extent.layers, 6u);
}
}
if (type == vk::ImageViewType::e3D && range.extent.layers > 1) {
// Some games pass incorrect layer count for 3D textures so we need to fixup it.
range.extent.layers = 1;
}
range.extent.levels = image.NumViewLevels(desc.is_array);
range.extent.layers = image.NumViewLayers(desc.is_array);
type = ConvertImageViewType(image.GetViewType(desc.is_array));
if (!is_storage) {
mapping = Vulkan::LiverpoolToVK::ComponentMapping(image.DstSelect());

View File

@ -469,9 +469,6 @@ ImageView& TextureCache::FindDepthTarget(BaseDesc& desc) {
}
void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_scheduler /*= nullptr*/) {
RENDERER_TRACE;
TRACE_HINT(fmt::format("{:x}:{:x}", image.info.guest_address, image.info.guest_size));
if (False(image.flags & ImageFlagBits::Dirty)) {
return;
}
@ -480,6 +477,9 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule
return;
}
RENDERER_TRACE;
TRACE_HINT(fmt::format("{:x}:{:x}", image.info.guest_address, image.info.guest_size));
if (True(image.flags & ImageFlagBits::MaybeCpuDirty) &&
False(image.flags & ImageFlagBits::CpuDirty)) {
// The image size should be less than page size to be considered MaybeCpuDirty

View File

@ -65,7 +65,7 @@ public:
struct TextureDesc : public BaseDesc {
TextureDesc() = default;
TextureDesc(const AmdGpu::Image& image, const Shader::ImageResource& desc)
: BaseDesc{desc.IsStorage(image) ? BindingType::Storage : BindingType::Texture,
: BaseDesc{desc.is_written ? BindingType::Storage : BindingType::Texture,
ImageInfo{image, desc}, ImageViewInfo{image, desc}} {}
};

View File

@ -8,6 +8,7 @@
#include "video_core/texture_cache/image_view.h"
#include "video_core/texture_cache/tile_manager.h"
#include "video_core/host_shaders/detilers/display_micro_64bpp_comp.h"
#include "video_core/host_shaders/detilers/macro_32bpp_comp.h"
#include "video_core/host_shaders/detilers/macro_64bpp_comp.h"
#include "video_core/host_shaders/detilers/macro_8bpp_comp.h"
@ -53,6 +54,14 @@ const DetilerContext* TileManager::GetDetiler(const ImageInfo& info) const {
return nullptr;
}
break;
case AmdGpu::TilingMode::Display_MicroTiled:
switch (bpp) {
case 64:
return &detilers[DetilerType::Display_Micro64];
default:
return nullptr;
}
break;
default:
return nullptr;
}
@ -68,10 +77,11 @@ struct DetilerParams {
TileManager::TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler)
: instance{instance}, scheduler{scheduler} {
static const std::array detiler_shaders{
HostShaders::MICRO_8BPP_COMP, HostShaders::MICRO_16BPP_COMP,
HostShaders::MICRO_32BPP_COMP, HostShaders::MICRO_64BPP_COMP,
HostShaders::MICRO_128BPP_COMP, HostShaders::MACRO_8BPP_COMP,
HostShaders::MACRO_32BPP_COMP, HostShaders::MACRO_64BPP_COMP,
HostShaders::MICRO_8BPP_COMP, HostShaders::MICRO_16BPP_COMP,
HostShaders::MICRO_32BPP_COMP, HostShaders::MICRO_64BPP_COMP,
HostShaders::MICRO_128BPP_COMP, HostShaders::MACRO_8BPP_COMP,
HostShaders::MACRO_32BPP_COMP, HostShaders::MACRO_64BPP_COMP,
HostShaders::DISPLAY_MICRO_64BPP_COMP,
};
boost::container::static_vector<vk::DescriptorSetLayoutBinding, 2> bindings{
@ -258,7 +268,8 @@ std::pair<vk::Buffer, u32> TileManager::TryDetile(vk::Buffer in_buffer, u32 in_o
params.num_levels = info.resources.levels;
params.pitch0 = info.pitch >> (info.props.is_block ? 2u : 0u);
params.height = info.size.height;
if (info.tiling_mode == AmdGpu::TilingMode::Texture_Volume) {
if (info.tiling_mode == AmdGpu::TilingMode::Texture_Volume ||
info.tiling_mode == AmdGpu::TilingMode::Display_MicroTiled) {
ASSERT(info.resources.levels == 1);
const auto tiles_per_row = info.pitch / 8u;
const auto tiles_per_slice = tiles_per_row * ((info.size.height + 7u) / 8u);

View File

@ -22,6 +22,8 @@ enum DetilerType : u32 {
Macro32,
Macro64,
Display_Micro64,
Max
};