Merge branch 'main' into ui-fixes

This commit is contained in:
tomboylover93 2025-01-13 05:31:39 -08:00 committed by GitHub
commit 6b191ae0a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
92 changed files with 10849 additions and 403 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 set(NETWORK_LIBS src/core/libraries/network/http.cpp
src/core/libraries/network/http.h 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/net.cpp
src/core/libraries/network/netctl.cpp src/core/libraries/network/netctl.cpp
src/core/libraries/network/netctl.h 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/net.h
src/core/libraries/network/ssl.cpp src/core/libraries/network/ssl.cpp
src/core/libraries/network/ssl.h 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 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 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_manager/np_manager.h
src/core/libraries/np_score/np_score.cpp src/core/libraries/np_score/np_score.cpp
src/core/libraries/np_score/np_score.h src/core/libraries/np_score/np_score.h

View File

@ -26,7 +26,7 @@
</screenshot> </screenshot>
<screenshot> <screenshot>
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/3.png</image> <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>
<screenshot> <screenshot>
<image type="source" translate="no">https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/4.png</image> <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; static std::string trophyKey;
// Gui // Gui
static bool load_game_size = true;
std::vector<std::filesystem::path> settings_install_dirs = {}; std::vector<std::filesystem::path> settings_install_dirs = {};
std::filesystem::path settings_addon_install_dir = {}; std::filesystem::path settings_addon_install_dir = {};
u32 main_window_geometry_x = 400; u32 main_window_geometry_x = 400;
@ -102,6 +103,14 @@ void setTrophyKey(std::string key) {
trophyKey = key; trophyKey = key;
} }
bool GetLoadGameSizeEnabled() {
return load_game_size;
}
void setLoadGameSizeEnabled(bool enable) {
load_game_size = enable;
}
bool isNeoModeConsole() { bool isNeoModeConsole() {
return isNeo; return isNeo;
} }
@ -650,6 +659,7 @@ void load(const std::filesystem::path& path) {
if (data.contains("GUI")) { if (data.contains("GUI")) {
const toml::value& gui = data.at("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 = toml::find_or<int>(gui, "iconSize", 0);
m_icon_size_grid = toml::find_or<int>(gui, "iconSizeGrid", 0); m_icon_size_grid = toml::find_or<int>(gui, "iconSizeGrid", 0);
m_slider_pos = toml::find_or<int>(gui, "sliderPos", 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}); install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data});
} }
data["GUI"]["installDirs"] = install_dirs; data["GUI"]["installDirs"] = install_dirs;
data["GUI"]["loadGameSizeEnabled"] = load_game_size;
data["GUI"]["addonInstallDir"] = data["GUI"]["addonInstallDir"] =
std::string{fmt::UTF(settings_addon_install_dir.u8string()).data}; 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(); std::string getTrophyKey();
void setTrophyKey(std::string key); void setTrophyKey(std::string key);
bool GetLoadGameSizeEnabled();
void setLoadGameSizeEnabled(bool enable);
bool getIsFullscreen(); bool getIsFullscreen();
std::string getFullscreenMode(); std::string getFullscreenMode();
bool isNeoModeConsole(); bool isNeoModeConsole();

View File

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

View File

@ -63,8 +63,11 @@ enum class Class : u8 {
Lib_SaveData, ///< The LibSceSaveData implementation. Lib_SaveData, ///< The LibSceSaveData implementation.
Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation. Lib_SaveDataDialog, ///< The LibSceSaveDataDialog implementation.
Lib_Ssl, ///< The LibSceSsl implementation. Lib_Ssl, ///< The LibSceSsl implementation.
Lib_Ssl2, ///< The LibSceSsl2 implementation.
Lib_Http, ///< The LibSceHttp implementation. Lib_Http, ///< The LibSceHttp implementation.
Lib_Http2, ///< The LibSceHttp2 implementation.
Lib_SysModule, ///< The LibSceSysModule implementation Lib_SysModule, ///< The LibSceSysModule implementation
Lib_NpCommon, ///< The LibSceNpCommon implementation
Lib_NpManager, ///< The LibSceNpManager implementation Lib_NpManager, ///< The LibSceNpManager implementation
Lib_NpScore, ///< The LibSceNpScore implementation Lib_NpScore, ///< The LibSceNpScore implementation
Lib_NpTrophy, ///< The LibSceNpTrophy 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) { 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); LOG_INFO(Kernel_Pthread, "name = {}", name);
Common::SetThreadName(reinterpret_cast<void*>(thread->native_thr.GetHandle()), name); Common::SetThreadName(reinterpret_cast<void*>(thread->native_thr.GetHandle()), name);
thread->name = name; thread->name = name;

View File

@ -21,9 +21,12 @@
#include "core/libraries/mouse/mouse.h" #include "core/libraries/mouse/mouse.h"
#include "core/libraries/move/move.h" #include "core/libraries/move/move.h"
#include "core/libraries/network/http.h" #include "core/libraries/network/http.h"
#include "core/libraries/network/http2.h"
#include "core/libraries/network/net.h" #include "core/libraries/network/net.h"
#include "core/libraries/network/netctl.h" #include "core/libraries/network/netctl.h"
#include "core/libraries/network/ssl.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_manager/np_manager.h"
#include "core/libraries/np_score/np_score.h" #include "core/libraries/np_score/np_score.h"
#include "core/libraries/np_trophy/np_trophy.h" #include "core/libraries/np_trophy/np_trophy.h"
@ -64,14 +67,17 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
Libraries::MsgDialog::RegisterlibSceMsgDialog(sym); Libraries::MsgDialog::RegisterlibSceMsgDialog(sym);
Libraries::AudioOut::RegisterlibSceAudioOut(sym); Libraries::AudioOut::RegisterlibSceAudioOut(sym);
Libraries::Http::RegisterlibSceHttp(sym); Libraries::Http::RegisterlibSceHttp(sym);
Libraries::Http2::RegisterlibSceHttp2(sym);
Libraries::Net::RegisterlibSceNet(sym); Libraries::Net::RegisterlibSceNet(sym);
Libraries::NetCtl::RegisterlibSceNetCtl(sym); Libraries::NetCtl::RegisterlibSceNetCtl(sym);
Libraries::SaveData::RegisterlibSceSaveData(sym); Libraries::SaveData::RegisterlibSceSaveData(sym);
Libraries::SaveData::Dialog::RegisterlibSceSaveDataDialog(sym); Libraries::SaveData::Dialog::RegisterlibSceSaveDataDialog(sym);
Libraries::Ssl::RegisterlibSceSsl(sym); Libraries::Ssl::RegisterlibSceSsl(sym);
Libraries::Ssl2::RegisterlibSceSsl2(sym);
Libraries::SysModule::RegisterlibSceSysmodule(sym); Libraries::SysModule::RegisterlibSceSysmodule(sym);
Libraries::Posix::Registerlibsceposix(sym); Libraries::Posix::Registerlibsceposix(sym);
Libraries::AudioIn::RegisterlibSceAudioIn(sym); Libraries::AudioIn::RegisterlibSceAudioIn(sym);
Libraries::NpCommon::RegisterlibSceNpCommon(sym);
Libraries::NpManager::RegisterlibSceNpManager(sym); Libraries::NpManager::RegisterlibSceNpManager(sym);
Libraries::NpScore::RegisterlibSceNpScore(sym); Libraries::NpScore::RegisterlibSceNpScore(sym);
Libraries::NpTrophy::RegisterlibSceNpTrophy(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-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/config.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"

View File

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

View File

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

View File

@ -62,11 +62,46 @@ public:
QDir dir(dirPath); QDir dir(dirPath);
QDirIterator it(dir.absolutePath(), QDirIterator::Subdirectories); QDirIterator it(dir.absolutePath(), QDirIterator::Subdirectories);
qint64 total = 0; 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()) { while (it.hasNext()) {
it.next(); it.next();
total += it.fileInfo().size(); total += it.fileInfo().size();
} }
game.size = FormatSize(total).toStdString(); 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) { static QString GetRegion(char region) {

View File

@ -283,7 +283,7 @@ public:
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
if (createShortcutWin(linkPath, ebootPath, icoPath, exePath)) { if (createShortcutWin(linkPath, ebootPath, icoPath, exePath)) {
#else #else
if (createShortcutLinux(linkPath, ebootPath, iconPath)) { if (createShortcutLinux(linkPath, m_games[itemID].name, ebootPath, iconPath)) {
#endif #endif
QMessageBox::information( QMessageBox::information(
nullptr, tr("Shortcut creation"), nullptr, tr("Shortcut creation"),
@ -301,7 +301,7 @@ public:
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
if (createShortcutWin(linkPath, ebootPath, iconPath, exePath)) { if (createShortcutWin(linkPath, ebootPath, iconPath, exePath)) {
#else #else
if (createShortcutLinux(linkPath, ebootPath, iconPath)) { if (createShortcutLinux(linkPath, m_games[itemID].name, ebootPath, iconPath)) {
#endif #endif
QMessageBox::information( QMessageBox::information(
nullptr, tr("Shortcut creation"), nullptr, tr("Shortcut creation"),
@ -510,8 +510,8 @@ private:
return SUCCEEDED(hres); return SUCCEEDED(hres);
} }
#else #else
bool createShortcutLinux(const QString& linkPath, const QString& targetPath, bool createShortcutLinux(const QString& linkPath, const std::string& name,
const QString& iconPath) { const QString& targetPath, const QString& iconPath) {
QFile shortcutFile(linkPath); QFile shortcutFile(linkPath);
if (!shortcutFile.open(QIODevice::WriteOnly | QIODevice::Text)) { if (!shortcutFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
QMessageBox::critical(nullptr, "Error", QMessageBox::critical(nullptr, "Error",
@ -522,7 +522,7 @@ private:
QTextStream out(&shortcutFile); QTextStream out(&shortcutFile);
out << "[Desktop Entry]\n"; out << "[Desktop Entry]\n";
out << "Version=1.0\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 << "Exec=" << QCoreApplication::applicationFilePath() << " \"" << targetPath << "\"\n";
out << "Icon=" << iconPath << "\n"; out << "Icon=" << iconPath << "\n";
out << "Terminal=false\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, connect(treeWidget, &QTreeWidget::customContextMenuRequested, this,
[=, this](const QPoint& pos) { [=, this](const QPoint& pos) {
if (treeWidget->selectedItems().isEmpty()) {
return;
}
m_gui_context_menus.RequestGameMenuPKGViewer(pos, m_full_pkg_list, treeWidget, m_gui_context_menus.RequestGameMenuPKGViewer(pos, m_full_pkg_list, treeWidget,
InstallDragDropPkg); InstallDragDropPkg);
}); });

View File

@ -17,6 +17,7 @@
#ifdef ENABLE_UPDATER #ifdef ENABLE_UPDATER
#include "check_update.h" #include "check_update.h"
#endif #endif
#include <QDesktopServices>
#include <toml.hpp> #include <toml.hpp>
#include "background_music_player.h" #include "background_music_player.h"
#include "common/logging/backend.h" #include "common/logging/backend.h"
@ -203,6 +204,16 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
}); });
} }
// DEBUG TAB
{
connect(ui->OpenLogLocationButton, &QPushButton::clicked, this, []() {
QString userPath;
Common::FS::PathToQString(userPath,
Common::FS::GetUserPath(Common::FS::PathType::UserDir));
QDesktopServices::openUrl(QUrl::fromLocalFile(userPath + "/log"));
});
}
// Descriptions // Descriptions
{ {
// General // General
@ -304,6 +315,7 @@ void SettingsDialog::LoadValuesFromConfig() {
toml::find_or<std::string>(data, "General", "FullscreenMode", "Borderless"))); toml::find_or<std::string>(data, "General", "FullscreenMode", "Borderless")));
ui->separateUpdatesCheckBox->setChecked( ui->separateUpdatesCheckBox->setChecked(
toml::find_or<bool>(data, "General", "separateUpdateEnabled", false)); 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->showSplashCheckBox->setChecked(toml::find_or<bool>(data, "General", "showSplash", false));
ui->logTypeComboBox->setCurrentText( ui->logTypeComboBox->setCurrentText(
QString::fromStdString(toml::find_or<std::string>(data, "General", "logType", "async"))); QString::fromStdString(toml::find_or<std::string>(data, "General", "logType", "async")));
@ -541,6 +553,7 @@ void SettingsDialog::UpdateSettings() {
Config::setDumpShaders(ui->dumpShadersCheckBox->isChecked()); Config::setDumpShaders(ui->dumpShadersCheckBox->isChecked());
Config::setNullGpu(ui->nullGpuCheckBox->isChecked()); Config::setNullGpu(ui->nullGpuCheckBox->isChecked());
Config::setSeparateUpdateEnabled(ui->separateUpdatesCheckBox->isChecked()); Config::setSeparateUpdateEnabled(ui->separateUpdatesCheckBox->isChecked());
Config::setLoadGameSizeEnabled(ui->gameSizeCheckBox->isChecked());
Config::setShowSplash(ui->showSplashCheckBox->isChecked()); Config::setShowSplash(ui->showSplashCheckBox->isChecked());
Config::setDebugDump(ui->debugDump->isChecked()); Config::setDebugDump(ui->debugDump->isChecked());
Config::setVkValidation(ui->vkValidationCheckBox->isChecked()); Config::setVkValidation(ui->vkValidationCheckBox->isChecked());

View File

@ -67,7 +67,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>932</width> <width>946</width>
<height>611</height> <height>611</height>
</rect> </rect>
</property> </property>
@ -206,6 +206,13 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>11</number> <number>11</number>
</property> </property>
<item>
<widget class="QCheckBox" name="gameSizeCheckBox">
<property name="text">
<string>Show Game Size In List</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="playBGMCheckBox"> <widget class="QCheckBox" name="playBGMCheckBox">
<property name="sizePolicy"> <property name="sizePolicy">
@ -280,59 +287,59 @@
</property> </property>
</widget> </widget>
</item> </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> <item>
<layout class="QVBoxLayout" name="vLayoutTrophy"> <layout class="QHBoxLayout" name="hLayoutTrophy">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>80</number>
</property>
<item> <item>
<layout class="QHBoxLayout" name="hLayoutTrophy"> <widget class="QGroupBox" name="trophyGroupBox">
<item> <property name="title">
<widget class="QGroupBox" name="trophyGroupBox"> <string>Trophy</string>
<property name="title"> </property>
<string>Trophy</string> <layout class="QVBoxLayout" name="userNameLayout">
</property> <item>
<layout class="QVBoxLayout" name="userNameLayout"> <widget class="QCheckBox" name="disableTrophycheckBox">
<item> <property name="text">
<widget class="QCheckBox" name="disableTrophycheckBox"> <string>Disable Trophy Pop-ups</string>
<property name="text"> </property>
<string>Disable Trophy Pop-ups</string> </widget>
</property> </item>
</widget> <item>
</item> <widget class="QLabel" name="label_Trophy">
<item> <property name="text">
<widget class="QLabel" name="label_Trophy"> <string>Trophy Key</string>
<property name="text"> </property>
<string>Trophy Key</string> </widget>
</property> </item>
</widget> <item>
</item> <widget class="QLineEdit" name="trophyKeyLineEdit">
<item> <property name="minimumSize">
<widget class="QLineEdit" name="trophyKeyLineEdit"> <size>
<property name="minimumSize"> <width>0</width>
<size> <height>0</height>
<width>0</width> </size>
<height>0</height> </property>
</size> <property name="font">
</property> <font>
<property name="font"> <pointsize>10</pointsize>
<font> <bold>false</bold>
<pointsize>10</pointsize> </font>
<bold>false</bold> </property>
</font> </widget>
</property> </item>
</widget> </layout>
</item> </widget>
</layout>
</widget>
</item>
</layout>
</item> </item>
</layout> </layout>
</item> </item>
@ -1232,8 +1239,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>493</width> <width>946</width>
<height>236</height> <height>586</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="debugTabVLayout" stretch="0,1"> <layout class="QVBoxLayout" name="debugTabVLayout" stretch="0,1">
@ -1367,6 +1374,13 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QPushButton" name="OpenLogLocationButton">
<property name="text">
<string>Open Log Location</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>عرض حجم اللعبة في القائمة</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>إظهار شاشة البداية</translation> <translation>إظهار شاشة البداية</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>مرشح السجل</translation> <translation>مرشح السجل</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>افتح موقع السجل</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>إدخال</translation> <translation>إدخال</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Vis vis spilstørrelse i listen</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Show Splash</translation> <translation>Show Splash</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Log Filter</translation> <translation>Log Filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Åbn logplacering</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Indtastning</translation> <translation>Indtastning</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Zeigen Sie die Spielgröße in der Liste</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Startbildschirm anzeigen</translation> <translation>Startbildschirm anzeigen</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Log-Filter</translation> <translation>Log-Filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Protokollspeicherort öffnen</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Eingabe</translation> <translation>Eingabe</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Εμφάνιση Μεγέθους Παιχνιδιού στη Λίστα</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Show Splash</translation> <translation>Show Splash</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Log Filter</translation> <translation>Log Filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Άνοιγμα τοποθεσίας αρχείου καταγραφής</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Είσοδος</translation> <translation>Είσοδος</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Show Game Size In List</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Show Splash</translation> <translation>Show Splash</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Log Filter</translation> <translation>Log Filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Open Log Location</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Input</translation> <translation>Input</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Mostrar Tamaño del Juego en la Lista</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Mostrar splash</translation> <translation>Mostrar splash</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Filtro de registro</translation> <translation>Filtro de registro</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Abrir ubicación del registro</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Entrada</translation> <translation>Entrada</translation>

View File

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

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Ota Käyttöön Erillinen Päivityshakemisto</translation> <translation>Ota Käyttöön Erillinen Päivityshakemisto</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Näytä pelin koko luettelossa</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Näytä Aloitusnäyttö</translation> <translation>Näytä Aloitusnäyttö</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Lokisuodatin</translation> <translation>Lokisuodatin</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Avaa lokin sijainti</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Syöttö</translation> <translation>Syöttö</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Dossier séparé pour les mises à jours</translation> <translation>Dossier séparé pour les mises à jours</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Afficher la taille du jeu dans la liste</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Afficher l'image du jeu</translation> <translation>Afficher l'image du jeu</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Filtre</translation> <translation>Filtre</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Ouvrir l'emplacement du journal</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Entrée</translation> <translation>Entrée</translation>

View File

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

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Tampilkan Ukuran Game di Daftar</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Show Splash</translation> <translation>Show Splash</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Log Filter</translation> <translation>Log Filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Buka Lokasi Log</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Masukan</translation> <translation>Masukan</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Abilita Cartella Aggiornamenti Separata</translation> <translation>Abilita Cartella Aggiornamenti Separata</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Mostra la dimensione del gioco nell'elenco</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Mostra Schermata Iniziale</translation> <translation>Mostra Schermata Iniziale</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Filtro Log</translation> <translation>Filtro Log</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Apri posizione del registro</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Input</translation> <translation>Input</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation></translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation></translation> <translation></translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation></translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation></translation> <translation></translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation> </translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Show Splash</translation> <translation>Show Splash</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Log Filter</translation> <translation>Log Filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation> </translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Input</translation> <translation>Input</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Rodyti žaidimo dydį sąraše</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Show Splash</translation> <translation>Show Splash</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Log Filter</translation> <translation>Log Filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Atidaryti žurnalo vietą</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Įvestis</translation> <translation>Įvestis</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Aktiver seperat oppdateringsmappe</translation> <translation>Aktiver seperat oppdateringsmappe</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Vis spillstørrelse i listen</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Vis velkomstbilde</translation> <translation>Vis velkomstbilde</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Logg filter</translation> <translation>Logg filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Åpne loggplassering</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Inndata</translation> <translation>Inndata</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Toon grootte van het spel in de lijst</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Show Splash</translation> <translation>Show Splash</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Log Filter</translation> <translation>Log Filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Loglocatie openen</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Invoer</translation> <translation>Invoer</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Pokaż rozmiar gry na liście</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Pokaż ekran powitania</translation> <translation>Pokaż ekran powitania</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Filtrowanie dziennika</translation> <translation>Filtrowanie dziennika</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Otwórz lokalizację dziennika</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Wejście</translation> <translation>Wejście</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Habilitar pasta de atualização separada</translation> <translation>Habilitar pasta de atualização separada</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Mostrar Tamanho do Jogo na Lista</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Mostrar Splash Inicial</translation> <translation>Mostrar Splash Inicial</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Filtro do Registro</translation> <translation>Filtro do Registro</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Abrir local do log</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Entradas</translation> <translation>Entradas</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Afișează dimensiunea jocului în listă</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Show Splash</translation> <translation>Show Splash</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Log Filter</translation> <translation>Log Filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Deschide locația jurnalului</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Introducere</translation> <translation>Introducere</translation>

View File

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

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Aktivizo dosjen e ndarë përditësimit</translation> <translation>Aktivizo dosjen e ndarë përditësimit</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Shfaq madhësinë e lojës listë</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Shfaq Pamjen e nisjes</translation> <translation>Shfaq Pamjen e nisjes</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Filtri i Ditarit</translation> <translation>Filtri i Ditarit</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Hap vendndodhjen e regjistrit</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Hyrja</translation> <translation>Hyrja</translation>

View File

@ -1032,6 +1032,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Aktivera separat uppdateringsmapp</translation> <translation>Aktivera separat uppdateringsmapp</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Visa spelstorlek i listan</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Visa startskärm</translation> <translation>Visa startskärm</translation>
@ -1064,6 +1068,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Loggfilter</translation> <translation>Loggfilter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Öppna loggplats</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Inmatning</translation> <translation>Inmatning</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Göster oyun boyutunu listede</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Başlangıç Ekranını Göster</translation> <translation>Başlangıç Ekranını Göster</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Kayıt Filtresi</translation> <translation>Kayıt Filtresi</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Günlük Konumunu </translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Girdi</translation> <translation>Girdi</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Увімкнути окрему папку оновлень</translation> <translation>Увімкнути окрему папку оновлень</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation>Показати розмір гри в списку</translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Показувати заставку</translation> <translation>Показувати заставку</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Фільтр логів</translation> <translation>Фільтр логів</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Відкрити місце розташування журналу</translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Введення</translation> <translation>Введення</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </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> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Show Splash</translation> <translation>Show Splash</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Log Filter</translation> <translation>Log Filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation>Mở vị trí nhật </translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation>Đu vào</translation> <translation>Đu vào</translation>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation></translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation></translation> <translation></translation>
@ -558,11 +562,11 @@
</message> </message>
<message> <message>
<source>Trophy Key</source> <source>Trophy Key</source>
<translation>Trophy Key</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Trophy</source> <source>Trophy</source>
<translation>Trophy</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Logger</source> <source>Logger</source>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation></translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation></translation> <translation></translation>
@ -778,7 +786,7 @@
</message> </message>
<message> <message>
<source>TrophyKey</source> <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>
<message> <message>
<source>logTypeGroupBox</source> <source>logTypeGroupBox</source>

View File

@ -540,6 +540,10 @@
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Show Game Size In List</source>
<translation></translation>
</message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation>Show Splash</translation> <translation>Show Splash</translation>
@ -576,6 +580,10 @@
<source>Log Filter</source> <source>Log Filter</source>
<translation>Log Filter</translation> <translation>Log Filter</translation>
</message> </message>
<message>
<source>Open Log Location</source>
<translation></translation>
</message>
<message> <message>
<source>Input</source> <source>Input</source>
<translation></translation> <translation></translation>

View File

@ -205,7 +205,9 @@ void WindowSDL::InitTimers() {
void WindowSDL::RequestKeyboard() { void WindowSDL::RequestKeyboard() {
if (keyboard_grab == 0) { if (keyboard_grab == 0) {
SDL_StartTextInput(window); SDL_RunOnMainThread(
[](void* userdata) { SDL_StartTextInput(static_cast<SDL_Window*>(userdata)); }, window,
true);
} }
keyboard_grab++; keyboard_grab++;
} }
@ -214,7 +216,9 @@ void WindowSDL::ReleaseKeyboard() {
ASSERT(keyboard_grab > 0); ASSERT(keyboard_grab > 0);
keyboard_grab--; keyboard_grab--;
if (keyboard_grab == 0) { 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 auto& texture = ctx.images[handle & 0xFFFF];
const Id image = ctx.OpLoad(texture.image_type, texture.id); const Id image = ctx.OpLoad(texture.image_type, texture.id);
const auto sharp = ctx.info.images[handle & 0xFFFF].GetSharp(ctx.info); const auto sharp = ctx.info.images[handle & 0xFFFF].GetSharp(ctx.info);
const auto type = sharp.GetBoundType();
const Id zero = ctx.u32_zero_value; const Id zero = ctx.u32_zero_value;
const auto mips{[&] { return has_mips ? ctx.OpImageQueryLevels(ctx.U32[1], image) : zero; }}; 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) { const auto query{[&](Id type) {
return uses_lod ? ctx.OpImageQuerySizeLod(type, image, lod) return uses_lod ? ctx.OpImageQuerySizeLod(type, image, lod)
: ctx.OpImageQuerySize(type, image); : ctx.OpImageQuerySize(type, image);
}}; }};
switch (type) { switch (texture.view_type) {
case AmdGpu::ImageType::Color1D: case AmdGpu::ImageType::Color1D:
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips()); return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[1]), zero, zero, mips());
case AmdGpu::ImageType::Color1DArray: case AmdGpu::ImageType::Color1DArray:
case AmdGpu::ImageType::Color2D: case AmdGpu::ImageType::Color2D:
case AmdGpu::ImageType::Cube:
case AmdGpu::ImageType::Color2DMsaa: case AmdGpu::ImageType::Color2DMsaa:
return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[2]), zero, mips()); return ctx.OpCompositeConstruct(ctx.U32[4], query(ctx.U32[2]), zero, mips());
case AmdGpu::ImageType::Color2DArray: 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); 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 } // 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 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 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 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 EmitLaneId(EmitContext& ctx);
Id EmitWarpId(EmitContext& ctx); Id EmitWarpId(EmitContext& ctx);
Id EmitQuadShuffle(EmitContext& ctx, Id value, Id index); 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) { Id ImageType(EmitContext& ctx, const ImageResource& desc, Id sampled_type) {
const auto image = desc.GetSharp(ctx.info); const auto image = desc.GetSharp(ctx.info);
const auto format = desc.is_atomic ? GetFormat(image) : spv::ImageFormat::Unknown; const auto format = desc.is_atomic ? GetFormat(image) : spv::ImageFormat::Unknown;
const auto type = image.GetBoundType(); const auto type = image.GetViewType(desc.is_array);
const u32 sampled = desc.IsStorage(image) ? 2 : 1; const u32 sampled = desc.is_written ? 2 : 1;
switch (type) { switch (type) {
case AmdGpu::ImageType::Color1D: case AmdGpu::ImageType::Color1D:
return ctx.TypeImage(sampled_type, spv::Dim::Dim1D, false, false, false, sampled, format); 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); return ctx.TypeImage(sampled_type, spv::Dim::Dim2D, false, false, true, sampled, format);
case AmdGpu::ImageType::Color3D: case AmdGpu::ImageType::Color3D:
return ctx.TypeImage(sampled_type, spv::Dim::Dim3D, false, false, false, sampled, format); 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: default:
break; break;
} }
@ -802,7 +799,7 @@ void EmitContext::DefineImagesAndSamplers() {
const auto sharp = image_desc.GetSharp(info); const auto sharp = image_desc.GetSharp(info);
const auto nfmt = sharp.GetNumberFmt(); const auto nfmt = sharp.GetNumberFmt();
const bool is_integer = AmdGpu::IsInteger(nfmt); 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 VectorIds& data_types = GetAttributeType(*this, nfmt);
const Id sampled_type = data_types[1]; const Id sampled_type = data_types[1];
const Id image_type{ImageType(*this, image_desc, sampled_type)}; 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), .sampled_type = is_storage ? sampled_type : TypeSampledImage(image_type),
.pointer_type = pointer_type, .pointer_type = pointer_type,
.image_type = image_type, .image_type = image_type,
.view_type = sharp.GetViewType(image_desc.is_array),
.is_integer = is_integer, .is_integer = is_integer,
.is_storage = is_storage, .is_storage = is_storage,
}); });

View File

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

View File

@ -47,13 +47,26 @@ static IR::Condition MakeCondition(const GcnInst& inst) {
} }
} }
static bool IgnoresExecMask(Opcode opcode) { static bool IgnoresExecMask(const GcnInst& inst) {
switch (opcode) { // EXEC mask does not affect scalar instructions or branches.
case Opcode::V_WRITELANE_B32: switch (inst.category) {
case InstCategory::ScalarALU:
case InstCategory::ScalarMemory:
case InstCategory::FlowControl:
return true; return true;
default: default:
return false; break;
} }
// Read/Write Lane instructions are not affected either.
switch (inst.opcode) {
case Opcode::V_READLANE_B32:
case Opcode::V_WRITELANE_B32:
case Opcode::V_READFIRSTLANE_B32:
return true;
default:
break;
}
return false;
} }
static constexpr size_t LabelReserveSize = 32; static constexpr size_t LabelReserveSize = 32;
@ -147,8 +160,7 @@ void CFG::EmitDivergenceLabels() {
// If all instructions in the scope ignore exec masking, we shouldn't insert a // If all instructions in the scope ignore exec masking, we shouldn't insert a
// scope. // scope.
const auto start = inst_list.begin() + curr_begin + 1; const auto start = inst_list.begin() + curr_begin + 1;
if (!std::ranges::all_of(start, inst_list.begin() + index, IgnoresExecMask, if (!std::ranges::all_of(start, inst_list.begin() + index, IgnoresExecMask)) {
&GcnInst::opcode)) {
// Add a label to the instruction right after the open scope call. // Add a label to the instruction right after the open scope call.
// It is the start of a new basic block. // It is the start of a new basic block.
const auto& save_inst = inst_list[curr_begin]; const auto& save_inst = inst_list[curr_begin];

View File

@ -301,6 +301,9 @@ private:
IR::U32 VMovRelSHelper(u32 src_vgprno, const IR::U32 m0); IR::U32 VMovRelSHelper(u32 src_vgprno, const IR::U32 m0);
void VMovRelDHelper(u32 dst_vgprno, const IR::U32 src_val, 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); void LogMissingOpcode(const GcnInst& inst);
private: private:

View File

@ -3,6 +3,7 @@
#include "shader_recompiler/frontend/opcodes.h" #include "shader_recompiler/frontend/opcodes.h"
#include "shader_recompiler/frontend/translate/translate.h" #include "shader_recompiler/frontend/translate/translate.h"
#include "shader_recompiler/profile.h"
namespace Shader::Gcn { namespace Shader::Gcn {
@ -1042,20 +1043,81 @@ void Translator::V_MAD_U32_U24(const GcnInst& inst) {
V_MAD_I32_I24(inst, false); 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) { 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) { 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) { 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) { 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) { 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{}; IR::TextureInstInfo info{};
info.has_lod.Assign(has_mip); info.has_lod.Assign(has_mip);
info.is_array.Assign(mimg.da);
const IR::Value texel = ir.ImageRead(handle, body, {}, {}, info); const IR::Value texel = ir.ImageRead(handle, body, {}, {}, info);
for (u32 i = 0; i < 4; i++) { for (u32 i = 0; i < 4; i++) {
@ -442,6 +443,7 @@ void Translator::IMAGE_STORE(bool has_mip, const GcnInst& inst) {
IR::TextureInstInfo info{}; IR::TextureInstInfo info{};
info.has_lod.Assign(has_mip); info.has_lod.Assign(has_mip);
info.is_array.Assign(mimg.da);
boost::container::static_vector<IR::F32, 4> comps; boost::container::static_vector<IR::F32, 4> comps;
for (u32 i = 0; i < 4; i++) { 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) { void Translator::IMAGE_GET_RESINFO(const GcnInst& inst) {
const auto& mimg = inst.control.mimg;
IR::VectorReg dst_reg{inst.dst[0].code}; IR::VectorReg dst_reg{inst.dst[0].code};
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4}; const IR::ScalarReg tsharp_reg{inst.src[2].code * 4};
const auto flags = ImageResFlags(inst.control.mimg.dmask); const auto flags = ImageResFlags(inst.control.mimg.dmask);
const bool has_mips = flags.test(ImageResComponent::MipCount); const bool has_mips = flags.test(ImageResComponent::MipCount);
const IR::U32 lod = ir.GetVectorReg(IR::VectorReg(inst.src[0].code)); const IR::U32 lod = ir.GetVectorReg(IR::VectorReg(inst.src[0].code));
const IR::Value tsharp = ir.GetScalarReg(tsharp_reg); 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)) { if (flags.test(ImageResComponent::Width)) {
ir.SetVectorReg(dst_reg++, IR::U32{ir.CompositeExtract(size, 0)}); 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}; IR::VectorReg addr_reg{inst.src[0].code};
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4}; 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 value = ir.GetVectorReg(val_reg);
const IR::Value handle = ir.GetScalarReg(tsharp_reg); const IR::Value handle = ir.GetScalarReg(tsharp_reg);
const IR::Value body = const IR::Value body =
@ -494,25 +504,25 @@ void Translator::IMAGE_ATOMIC(AtomicOp op, const GcnInst& inst) {
case AtomicOp::Swap: case AtomicOp::Swap:
return ir.ImageAtomicExchange(handle, body, value, {}); return ir.ImageAtomicExchange(handle, body, value, {});
case AtomicOp::Add: case AtomicOp::Add:
return ir.ImageAtomicIAdd(handle, body, value, {}); return ir.ImageAtomicIAdd(handle, body, value, info);
case AtomicOp::Smin: case AtomicOp::Smin:
return ir.ImageAtomicIMin(handle, body, value, true, {}); return ir.ImageAtomicIMin(handle, body, value, true, info);
case AtomicOp::Umin: case AtomicOp::Umin:
return ir.ImageAtomicUMin(handle, body, value, {}); return ir.ImageAtomicUMin(handle, body, value, info);
case AtomicOp::Smax: case AtomicOp::Smax:
return ir.ImageAtomicIMax(handle, body, value, true, {}); return ir.ImageAtomicIMax(handle, body, value, true, info);
case AtomicOp::Umax: case AtomicOp::Umax:
return ir.ImageAtomicUMax(handle, body, value, {}); return ir.ImageAtomicUMax(handle, body, value, info);
case AtomicOp::And: case AtomicOp::And:
return ir.ImageAtomicAnd(handle, body, value, {}); return ir.ImageAtomicAnd(handle, body, value, info);
case AtomicOp::Or: case AtomicOp::Or:
return ir.ImageAtomicOr(handle, body, value, {}); return ir.ImageAtomicOr(handle, body, value, info);
case AtomicOp::Xor: case AtomicOp::Xor:
return ir.ImageAtomicXor(handle, body, value, {}); return ir.ImageAtomicXor(handle, body, value, info);
case AtomicOp::Inc: case AtomicOp::Inc:
return ir.ImageAtomicInc(handle, body, value, {}); return ir.ImageAtomicInc(handle, body, value, info);
case AtomicOp::Dec: case AtomicOp::Dec:
return ir.ImageAtomicDec(handle, body, value, {}); return ir.ImageAtomicDec(handle, body, value, info);
default: default:
UNREACHABLE(); UNREACHABLE();
} }
@ -643,11 +653,14 @@ void Translator::IMAGE_GET_LOD(const GcnInst& inst) {
IR::VectorReg addr_reg{inst.src[0].code}; IR::VectorReg addr_reg{inst.src[0].code};
const IR::ScalarReg tsharp_reg{inst.src[2].code * 4}; 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 handle = ir.GetScalarReg(tsharp_reg);
const IR::Value body = ir.CompositeConstruct( 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), ir.GetVectorReg<IR::F32>(addr_reg + 1),
ir.GetVectorReg<IR::F32>(addr_reg + 2), ir.GetVectorReg<IR::F32>(addr_reg + 3)); 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, 0)});
ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 1)}); ir.SetVectorReg(dst_reg++, IR::F32{ir.CompositeExtract(lod, 1)});
} }

View File

@ -70,14 +70,8 @@ struct ImageResource {
bool is_depth{}; bool is_depth{};
bool is_atomic{}; bool is_atomic{};
bool is_array{}; bool is_array{};
bool is_read{};
bool is_written{}; 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; [[nodiscard]] constexpr AmdGpu::Image GetSharp(const Info& info) const noexcept;
}; };
using ImageResourceList = boost::container::small_vector<ImageResource, 16>; 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); 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, Value IREmitter::ImageQueryDimension(const Value& handle, const IR::U32& lod,
const IR::U1& skip_mips, TextureInstInfo info) { const IR::U1& skip_mips, TextureInstInfo info) {
return Inst(Opcode::ImageQueryDimensions, Flags{info}, handle, lod, skip_mips); 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); 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 // Debug print maps to SPIRV's NonSemantic DebugPrintf instruction
// Renderdoc will hook in its own implementation of the SPIRV instruction // Renderdoc will hook in its own implementation of the SPIRV instruction
// Renderdoc accepts format specifiers, e.g. %u, listed here: // Renderdoc accepts format specifiers, e.g. %u, listed here:

View File

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

View File

@ -374,6 +374,9 @@ OPCODE(ImageAtomicOr32, U32, Opaq
OPCODE(ImageAtomicXor32, U32, Opaque, Opaque, U32, ) OPCODE(ImageAtomicXor32, U32, Opaque, Opaque, U32, )
OPCODE(ImageAtomicExchange32, 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 // Warp operations
OPCODE(LaneId, U32, ) OPCODE(LaneId, U32, )
OPCODE(WarpId, U32, ) OPCODE(WarpId, U32, )

View File

@ -161,10 +161,9 @@ public:
u32 Add(const ImageResource& desc) { u32 Add(const ImageResource& desc) {
const u32 index{Add(image_resources, desc, [&desc](const auto& existing) { 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]; auto& image = image_resources[index];
image.is_read |= desc.is_read;
image.is_written |= desc.is_written; image.is_written |= desc.is_written;
return index; return index;
} }
@ -361,7 +360,6 @@ void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors&
image = AmdGpu::Image::Null(); image = AmdGpu::Image::Null();
} }
ASSERT(image.GetType() != AmdGpu::ImageType::Invalid); ASSERT(image.GetType() != AmdGpu::ImageType::Invalid);
const bool is_read = inst.GetOpcode() == IR::Opcode::ImageRead;
const bool is_written = inst.GetOpcode() == IR::Opcode::ImageWrite; const bool is_written = inst.GetOpcode() == IR::Opcode::ImageWrite;
// Patch image instruction if image is FMask. // 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_depth = bool(inst_info.is_depth),
.is_atomic = IsImageAtomicInstruction(inst), .is_atomic = IsImageAtomicInstruction(inst),
.is_array = bool(inst_info.is_array), .is_array = bool(inst_info.is_array),
.is_read = is_read,
.is_written = is_written, .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, 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 handle = inst.Arg(0);
const auto sampler_res = info.samplers[(handle.U32() >> 16) & 0xFFFF]; const auto sampler_res = info.samplers[(handle.U32() >> 16) & 0xFFFF];
auto sampler = sampler_res.GetSharp(info); auto sampler = sampler_res.GetSharp(info);
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
const auto inst_info = inst.Flags<IR::TextureInstInfo>(); 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* body1 = inst.Arg(1).InstRecursive();
IR::Inst* body2 = inst.Arg(2).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); 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::Color1D:
case AmdGpu::ImageType::Color1DArray: case AmdGpu::ImageType::Color1DArray:
return read(0); return read(0);
@ -649,7 +621,6 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info,
case AmdGpu::ImageType::Color2DMsaa: case AmdGpu::ImageType::Color2DMsaa:
return ir.CompositeConstruct(read(0), read(8)); return ir.CompositeConstruct(read(0), read(8));
case AmdGpu::ImageType::Color3D: case AmdGpu::ImageType::Color3D:
case AmdGpu::ImageType::Cube:
return ir.CompositeConstruct(read(0), read(8), read(16)); return ir.CompositeConstruct(read(0), read(8), read(16));
default: default:
UNREACHABLE(); UNREACHABLE();
@ -661,7 +632,7 @@ void PatchImageSampleArgs(IR::Block& block, IR::Inst& inst, Info& info,
if (!inst_info.has_derivatives) { if (!inst_info.has_derivatives) {
return {}; return {};
} }
switch (image.GetType()) { switch (view_type) {
case AmdGpu::ImageType::Color1D: case AmdGpu::ImageType::Color1D:
case AmdGpu::ImageType::Color1DArray: case AmdGpu::ImageType::Color1DArray:
// du/dx, du/dy // 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)), 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))}; ir.CompositeConstruct(get_addr_reg(addr_reg - 2), get_addr_reg(addr_reg - 1))};
case AmdGpu::ImageType::Color3D: case AmdGpu::ImageType::Color3D:
case AmdGpu::ImageType::Cube:
// (du/dx, dv/dx, dw/dx), (du/dy, dv/dy, dw/dy) // (du/dx, dv/dx, dw/dx), (du/dy, dv/dy, dw/dy)
addr_reg = addr_reg + 6; addr_reg = addr_reg + 6;
return {ir.CompositeConstruct(get_addr_reg(addr_reg - 6), get_addr_reg(addr_reg - 5), 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. // 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. // We can't use the image sharp because it could be bound to a different image later.
const auto dimensions = 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 get_coord = [&](u32 coord_idx, u32 dim_idx) -> IR::Value {
const auto coord = get_addr_reg(coord_idx); const auto coord = get_addr_reg(coord_idx);
if (unnormalized) { 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 // Now we can load body components as noted in Table 8.9 Image Opcodes with Sampler
const IR::Value coords = [&] -> IR::Value { const IR::Value coords = [&] -> IR::Value {
switch (image.GetType()) { switch (view_type) {
case AmdGpu::ImageType::Color1D: // x case AmdGpu::ImageType::Color1D: // x
addr_reg = addr_reg + 1; addr_reg = addr_reg + 1;
return get_coord(addr_reg - 1, 0); 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; addr_reg = addr_reg + 3;
return ir.CompositeConstruct(get_coord(addr_reg - 3, 0), get_coord(addr_reg - 2, 1), return ir.CompositeConstruct(get_coord(addr_reg - 3, 0), get_coord(addr_reg - 2, 1),
get_coord(addr_reg - 1, 2)); 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: default:
UNREACHABLE(); 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. // Sample instructions must be handled separately using address register data.
if (inst.GetOpcode() == IR::Opcode::ImageSampleRaw) { if (inst.GetOpcode() == IR::Opcode::ImageSampleRaw) {
PatchImageSampleArgs(block, inst, info, image); PatchImageSampleArgs(block, inst, info, image_res, image);
return; return;
} }
IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)};
const auto inst_info = inst.Flags<IR::TextureInstInfo>(); 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. // Now that we know the image type, adjust texture coordinate vector.
IR::Inst* body = inst.Arg(1).InstRecursive(); IR::Inst* body = inst.Arg(1).InstRecursive();
const auto [coords, arg] = [&] -> std::pair<IR::Value, IR::Value> { const auto [coords, arg] = [&] -> std::pair<IR::Value, IR::Value> {
switch (image.GetType()) { switch (view_type) {
case AmdGpu::ImageType::Color1D: // x, [lod] case AmdGpu::ImageType::Color1D: // x, [lod]
return {body->Arg(0), body->Arg(1)}; return {body->Arg(0), body->Arg(1)};
case AmdGpu::ImageType::Color1DArray: // x, slice, [lod] case AmdGpu::ImageType::Color1DArray: // x, slice, [lod]
@ -805,22 +773,18 @@ void PatchImageArgs(IR::Block& block, IR::Inst& inst, Info& info) {
[[fallthrough]]; [[fallthrough]];
case AmdGpu::ImageType::Color3D: // x, y, z, [lod] case AmdGpu::ImageType::Color3D: // x, y, z, [lod]
return {ir.CompositeConstruct(body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)}; 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: default:
UNREACHABLE_MSG("Unknown image type {}", image.GetType()); UNREACHABLE_MSG("Unknown image type {}", view_type);
} }
}(); }();
const auto has_ms = image.GetType() == AmdGpu::ImageType::Color2DMsaa || const auto has_ms = view_type == AmdGpu::ImageType::Color2DMsaa ||
image.GetType() == AmdGpu::ImageType::Color2DMsaaArray; view_type == AmdGpu::ImageType::Color2DMsaaArray;
ASSERT(!inst_info.has_lod || !has_ms); ASSERT(!inst_info.has_lod || !has_ms);
const auto lod = inst_info.has_lod ? IR::U32{arg} : IR::U32{}; const auto lod = inst_info.has_lod ? IR::U32{arg} : IR::U32{};
const auto ms = has_ms ? 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) { if (inst.GetOpcode() == IR::Opcode::ImageRead) {
auto texel = ir.ImageRead(handle, coords, lod, ms, inst_info); auto texel = ir.ImageRead(handle, coords, lod, ms, inst_info);
if (is_storage) { if (is_storage) {

View File

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

View File

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

View File

@ -113,9 +113,9 @@ struct StageSpecialization {
}); });
ForEachSharp(binding, images, info->images, ForEachSharp(binding, images, info->images,
[](auto& spec, const auto& desc, AmdGpu::Image sharp) { [](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_integer = AmdGpu::IsInteger(sharp.GetNumberFmt());
spec.is_storage = desc.IsStorage(sharp); spec.is_storage = desc.is_written;
if (spec.is_storage) { if (spec.is_storage) {
spec.dst_select = sharp.DstSelect(); 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. // There is a small difference between T# and CB number types, account for it.
return RemapNumberFormat(info.number_type == NumberFormat::SnormNz return RemapNumberFormat(info.number_type == NumberFormat::SnormNz
? NumberFormat::Srgb ? NumberFormat::Srgb
: info.number_type.Value()); : info.number_type.Value(),
info.format);
} }
[[nodiscard]] NumberConversion GetNumberConversion() const { [[nodiscard]] NumberConversion GetNumberConversion() const {

View File

@ -54,7 +54,7 @@ struct Buffer {
} }
NumberFormat GetNumberFmt() const noexcept { NumberFormat GetNumberFmt() const noexcept {
return RemapNumberFormat(NumberFormat(num_format)); return RemapNumberFormat(NumberFormat(num_format), DataFormat(data_format));
} }
DataFormat GetDataFmt() const noexcept { DataFormat GetDataFmt() const noexcept {
@ -119,6 +119,7 @@ constexpr std::string_view NameOf(ImageType type) {
enum class TilingMode : u32 { enum class TilingMode : u32 {
Depth_MacroTiled = 0u, Depth_MacroTiled = 0u,
Display_Linear = 0x8u, Display_Linear = 0x8u,
Display_MicroTiled = 0x9u,
Display_MacroTiled = 0xAu, Display_MacroTiled = 0xAu,
Texture_MicroTiled = 0xDu, Texture_MicroTiled = 0xDu,
Texture_MacroTiled = 0xEu, Texture_MacroTiled = 0xEu,
@ -131,6 +132,8 @@ constexpr std::string_view NameOf(TilingMode type) {
return "Depth_MacroTiled"; return "Depth_MacroTiled";
case TilingMode::Display_Linear: case TilingMode::Display_Linear:
return "Display_Linear"; return "Display_Linear";
case TilingMode::Display_MicroTiled:
return "Display_MicroTiled";
case TilingMode::Display_MacroTiled: case TilingMode::Display_MacroTiled:
return "Display_MacroTiled"; return "Display_MacroTiled";
case TilingMode::Texture_MicroTiled: case TilingMode::Texture_MicroTiled:
@ -226,15 +229,15 @@ struct Image {
return pitch + 1; return pitch + 1;
} }
u32 NumLayers(bool is_array) const { [[nodiscard]] u32 NumLayers() const noexcept {
u32 slices = GetType() == ImageType::Color3D ? 1 : depth + 1; // Depth is the number of layers for Array images.
if (GetType() == ImageType::Cube) { u32 slices = depth + 1;
if (is_array) { if (GetType() == ImageType::Color3D) {
slices = last_array + 1; // Depth is the actual texture depth for 3D images.
ASSERT(slices % 6 == 0); slices = 1;
} else { } else if (IsCube()) {
slices = 6; // Depth is the number of full cubes for Cube images.
} slices *= 6;
} }
if (pow2pad) { if (pow2pad) {
slices = std::bit_ceil(slices); slices = std::bit_ceil(slices);
@ -256,8 +259,12 @@ struct Image {
return 1; return 1;
} }
bool IsCube() const noexcept {
return static_cast<ImageType>(type) == ImageType::Cube;
}
ImageType GetType() const noexcept { ImageType GetType() const noexcept {
return static_cast<ImageType>(type); return IsCube() ? ImageType::Color2DArray : static_cast<ImageType>(type);
} }
DataFormat GetDataFmt() const noexcept { DataFormat GetDataFmt() const noexcept {
@ -265,7 +272,7 @@ struct Image {
} }
NumberFormat GetNumberFmt() const noexcept { NumberFormat GetNumberFmt() const noexcept {
return RemapNumberFormat(NumberFormat(num_format)); return RemapNumberFormat(NumberFormat(num_format), DataFormat(data_format));
} }
NumberConversion GetNumberConversion() const noexcept { NumberConversion GetNumberConversion() const noexcept {
@ -289,13 +296,48 @@ struct Image {
GetDataFmt() <= DataFormat::FormatFmask64_8; GetDataFmt() <= DataFormat::FormatFmask64_8;
} }
bool IsPartialCubemap() const { [[nodiscard]] ImageType GetViewType(const bool is_array) const noexcept {
const auto viewed_slice = last_array - base_array + 1; const auto base_type = GetType();
return GetType() == ImageType::Cube && viewed_slice < 6; 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 { [[nodiscard]] u32 NumViewLevels(const bool is_array) const noexcept {
return IsPartialCubemap() ? ImageType::Color2DArray : GetType(); 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 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) { switch (format) {
case NumberFormat::Uscaled: case NumberFormat::Uscaled:
return NumberFormat::Uint; return NumberFormat::Uint;
@ -260,6 +260,14 @@ inline NumberFormat RemapNumberFormat(const NumberFormat format) {
return NumberFormat::Sint; return NumberFormat::Sint;
case NumberFormat::Ubnorm: case NumberFormat::Ubnorm:
return NumberFormat::Unorm; 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: default:
return format; return format;
} }

View File

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

View File

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

View File

@ -2,6 +2,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
set(SHADER_FILES set(SHADER_FILES
detilers/display_micro_64bpp.comp
detilers/macro_32bpp.comp detilers/macro_32bpp.comp
detilers/macro_64bpp.comp detilers/macro_64bpp.comp
detilers/macro_8bpp.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) { for (const auto& image : info->images) {
bindings.push_back({ bindings.push_back({
.binding = binding++, .binding = binding++,
.descriptorType = image.IsStorage(image.GetSharp(*info)) .descriptorType = image.is_written ? vk::DescriptorType::eStorageImage
? vk::DescriptorType::eStorageImage : vk::DescriptorType::eSampledImage,
: vk::DescriptorType::eSampledImage,
.descriptorCount = 1, .descriptorCount = 1,
.stageFlags = vk::ShaderStageFlagBits::eCompute, .stageFlags = vk::ShaderStageFlagBits::eCompute,
}); });

View File

@ -57,35 +57,11 @@ GraphicsPipeline::GraphicsPipeline(
pipeline_layout = std::move(layout); pipeline_layout = std::move(layout);
SetObjectName(device, *pipeline_layout, "Graphics PipelineLayout {}", debug_str); SetObjectName(device, *pipeline_layout, "Graphics PipelineLayout {}", debug_str);
boost::container::static_vector<vk::VertexInputBindingDescription, 32> vertex_bindings; VertexInputs<vk::VertexInputAttributeDescription> vertex_attributes;
boost::container::static_vector<vk::VertexInputAttributeDescription, 32> vertex_attributes; VertexInputs<vk::VertexInputBindingDescription> vertex_bindings;
if (fetch_shader && !instance.IsVertexInputDynamicState()) { VertexInputs<AmdGpu::Buffer> guest_buffers;
const auto& vs_info = GetStage(Shader::LogicalStage::Vertex); if (!instance.IsVertexInputDynamicState()) {
for (const auto& attrib : fetch_shader->attributes) { GetVertexInputs(vertex_attributes, vertex_bindings, guest_buffers);
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,
});
}
} }
const vk::PipelineVertexInputStateCreateInfo vertex_input_info = { const vk::PipelineVertexInputStateCreateInfo vertex_input_info = {
@ -161,7 +137,7 @@ GraphicsPipeline::GraphicsPipeline(
} }
if (instance.IsVertexInputDynamicState()) { if (instance.IsVertexInputDynamicState()) {
dynamic_states.push_back(vk::DynamicState::eVertexInputEXT); dynamic_states.push_back(vk::DynamicState::eVertexInputEXT);
} else { } else if (!vertex_bindings.empty()) {
dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStrideEXT); dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStrideEXT);
} }
@ -329,6 +305,51 @@ GraphicsPipeline::GraphicsPipeline(
GraphicsPipeline::~GraphicsPipeline() = default; 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() { void GraphicsPipeline::BuildDescSetLayout() {
boost::container::small_vector<vk::DescriptorSetLayoutBinding, 32> bindings; boost::container::small_vector<vk::DescriptorSetLayoutBinding, 32> bindings;
u32 binding{}; u32 binding{};
@ -367,9 +388,8 @@ void GraphicsPipeline::BuildDescSetLayout() {
for (const auto& image : stage->images) { for (const auto& image : stage->images) {
bindings.push_back({ bindings.push_back({
.binding = binding++, .binding = binding++,
.descriptorType = image.IsStorage(image.GetSharp(*stage)) .descriptorType = image.is_written ? vk::DescriptorType::eStorageImage
? vk::DescriptorType::eStorageImage : vk::DescriptorType::eSampledImage,
: vk::DescriptorType::eSampledImage,
.descriptorCount = 1, .descriptorCount = 1,
.stageFlags = gp_stage_flags, .stageFlags = gp_stage_flags,
}); });

View File

@ -3,6 +3,7 @@
#pragma once #pragma once
#include <boost/container/static_vector.hpp>
#include <xxhash.h> #include <xxhash.h>
#include "common/types.h" #include "common/types.h"
@ -27,6 +28,9 @@ class DescriptorHeap;
using Liverpool = AmdGpu::Liverpool; using Liverpool = AmdGpu::Liverpool;
template <typename T>
using VertexInputs = boost::container::static_vector<T, MaxVertexBufferCount>;
struct GraphicsPipelineKey { struct GraphicsPipelineKey {
std::array<size_t, MaxShaderStages> stage_hashes; std::array<size_t, MaxShaderStages> stage_hashes;
u32 num_color_attachments; u32 num_color_attachments;
@ -100,6 +104,11 @@ public:
key.prim_type == AmdGpu::PrimitiveType::QuadList; 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: private:
void BuildDescSetLayout(); void BuildDescSetLayout();

View File

@ -271,6 +271,7 @@ bool Instance::CreateDevice() {
maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME); maintenance5 = add_extension(VK_KHR_MAINTENANCE_5_EXTENSION_NAME);
legacy_vertex_attributes = add_extension(VK_EXT_LEGACY_VERTEX_ATTRIBUTES_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); 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 // These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2
// with extensions. // with extensions.

View File

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

View File

@ -204,6 +204,7 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
.support_explicit_workgroup_layout = true, .support_explicit_workgroup_layout = true,
.support_legacy_vertex_attributes = instance_.IsLegacyVertexAttributesSupported(), .support_legacy_vertex_attributes = instance_.IsLegacyVertexAttributesSupported(),
.supports_image_load_store_lod = instance_.IsImageLoadStoreLodSupported(), .supports_image_load_store_lod = instance_.IsImageLoadStoreLodSupported(),
.supports_native_cube_calc = instance_.IsAmdGcnShaderSupported(),
.needs_manual_interpolation = instance.IsFragmentShaderBarycentricSupported() && .needs_manual_interpolation = instance.IsFragmentShaderBarycentricSupported() &&
instance.GetDriverID() == vk::DriverId::eNvidiaProprietary, instance.GetDriverID() == vk::DriverId::eNvidiaProprietary,
.needs_lds_barriers = 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()) { 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; u32 vertex_binding = 0;
for (const auto& attrib : fetch_shader->attributes) { for (const auto& attrib : fetch_shader->attributes) {
if (attrib.UsesStepRates()) { if (attrib.UsesStepRates()) {
// Skip attribute binding as the data will be pulled by shader.
continue; continue;
} }
const auto& buffer = attrib.GetSharp(*vs_info); const auto& buffer = attrib.GetSharp(*vs_info);
if (buffer.GetSize() == 0) {
continue;
}
ASSERT(vertex_binding < MaxVertexBufferCount); ASSERT(vertex_binding < MaxVertexBufferCount);
key.vertex_buffer_formats[vertex_binding++] = key.vertex_buffer_formats[vertex_binding++] =
Vulkan::LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt()); Vulkan::LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt());

View File

@ -248,9 +248,7 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
return; return;
} }
const auto& vs_info = pipeline->GetStage(Shader::LogicalStage::Vertex); buffer_cache.BindVertexBuffers(*pipeline);
const auto& fetch_shader = pipeline->GetFetchShader();
buffer_cache.BindVertexBuffers(vs_info, fetch_shader);
if (is_indexed) { if (is_indexed) {
buffer_cache.BindIndexBuffer(index_offset); buffer_cache.BindIndexBuffer(index_offset);
} }
@ -258,6 +256,8 @@ void Rasterizer::Draw(bool is_indexed, u32 index_offset) {
BeginRendering(*pipeline, state); BeginRendering(*pipeline, state);
UpdateDynamicState(*pipeline); 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 [vertex_offset, instance_offset] = GetDrawOffsets(regs, vs_info, fetch_shader);
const auto cmdbuf = scheduler.CommandBuffer(); const auto cmdbuf = scheduler.CommandBuffer();
@ -292,9 +292,7 @@ void Rasterizer::DrawIndirect(bool is_indexed, VAddr arg_address, u32 offset, u3
return; return;
} }
const auto& vs_info = pipeline->GetStage(Shader::LogicalStage::Vertex); buffer_cache.BindVertexBuffers(*pipeline);
const auto& fetch_shader = pipeline->GetFetchShader();
buffer_cache.BindVertexBuffers(vs_info, fetch_shader);
if (is_indexed) { if (is_indexed) {
buffer_cache.BindIndexBuffer(0); buffer_cache.BindIndexBuffer(0);
} }
@ -661,7 +659,7 @@ void Rasterizer::BindTextures(const Shader::Info& stage, Shader::Backend::Bindin
if (image->binding.is_bound) { if (image->binding.is_bound) {
// The image is already bound. In case if it is about to be used as storage we need // The image is already bound. In case if it is about to be used as storage we need
// to force general layout on it. // 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) { if (image->binding.is_target) {
// The image is already bound as target. Since we read and output to it need to force // 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 // the texture cache should re-create the resource with the usage requested
vk::ImageCreateFlags flags{vk::ImageCreateFlagBits::eMutableFormat | vk::ImageCreateFlags flags{vk::ImageCreateFlagBits::eMutableFormat |
vk::ImageCreateFlagBits::eExtendedUsage}; vk::ImageCreateFlagBits::eExtendedUsage};
const bool can_be_cube = if (info.props.is_volume) {
(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) {
flags |= vk::ImageCreateFlagBits::e2DArrayCompatible; flags |= vk::ImageCreateFlagBits::e2DArrayCompatible;
} }

View File

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

View File

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

View File

@ -20,8 +20,6 @@ vk::ImageViewType ConvertImageViewType(AmdGpu::ImageType type) {
case AmdGpu::ImageType::Color2D: case AmdGpu::ImageType::Color2D:
case AmdGpu::ImageType::Color2DMsaa: case AmdGpu::ImageType::Color2DMsaa:
return vk::ImageViewType::e2D; return vk::ImageViewType::e2D;
case AmdGpu::ImageType::Cube:
return vk::ImageViewType::eCube;
case AmdGpu::ImageType::Color2DArray: case AmdGpu::ImageType::Color2DArray:
return vk::ImageViewType::e2DArray; return vk::ImageViewType::e2DArray;
case AmdGpu::ImageType::Color3D: 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 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(); const auto dfmt = image.GetDataFmt();
auto nfmt = image.GetNumberFmt(); auto nfmt = image.GetNumberFmt();
if (is_storage && nfmt == AmdGpu::NumberFormat::Srgb) { if (is_storage && nfmt == AmdGpu::NumberFormat::Srgb) {
@ -42,30 +40,12 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Image& image, const Shader::ImageReso
if (desc.is_depth) { if (desc.is_depth) {
format = Vulkan::LiverpoolToVK::PromoteFormatToDepth(format); format = Vulkan::LiverpoolToVK::PromoteFormatToDepth(format);
} }
range.base.level = image.base_level; range.base.level = image.base_level;
range.base.layer = image.base_array; range.base.layer = image.base_array;
if (image.GetType() == AmdGpu::ImageType::Color2DMsaa || range.extent.levels = image.NumViewLevels(desc.is_array);
image.GetType() == AmdGpu::ImageType::Color2DMsaaArray) { range.extent.layers = image.NumViewLayers(desc.is_array);
range.extent.levels = 1; type = ConvertImageViewType(image.GetViewType(desc.is_array));
} 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;
}
if (!is_storage) { if (!is_storage) {
mapping = Vulkan::LiverpoolToVK::ComponentMapping(image.DstSelect()); 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*/) { 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)) { if (False(image.flags & ImageFlagBits::Dirty)) {
return; return;
} }
@ -480,6 +477,9 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule
return; return;
} }
RENDERER_TRACE;
TRACE_HINT(fmt::format("{:x}:{:x}", image.info.guest_address, image.info.guest_size));
if (True(image.flags & ImageFlagBits::MaybeCpuDirty) && if (True(image.flags & ImageFlagBits::MaybeCpuDirty) &&
False(image.flags & ImageFlagBits::CpuDirty)) { False(image.flags & ImageFlagBits::CpuDirty)) {
// The image size should be less than page size to be considered MaybeCpuDirty // The image size should be less than page size to be considered MaybeCpuDirty

View File

@ -65,7 +65,7 @@ public:
struct TextureDesc : public BaseDesc { struct TextureDesc : public BaseDesc {
TextureDesc() = default; TextureDesc() = default;
TextureDesc(const AmdGpu::Image& image, const Shader::ImageResource& desc) 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}} {} 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/image_view.h"
#include "video_core/texture_cache/tile_manager.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_32bpp_comp.h"
#include "video_core/host_shaders/detilers/macro_64bpp_comp.h" #include "video_core/host_shaders/detilers/macro_64bpp_comp.h"
#include "video_core/host_shaders/detilers/macro_8bpp_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; return nullptr;
} }
break; break;
case AmdGpu::TilingMode::Display_MicroTiled:
switch (bpp) {
case 64:
return &detilers[DetilerType::Display_Micro64];
default:
return nullptr;
}
break;
default: default:
return nullptr; return nullptr;
} }
@ -68,10 +77,11 @@ struct DetilerParams {
TileManager::TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler) TileManager::TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler)
: instance{instance}, scheduler{scheduler} { : instance{instance}, scheduler{scheduler} {
static const std::array detiler_shaders{ static const std::array detiler_shaders{
HostShaders::MICRO_8BPP_COMP, HostShaders::MICRO_16BPP_COMP, HostShaders::MICRO_8BPP_COMP, HostShaders::MICRO_16BPP_COMP,
HostShaders::MICRO_32BPP_COMP, HostShaders::MICRO_64BPP_COMP, HostShaders::MICRO_32BPP_COMP, HostShaders::MICRO_64BPP_COMP,
HostShaders::MICRO_128BPP_COMP, HostShaders::MACRO_8BPP_COMP, HostShaders::MICRO_128BPP_COMP, HostShaders::MACRO_8BPP_COMP,
HostShaders::MACRO_32BPP_COMP, HostShaders::MACRO_64BPP_COMP, HostShaders::MACRO_32BPP_COMP, HostShaders::MACRO_64BPP_COMP,
HostShaders::DISPLAY_MICRO_64BPP_COMP,
}; };
boost::container::static_vector<vk::DescriptorSetLayoutBinding, 2> bindings{ 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.num_levels = info.resources.levels;
params.pitch0 = info.pitch >> (info.props.is_block ? 2u : 0u); params.pitch0 = info.pitch >> (info.props.is_block ? 2u : 0u);
params.height = info.size.height; 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); ASSERT(info.resources.levels == 1);
const auto tiles_per_row = info.pitch / 8u; const auto tiles_per_row = info.pitch / 8u;
const auto tiles_per_slice = tiles_per_row * ((info.size.height + 7u) / 8u); const auto tiles_per_slice = tiles_per_row * ((info.size.height + 7u) / 8u);

View File

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