mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-08-06 01:12:33 +00:00
Merge branch 'shadps4-emu:main' into Fix_PromoteFormatToDepth
This commit is contained in:
commit
7d02688f96
12
.github/ISSUE_TEMPLATE/game-bug-report.yaml
vendored
12
.github/ISSUE_TEMPLATE/game-bug-report.yaml
vendored
@ -13,7 +13,11 @@ body:
|
|||||||
**Please do not make support requests on GitHub. Our issue tracker is for tracking bugs and feature requests only.
|
**Please do not make support requests on GitHub. Our issue tracker is for tracking bugs and feature requests only.
|
||||||
If you have a support request or are unsure about the nature of your issue please contact us on [discord](https://discord.gg/bFJxfftGW6).**
|
If you have a support request or are unsure about the nature of your issue please contact us on [discord](https://discord.gg/bFJxfftGW6).**
|
||||||
|
|
||||||
You can also check the [Game Compatibility Repository](https://github.com/shadps4-emu/shadps4-game-compatibility) for the information about the status of the game.
|
This repository does not provide support for modded games. You should perform and test a clean game installation before submitting an issue.
|
||||||
|
|
||||||
|
This repository does not provide support for game patches. If you are having issues with patches please refer to [Cheats and Patches Repository](https://github.com/shadps4-emu/ps4_cheats).
|
||||||
|
|
||||||
|
Before submitting an issue please check [Game Compatibility Repository](https://github.com/shadps4-emu/shadps4-game-compatibility) for the information about the status of the game.
|
||||||
|
|
||||||
Please make an effort to make sure your issue isn't already reported.
|
Please make an effort to make sure your issue isn't already reported.
|
||||||
|
|
||||||
@ -21,15 +25,15 @@ body:
|
|||||||
- type: checkboxes
|
- type: checkboxes
|
||||||
id: checklist
|
id: checklist
|
||||||
attributes:
|
attributes:
|
||||||
label: Checklist
|
label: Checklist (we expect you to perform these steps before opening the issue)
|
||||||
options:
|
options:
|
||||||
- label: I have searched for a similar issue in this repository and did not find one.
|
- label: I have searched for a similar issue in this repository and did not find one.
|
||||||
required: true
|
required: true
|
||||||
- label: I am using an official build obtained from [releases](https://github.com/shadps4-emu/shadPS4/releases) or updated one of those builds using its in-app updater.
|
- label: I am using an official build obtained from [releases](https://github.com/shadps4-emu/shadPS4/releases) or updated one of those builds using its in-app updater.
|
||||||
required: true
|
required: true
|
||||||
- label: I have re-dumped the game and performed a clean install without mods.
|
- label: I have re-dumped the game and performed a clean install without mods and the issue is still present.
|
||||||
required: true
|
required: true
|
||||||
- label: I have disabled all patches and cheats.
|
- label: I have disabled all patches and cheats and the issue is still present.
|
||||||
required: true
|
required: true
|
||||||
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadps4-game-compatibility?tab=readme-ov-file#informations) installed.
|
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadps4-game-compatibility?tab=readme-ov-file#informations) installed.
|
||||||
required: true
|
required: true
|
||||||
|
@ -67,6 +67,7 @@ static int cursorHideTimeout = 5; // 5 seconds (default)
|
|||||||
static bool separateupdatefolder = false;
|
static bool separateupdatefolder = false;
|
||||||
static bool compatibilityData = false;
|
static bool compatibilityData = false;
|
||||||
static bool checkCompatibilityOnStartup = false;
|
static bool checkCompatibilityOnStartup = false;
|
||||||
|
static std::string trophyKey;
|
||||||
|
|
||||||
// Gui
|
// Gui
|
||||||
std::vector<std::filesystem::path> settings_install_dirs = {};
|
std::vector<std::filesystem::path> settings_install_dirs = {};
|
||||||
@ -91,6 +92,14 @@ std::string emulator_language = "en";
|
|||||||
// Language
|
// Language
|
||||||
u32 m_language = 1; // english
|
u32 m_language = 1; // english
|
||||||
|
|
||||||
|
std::string getTrophyKey() {
|
||||||
|
return trophyKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTrophyKey(std::string key) {
|
||||||
|
trophyKey = key;
|
||||||
|
}
|
||||||
|
|
||||||
bool isNeoMode() {
|
bool isNeoMode() {
|
||||||
return isNeo;
|
return isNeo;
|
||||||
}
|
}
|
||||||
@ -652,6 +661,11 @@ void load(const std::filesystem::path& path) {
|
|||||||
|
|
||||||
m_language = toml::find_or<int>(settings, "consoleLanguage", 1);
|
m_language = toml::find_or<int>(settings, "consoleLanguage", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data.contains("Keys")) {
|
||||||
|
const toml::value& keys = data.at("Keys");
|
||||||
|
trophyKey = toml::find_or<std::string>(keys, "TrophyKey", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void save(const std::filesystem::path& path) {
|
void save(const std::filesystem::path& path) {
|
||||||
@ -712,6 +726,8 @@ void save(const std::filesystem::path& path) {
|
|||||||
data["Debug"]["DebugDump"] = isDebugDump;
|
data["Debug"]["DebugDump"] = isDebugDump;
|
||||||
data["Debug"]["CollectShader"] = isShaderDebug;
|
data["Debug"]["CollectShader"] = isShaderDebug;
|
||||||
|
|
||||||
|
data["Keys"]["TrophyKey"] = trophyKey;
|
||||||
|
|
||||||
std::vector<std::string> install_dirs;
|
std::vector<std::string> install_dirs;
|
||||||
for (const auto& dirString : settings_install_dirs) {
|
for (const auto& dirString : settings_install_dirs) {
|
||||||
install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data});
|
install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data});
|
||||||
|
@ -15,6 +15,9 @@ void load(const std::filesystem::path& path);
|
|||||||
void save(const std::filesystem::path& path);
|
void save(const std::filesystem::path& path);
|
||||||
void saveMainWindow(const std::filesystem::path& path);
|
void saveMainWindow(const std::filesystem::path& path);
|
||||||
|
|
||||||
|
std::string getTrophyKey();
|
||||||
|
void setTrophyKey(std::string key);
|
||||||
|
|
||||||
bool isNeoMode();
|
bool isNeoMode();
|
||||||
bool isFullscreenMode();
|
bool isFullscreenMode();
|
||||||
bool getPlayBGM();
|
bool getPlayBGM();
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
|
|
||||||
CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() {
|
CryptoPP::RSA::PrivateKey Crypto::key_pkg_derived_key3_keyset_init() {
|
||||||
@ -137,17 +138,20 @@ void Crypto::aesCbcCfb128DecryptEntry(std::span<const CryptoPP::byte, 32> ivkey,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Crypto::decryptEFSM(std::span<CryptoPP::byte, 16> NPcommID,
|
void Crypto::decryptEFSM(std::span<CryptoPP::byte, 16> trophyKey,
|
||||||
|
std::span<CryptoPP::byte, 16> NPcommID,
|
||||||
std::span<CryptoPP::byte, 16> efsmIv, std::span<CryptoPP::byte> ciphertext,
|
std::span<CryptoPP::byte, 16> efsmIv, std::span<CryptoPP::byte> ciphertext,
|
||||||
std::span<CryptoPP::byte> decrypted) {
|
std::span<CryptoPP::byte> decrypted) {
|
||||||
|
|
||||||
std::vector<CryptoPP::byte> TrophyIV = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
||||||
// step 1: Encrypt NPcommID
|
// step 1: Encrypt NPcommID
|
||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encrypt;
|
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption encrypt;
|
||||||
|
|
||||||
|
std::vector<CryptoPP::byte> trophyIv(16, 0);
|
||||||
std::vector<CryptoPP::byte> trpKey(16);
|
std::vector<CryptoPP::byte> trpKey(16);
|
||||||
|
|
||||||
|
encrypt.SetKeyWithIV(trophyKey.data(), trophyKey.size(), trophyIv.data());
|
||||||
encrypt.ProcessData(trpKey.data(), NPcommID.data(), 16);
|
encrypt.ProcessData(trpKey.data(), NPcommID.data(), 16);
|
||||||
|
|
||||||
// step 2: decrypt efsm.
|
// step 2: decrypt efsm.
|
||||||
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decrypt;
|
CryptoPP::CBC_Mode<CryptoPP::AES>::Decryption decrypt;
|
||||||
decrypt.SetKeyWithIV(trpKey.data(), trpKey.size(), efsmIv.data());
|
decrypt.SetKeyWithIV(trpKey.data(), trpKey.size(), efsmIv.data());
|
||||||
|
@ -32,7 +32,8 @@ public:
|
|||||||
void aesCbcCfb128DecryptEntry(std::span<const CryptoPP::byte, 32> ivkey,
|
void aesCbcCfb128DecryptEntry(std::span<const CryptoPP::byte, 32> ivkey,
|
||||||
std::span<CryptoPP::byte> ciphertext,
|
std::span<CryptoPP::byte> ciphertext,
|
||||||
std::span<CryptoPP::byte> decrypted);
|
std::span<CryptoPP::byte> decrypted);
|
||||||
void decryptEFSM(std::span<CryptoPP::byte, 16>, std::span<CryptoPP::byte, 16> efsmIv,
|
void decryptEFSM(std::span<CryptoPP::byte, 16> trophyKey,
|
||||||
|
std::span<CryptoPP::byte, 16> NPcommID, std::span<CryptoPP::byte, 16> efsmIv,
|
||||||
std::span<CryptoPP::byte> ciphertext, std::span<CryptoPP::byte> decrypted);
|
std::span<CryptoPP::byte> ciphertext, std::span<CryptoPP::byte> decrypted);
|
||||||
void PfsGenCryptoKey(std::span<const CryptoPP::byte, 32> ekpfs,
|
void PfsGenCryptoKey(std::span<const CryptoPP::byte, 32> ekpfs,
|
||||||
std::span<const CryptoPP::byte, 16> seed,
|
std::span<const CryptoPP::byte, 16> seed,
|
||||||
|
@ -66,7 +66,7 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) {
|
|||||||
"GetColorSliceSize()", buffer.GetColorSliceSize(),
|
"GetColorSliceSize()", buffer.GetColorSliceSize(),
|
||||||
"GetTilingMode()", buffer.GetTilingMode(),
|
"GetTilingMode()", buffer.GetTilingMode(),
|
||||||
"IsTiled()", buffer.IsTiled(),
|
"IsTiled()", buffer.IsTiled(),
|
||||||
"NumFormat()", buffer.NumFormat()
|
"NumFormat()", buffer.GetNumberFmt()
|
||||||
);
|
);
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// 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 "common/path_util.h"
|
#include "common/path_util.h"
|
||||||
#include "trp.h"
|
#include "trp.h"
|
||||||
@ -33,12 +34,29 @@ static void removePadding(std::vector<u8>& vec) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hexToBytes(const char* hex, unsigned char* dst) {
|
||||||
|
for (size_t i = 0; hex[i] != 0; i++) {
|
||||||
|
const unsigned char value = (hex[i] < 0x3A) ? (hex[i] - 0x30) : (hex[i] - 0x37);
|
||||||
|
dst[i / 2] |= ((i % 2) == 0) ? (value << 4) : (value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string titleId) {
|
bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string titleId) {
|
||||||
std::filesystem::path gameSysDir = trophyPath / "sce_sys/trophy/";
|
std::filesystem::path gameSysDir = trophyPath / "sce_sys/trophy/";
|
||||||
if (!std::filesystem::exists(gameSysDir)) {
|
if (!std::filesystem::exists(gameSysDir)) {
|
||||||
LOG_CRITICAL(Common_Filesystem, "Game sce_sys directory doesn't exist");
|
LOG_CRITICAL(Common_Filesystem, "Game sce_sys directory doesn't exist");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto user_key_str = Config::getTrophyKey();
|
||||||
|
if (user_key_str.size() != 32) {
|
||||||
|
LOG_CRITICAL(Common_Filesystem, "Trophy decryption key is not specified");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<CryptoPP::byte, 16> user_key{};
|
||||||
|
hexToBytes(user_key_str.c_str(), user_key.data());
|
||||||
|
|
||||||
for (int index = 0; const auto& it : std::filesystem::directory_iterator(gameSysDir)) {
|
for (int index = 0; const auto& it : std::filesystem::directory_iterator(gameSysDir)) {
|
||||||
if (it.is_regular_file()) {
|
if (it.is_regular_file()) {
|
||||||
GetNPcommID(trophyPath, index);
|
GetNPcommID(trophyPath, index);
|
||||||
@ -97,7 +115,7 @@ bool TRP::Extract(const std::filesystem::path& trophyPath, const std::string tit
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
file.Read(ESFM);
|
file.Read(ESFM);
|
||||||
crypto.decryptEFSM(np_comm_id, esfmIv, ESFM, XML); // decrypt
|
crypto.decryptEFSM(user_key, np_comm_id, esfmIv, ESFM, XML); // decrypt
|
||||||
removePadding(XML);
|
removePadding(XML);
|
||||||
std::string xml_name = entry.entry_name;
|
std::string xml_name = entry.entry_name;
|
||||||
size_t pos = xml_name.find("ESFM");
|
size_t pos = xml_name.find("ESFM");
|
||||||
|
@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <shared_mutex>
|
#include <stop_token>
|
||||||
|
#include <thread>
|
||||||
#include <magic_enum/magic_enum.hpp>
|
#include <magic_enum/magic_enum.hpp>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "common/polyfill_thread.h"
|
|
||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
#include "core/libraries/audio/audioout.h"
|
#include "core/libraries/audio/audioout.h"
|
||||||
#include "core/libraries/audio/audioout_backend.h"
|
#include "core/libraries/audio/audioout_backend.h"
|
||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
namespace Libraries::AudioOut {
|
namespace Libraries::AudioOut {
|
||||||
|
|
||||||
std::shared_mutex ports_mutex;
|
std::mutex port_open_mutex{};
|
||||||
std::array<PortOut, SCE_AUDIO_OUT_NUM_PORTS> ports_out{};
|
std::array<PortOut, SCE_AUDIO_OUT_NUM_PORTS> ports_out{};
|
||||||
|
|
||||||
static std::unique_ptr<AudioOutBackend> audio;
|
static std::unique_ptr<AudioOutBackend> audio;
|
||||||
@ -93,17 +93,20 @@ int PS4_SYSV_ABI sceAudioOutClose(s32 handle) {
|
|||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::scoped_lock lock(ports_mutex);
|
std::unique_lock open_lock{port_open_mutex};
|
||||||
auto& port = ports_out.at(handle - 1);
|
auto& port = ports_out.at(handle - 1);
|
||||||
if (!port.impl) {
|
{
|
||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
std::unique_lock lock{port.mutex};
|
||||||
|
if (!port.IsOpen()) {
|
||||||
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
|
}
|
||||||
|
std::free(port.output_buffer);
|
||||||
|
port.output_buffer = nullptr;
|
||||||
|
port.output_ready = false;
|
||||||
|
port.impl = nullptr;
|
||||||
}
|
}
|
||||||
|
// Stop outside of port lock scope to prevent deadlocks.
|
||||||
port.output_thread.Stop();
|
port.output_thread.Stop();
|
||||||
std::free(port.output_buffer);
|
|
||||||
port.output_buffer = nullptr;
|
|
||||||
port.output_ready = false;
|
|
||||||
port.impl = nullptr;
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,35 +175,34 @@ int PS4_SYSV_ABI sceAudioOutGetPortState(s32 handle, OrbisAudioOutPortState* sta
|
|||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::scoped_lock lock(ports_mutex);
|
auto& port = ports_out.at(handle - 1);
|
||||||
const auto& port = ports_out.at(handle - 1);
|
{
|
||||||
if (!port.impl) {
|
std::unique_lock lock{port.mutex};
|
||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
if (!port.IsOpen()) {
|
||||||
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
|
}
|
||||||
|
switch (port.type) {
|
||||||
|
case OrbisAudioOutPort::Main:
|
||||||
|
case OrbisAudioOutPort::Bgm:
|
||||||
|
case OrbisAudioOutPort::Voice:
|
||||||
|
state->output = 1;
|
||||||
|
state->channel = port.format_info.num_channels > 2 ? 2 : port.format_info.num_channels;
|
||||||
|
break;
|
||||||
|
case OrbisAudioOutPort::Personal:
|
||||||
|
case OrbisAudioOutPort::Padspk:
|
||||||
|
state->output = 4;
|
||||||
|
state->channel = 1;
|
||||||
|
break;
|
||||||
|
case OrbisAudioOutPort::Aux:
|
||||||
|
state->output = 0;
|
||||||
|
state->channel = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
state->rerouteCounter = 0;
|
||||||
|
state->volume = 127;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->rerouteCounter = 0;
|
|
||||||
state->volume = 127;
|
|
||||||
|
|
||||||
switch (port.type) {
|
|
||||||
case OrbisAudioOutPort::Main:
|
|
||||||
case OrbisAudioOutPort::Bgm:
|
|
||||||
case OrbisAudioOutPort::Voice:
|
|
||||||
state->output = 1;
|
|
||||||
state->channel = port.format_info.num_channels > 2 ? 2 : port.format_info.num_channels;
|
|
||||||
break;
|
|
||||||
case OrbisAudioOutPort::Personal:
|
|
||||||
case OrbisAudioOutPort::Padspk:
|
|
||||||
state->output = 4;
|
|
||||||
state->channel = 1;
|
|
||||||
break;
|
|
||||||
case OrbisAudioOutPort::Aux:
|
|
||||||
state->output = 0;
|
|
||||||
state->channel = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,15 +281,16 @@ static void AudioOutputThread(PortOut* port, const std::stop_token& stop) {
|
|||||||
while (true) {
|
while (true) {
|
||||||
timer.Start();
|
timer.Start();
|
||||||
{
|
{
|
||||||
std::unique_lock lock{port->output_mutex};
|
std::unique_lock lock{port->mutex};
|
||||||
Common::CondvarWait(port->output_cv, lock, stop, [&] { return port->output_ready; });
|
if (port->output_cv.wait(lock, stop, [&] { return port->output_ready; })) {
|
||||||
if (stop.stop_requested()) {
|
port->impl->Output(port->output_buffer);
|
||||||
break;
|
port->output_ready = false;
|
||||||
}
|
}
|
||||||
port->impl->Output(port->output_buffer);
|
|
||||||
port->output_ready = false;
|
|
||||||
}
|
}
|
||||||
port->output_cv.notify_one();
|
port->output_cv.notify_one();
|
||||||
|
if (stop.stop_requested()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
timer.End();
|
timer.End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -332,27 +335,30 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id,
|
|||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_FORMAT;
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::scoped_lock lock{ports_mutex};
|
std::unique_lock open_lock{port_open_mutex};
|
||||||
const auto port =
|
const auto port =
|
||||||
std::ranges::find_if(ports_out, [&](const PortOut& p) { return p.impl == nullptr; });
|
std::ranges::find_if(ports_out, [&](const PortOut& p) { return !p.IsOpen(); });
|
||||||
if (port == ports_out.end()) {
|
if (port == ports_out.end()) {
|
||||||
LOG_ERROR(Lib_AudioOut, "Audio ports are full");
|
LOG_ERROR(Lib_AudioOut, "Audio ports are full");
|
||||||
return ORBIS_AUDIO_OUT_ERROR_PORT_FULL;
|
return ORBIS_AUDIO_OUT_ERROR_PORT_FULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
port->type = port_type;
|
{
|
||||||
port->format_info = GetFormatInfo(format);
|
std::unique_lock port_lock(port->mutex);
|
||||||
port->sample_rate = sample_rate;
|
|
||||||
port->buffer_frames = length;
|
|
||||||
port->volume.fill(SCE_AUDIO_OUT_VOLUME_0DB);
|
|
||||||
|
|
||||||
port->impl = audio->Open(*port);
|
port->type = port_type;
|
||||||
|
port->format_info = GetFormatInfo(format);
|
||||||
|
port->sample_rate = sample_rate;
|
||||||
|
port->buffer_frames = length;
|
||||||
|
port->volume.fill(SCE_AUDIO_OUT_VOLUME_0DB);
|
||||||
|
|
||||||
port->output_buffer = std::malloc(port->BufferSize());
|
port->impl = audio->Open(*port);
|
||||||
port->output_ready = false;
|
|
||||||
port->output_thread.Run(
|
|
||||||
[port](const std::stop_token& stop) { AudioOutputThread(&*port, stop); });
|
|
||||||
|
|
||||||
|
port->output_buffer = std::malloc(port->BufferSize());
|
||||||
|
port->output_ready = false;
|
||||||
|
port->output_thread.Run(
|
||||||
|
[port](const std::stop_token& stop) { AudioOutputThread(&*port, stop); });
|
||||||
|
}
|
||||||
return std::distance(ports_out.begin(), port) + 1;
|
return std::distance(ports_out.begin(), port) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,14 +373,13 @@ s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, void* ptr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto& port = ports_out.at(handle - 1);
|
auto& port = ports_out.at(handle - 1);
|
||||||
if (!port.impl) {
|
|
||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
std::unique_lock lock{port.output_mutex};
|
std::unique_lock lock{port.mutex};
|
||||||
|
if (!port.IsOpen()) {
|
||||||
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
|
}
|
||||||
port.output_cv.wait(lock, [&] { return !port.output_ready; });
|
port.output_cv.wait(lock, [&] { return !port.output_ready; });
|
||||||
if (ptr != nullptr) {
|
if (ptr != nullptr && port.IsOpen()) {
|
||||||
std::memcpy(port.output_buffer, ptr, port.BufferSize());
|
std::memcpy(port.output_buffer, ptr, port.BufferSize());
|
||||||
port.output_ready = true;
|
port.output_ready = true;
|
||||||
}
|
}
|
||||||
@ -488,19 +493,19 @@ s32 PS4_SYSV_ABI sceAudioOutSetVolume(s32 handle, s32 flag, s32* vol) {
|
|||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::scoped_lock lock(ports_mutex);
|
|
||||||
auto& port = ports_out.at(handle - 1);
|
auto& port = ports_out.at(handle - 1);
|
||||||
if (!port.impl) {
|
{
|
||||||
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
std::unique_lock lock{port.mutex};
|
||||||
}
|
if (!port.IsOpen()) {
|
||||||
|
return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT;
|
||||||
for (int i = 0; i < port.format_info.num_channels; i++, flag >>= 1u) {
|
|
||||||
if (flag & 0x1u) {
|
|
||||||
port.volume[i] = vol[i];
|
|
||||||
}
|
}
|
||||||
|
for (int i = 0; i < port.format_info.num_channels; i++, flag >>= 1u) {
|
||||||
|
if (flag & 0x1u) {
|
||||||
|
port.volume[i] = vol[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
port.impl->SetVolume(port.volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
port.impl->SetVolume(port.volume);
|
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "core/libraries/kernel/threads.h"
|
#include "core/libraries/kernel/threads.h"
|
||||||
@ -74,10 +76,10 @@ struct AudioFormatInfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct PortOut {
|
struct PortOut {
|
||||||
|
std::mutex mutex;
|
||||||
std::unique_ptr<PortBackend> impl{};
|
std::unique_ptr<PortBackend> impl{};
|
||||||
|
|
||||||
void* output_buffer;
|
void* output_buffer;
|
||||||
std::mutex output_mutex;
|
|
||||||
std::condition_variable_any output_cv;
|
std::condition_variable_any output_cv;
|
||||||
bool output_ready;
|
bool output_ready;
|
||||||
Kernel::Thread output_thread{};
|
Kernel::Thread output_thread{};
|
||||||
@ -88,6 +90,10 @@ struct PortOut {
|
|||||||
u32 buffer_frames;
|
u32 buffer_frames;
|
||||||
std::array<s32, 8> volume;
|
std::array<s32, 8> volume;
|
||||||
|
|
||||||
|
[[nodiscard]] bool IsOpen() const {
|
||||||
|
return impl != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] u32 BufferSize() const {
|
[[nodiscard]] u32 BufferSize() const {
|
||||||
return buffer_frames * format_info.FrameSize();
|
return buffer_frames * format_info.FrameSize();
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ namespace Libraries::AudioOut {
|
|||||||
class SDLPortBackend : public PortBackend {
|
class SDLPortBackend : public PortBackend {
|
||||||
public:
|
public:
|
||||||
explicit SDLPortBackend(const PortOut& port)
|
explicit SDLPortBackend(const PortOut& port)
|
||||||
: frame_size(port.format_info.FrameSize()), buffer_size(port.BufferSize()) {
|
: frame_size(port.format_info.FrameSize()), guest_buffer_size(port.BufferSize()) {
|
||||||
// We want the latency for delivering frames out to be as small as possible,
|
// We want the latency for delivering frames out to be as small as possible,
|
||||||
// so set the sample frames hint to the number of frames per buffer.
|
// so set the sample frames hint to the number of frames per buffer.
|
||||||
const auto samples_num_str = std::to_string(port.buffer_frames);
|
const auto samples_num_str = std::to_string(port.buffer_frames);
|
||||||
@ -33,7 +33,7 @@ public:
|
|||||||
LOG_ERROR(Lib_AudioOut, "Failed to create SDL audio stream: {}", SDL_GetError());
|
LOG_ERROR(Lib_AudioOut, "Failed to create SDL audio stream: {}", SDL_GetError());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
queue_threshold = CalculateQueueThreshold();
|
CalculateQueueThreshold();
|
||||||
if (!SDL_SetAudioStreamInputChannelMap(stream, port.format_info.channel_layout.data(),
|
if (!SDL_SetAudioStreamInputChannelMap(stream, port.format_info.channel_layout.data(),
|
||||||
port.format_info.num_channels)) {
|
port.format_info.num_channels)) {
|
||||||
LOG_ERROR(Lib_AudioOut, "Failed to configure SDL audio stream channel map: {}",
|
LOG_ERROR(Lib_AudioOut, "Failed to configure SDL audio stream channel map: {}",
|
||||||
@ -71,9 +71,9 @@ public:
|
|||||||
queue_threshold);
|
queue_threshold);
|
||||||
SDL_ClearAudioStream(stream);
|
SDL_ClearAudioStream(stream);
|
||||||
// Recalculate the threshold in case this happened because of a device change.
|
// Recalculate the threshold in case this happened because of a device change.
|
||||||
queue_threshold = CalculateQueueThreshold();
|
CalculateQueueThreshold();
|
||||||
}
|
}
|
||||||
if (!SDL_PutAudioStreamData(stream, ptr, static_cast<int>(buffer_size))) {
|
if (!SDL_PutAudioStreamData(stream, ptr, static_cast<int>(guest_buffer_size))) {
|
||||||
LOG_ERROR(Lib_AudioOut, "Failed to output to SDL audio stream: {}", SDL_GetError());
|
LOG_ERROR(Lib_AudioOut, "Failed to output to SDL audio stream: {}", SDL_GetError());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] u32 CalculateQueueThreshold() const {
|
void CalculateQueueThreshold() {
|
||||||
SDL_AudioSpec discard;
|
SDL_AudioSpec discard;
|
||||||
int sdl_buffer_frames;
|
int sdl_buffer_frames;
|
||||||
if (!SDL_GetAudioDeviceFormat(SDL_GetAudioStreamDevice(stream), &discard,
|
if (!SDL_GetAudioDeviceFormat(SDL_GetAudioStreamDevice(stream), &discard,
|
||||||
@ -100,13 +100,22 @@ private:
|
|||||||
SDL_GetError());
|
SDL_GetError());
|
||||||
sdl_buffer_frames = 0;
|
sdl_buffer_frames = 0;
|
||||||
}
|
}
|
||||||
return std::max<u32>(buffer_size, sdl_buffer_frames * frame_size) * 4;
|
const auto sdl_buffer_size = sdl_buffer_frames * frame_size;
|
||||||
|
const auto new_threshold = std::max(guest_buffer_size, sdl_buffer_size) * 4;
|
||||||
|
if (host_buffer_size != sdl_buffer_size || queue_threshold != new_threshold) {
|
||||||
|
host_buffer_size = sdl_buffer_size;
|
||||||
|
queue_threshold = new_threshold;
|
||||||
|
LOG_INFO(Lib_AudioOut,
|
||||||
|
"SDL audio buffers: guest = {} bytes, host = {} bytes, threshold = {} bytes",
|
||||||
|
guest_buffer_size, host_buffer_size, queue_threshold);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 frame_size;
|
u32 frame_size;
|
||||||
u32 buffer_size;
|
u32 guest_buffer_size;
|
||||||
u32 queue_threshold;
|
u32 host_buffer_size{};
|
||||||
SDL_AudioStream* stream;
|
u32 queue_threshold{};
|
||||||
|
SDL_AudioStream* stream{};
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<PortBackend> SDLAudioOut::Open(PortOut& port) {
|
std::unique_ptr<PortBackend> SDLAudioOut::Open(PortOut& port) {
|
||||||
|
@ -505,6 +505,41 @@ int PS4_SYSV_ABI posix_munmap(void* addr, size_t len) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr int MAX_PRT_APERTURES = 3;
|
||||||
|
static constexpr VAddr PRT_AREA_START_ADDR = 0x1000000000;
|
||||||
|
static constexpr size_t PRT_AREA_SIZE = 0xec00000000;
|
||||||
|
static std::array<std::pair<VAddr, size_t>, MAX_PRT_APERTURES> PrtApertures{};
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI sceKernelSetPrtAperture(int id, VAddr address, size_t size) {
|
||||||
|
if (id < 0 || id >= MAX_PRT_APERTURES) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (address < PRT_AREA_START_ADDR || address + size > PRT_AREA_START_ADDR + PRT_AREA_SIZE) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (address % 4096 != 0) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_WARNING(Kernel_Vmm,
|
||||||
|
"PRT aperture id = {}, address = {:#x}, size = {:#x} is set but not used", id,
|
||||||
|
address, size);
|
||||||
|
|
||||||
|
PrtApertures[id] = {address, size};
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PS4_SYSV_ABI sceKernelGetPrtAperture(int id, VAddr* address, size_t* size) {
|
||||||
|
if (id < 0 || id >= MAX_PRT_APERTURES) {
|
||||||
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::tie(*address, *size) = PrtApertures[id];
|
||||||
|
return ORBIS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterMemory(Core::Loader::SymbolsResolver* sym) {
|
void RegisterMemory(Core::Loader::SymbolsResolver* sym) {
|
||||||
LIB_FUNCTION("rTXw65xmLIA", "libkernel", 1, "libkernel", 1, 1, sceKernelAllocateDirectMemory);
|
LIB_FUNCTION("rTXw65xmLIA", "libkernel", 1, "libkernel", 1, 1, sceKernelAllocateDirectMemory);
|
||||||
LIB_FUNCTION("B+vc2AO2Zrc", "libkernel", 1, "libkernel", 1, 1,
|
LIB_FUNCTION("B+vc2AO2Zrc", "libkernel", 1, "libkernel", 1, 1,
|
||||||
@ -551,6 +586,10 @@ void RegisterMemory(Core::Loader::SymbolsResolver* sym) {
|
|||||||
LIB_FUNCTION("BPE9s9vQQXo", "libScePosix", 1, "libkernel", 1, 1, posix_mmap);
|
LIB_FUNCTION("BPE9s9vQQXo", "libScePosix", 1, "libkernel", 1, 1, posix_mmap);
|
||||||
LIB_FUNCTION("UqDGjXA5yUM", "libkernel", 1, "libkernel", 1, 1, posix_munmap);
|
LIB_FUNCTION("UqDGjXA5yUM", "libkernel", 1, "libkernel", 1, 1, posix_munmap);
|
||||||
LIB_FUNCTION("UqDGjXA5yUM", "libScePosix", 1, "libkernel", 1, 1, posix_munmap);
|
LIB_FUNCTION("UqDGjXA5yUM", "libScePosix", 1, "libkernel", 1, 1, posix_munmap);
|
||||||
|
|
||||||
|
// PRT memory management
|
||||||
|
LIB_FUNCTION("BohYr-F7-is", "libkernel", 1, "libkernel", 1, 1, sceKernelSetPrtAperture);
|
||||||
|
LIB_FUNCTION("L0v2Go5jOuM", "libkernel", 1, "libkernel", 1, 1, sceKernelGetPrtAperture);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries::Kernel
|
} // namespace Libraries::Kernel
|
||||||
|
@ -55,6 +55,9 @@ public:
|
|||||||
stop.request_stop();
|
stop.request_stop();
|
||||||
Join();
|
Join();
|
||||||
}
|
}
|
||||||
|
thread = nullptr;
|
||||||
|
func = nullptr;
|
||||||
|
stop = std::stop_source{};
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* PS4_SYSV_ABI RunWrapper(void* arg) {
|
static void* PS4_SYSV_ABI RunWrapper(void* arg) {
|
||||||
|
@ -47,6 +47,8 @@
|
|||||||
#include "core/libraries/videodec/videodec.h"
|
#include "core/libraries/videodec/videodec.h"
|
||||||
#include "core/libraries/videodec/videodec2.h"
|
#include "core/libraries/videodec/videodec2.h"
|
||||||
#include "core/libraries/videoout/video_out.h"
|
#include "core/libraries/videoout/video_out.h"
|
||||||
|
#include "fiber/fiber.h"
|
||||||
|
#include "jpeg/jpegenc.h"
|
||||||
|
|
||||||
namespace Libraries {
|
namespace Libraries {
|
||||||
|
|
||||||
@ -93,6 +95,8 @@ void InitHLELibs(Core::Loader::SymbolsResolver* sym) {
|
|||||||
Libraries::Videodec::RegisterlibSceVideodec(sym);
|
Libraries::Videodec::RegisterlibSceVideodec(sym);
|
||||||
Libraries::RazorCpu::RegisterlibSceRazorCpu(sym);
|
Libraries::RazorCpu::RegisterlibSceRazorCpu(sym);
|
||||||
Libraries::Move::RegisterlibSceMove(sym);
|
Libraries::Move::RegisterlibSceMove(sym);
|
||||||
|
Libraries::Fiber::RegisterlibSceFiber(sym);
|
||||||
|
Libraries::JpegEnc::RegisterlibSceJpegEnc(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libraries
|
} // namespace Libraries
|
||||||
|
@ -972,11 +972,8 @@ int PS4_SYSV_ABI sceNpGetGamePresenceStatusA() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId user_id, OrbisNpId* np_id) {
|
int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId user_id, OrbisNpId* np_id) {
|
||||||
LOG_INFO(Lib_NpManager, "user_id {}", user_id);
|
LOG_DEBUG(Lib_NpManager, "user_id {}", user_id);
|
||||||
const auto name = Config::getUserName();
|
return ORBIS_NP_ERROR_SIGNED_OUT;
|
||||||
std::memset(np_id, 0, sizeof(OrbisNpId));
|
|
||||||
name.copy(np_id->handle.data, sizeof(np_id->handle.data));
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNpGetNpReachabilityState() {
|
int PS4_SYSV_ABI sceNpGetNpReachabilityState() {
|
||||||
@ -986,10 +983,7 @@ int PS4_SYSV_ABI sceNpGetNpReachabilityState() {
|
|||||||
|
|
||||||
int PS4_SYSV_ABI sceNpGetOnlineId(s32 user_id, OrbisNpOnlineId* online_id) {
|
int PS4_SYSV_ABI sceNpGetOnlineId(s32 user_id, OrbisNpOnlineId* online_id) {
|
||||||
LOG_DEBUG(Lib_NpManager, "user_id {}", user_id);
|
LOG_DEBUG(Lib_NpManager, "user_id {}", user_id);
|
||||||
const auto name = Config::getUserName();
|
return ORBIS_NP_ERROR_SIGNED_OUT;
|
||||||
std::memset(online_id, 0, sizeof(OrbisNpOnlineId));
|
|
||||||
name.copy(online_id->data, sizeof(online_id->data));
|
|
||||||
return ORBIS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceNpGetParentalControlInfo() {
|
int PS4_SYSV_ABI sceNpGetParentalControlInfo() {
|
||||||
|
@ -286,6 +286,7 @@ int PS4_SYSV_ABI scePadOutputReport() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) {
|
int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) {
|
||||||
|
LOG_TRACE(Lib_Pad, "called");
|
||||||
int connected_count = 0;
|
int connected_count = 0;
|
||||||
bool connected = false;
|
bool connected = false;
|
||||||
Input::State states[64];
|
Input::State states[64];
|
||||||
@ -304,16 +305,15 @@ int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) {
|
|||||||
pData[i].rightStick.y = states[i].axes[static_cast<int>(Input::Axis::RightY)];
|
pData[i].rightStick.y = states[i].axes[static_cast<int>(Input::Axis::RightY)];
|
||||||
pData[i].analogButtons.l2 = states[i].axes[static_cast<int>(Input::Axis::TriggerLeft)];
|
pData[i].analogButtons.l2 = states[i].axes[static_cast<int>(Input::Axis::TriggerLeft)];
|
||||||
pData[i].analogButtons.r2 = states[i].axes[static_cast<int>(Input::Axis::TriggerRight)];
|
pData[i].analogButtons.r2 = states[i].axes[static_cast<int>(Input::Axis::TriggerRight)];
|
||||||
pData[i].orientation.x = 0.0f;
|
pData[i].acceleration.x = states[i].acceleration.x;
|
||||||
pData[i].orientation.y = 0.0f;
|
pData[i].acceleration.y = states[i].acceleration.y;
|
||||||
pData[i].orientation.z = 0.0f;
|
pData[i].acceleration.z = states[i].acceleration.z;
|
||||||
pData[i].orientation.w = 1.0f;
|
pData[i].angularVelocity.x = states[i].angularVelocity.x;
|
||||||
pData[i].acceleration.x = 0.0f;
|
pData[i].angularVelocity.y = states[i].angularVelocity.y;
|
||||||
pData[i].acceleration.y = 0.0f;
|
pData[i].angularVelocity.z = states[i].angularVelocity.z;
|
||||||
pData[i].acceleration.z = 0.0f;
|
Input::GameController::CalculateOrientation(pData[i].acceleration, pData[i].angularVelocity,
|
||||||
pData[i].angularVelocity.x = 0.0f;
|
1.0f / controller->accel_poll_rate,
|
||||||
pData[i].angularVelocity.y = 0.0f;
|
pData[i].orientation);
|
||||||
pData[i].angularVelocity.z = 0.0f;
|
|
||||||
pData[i].touchData.touchNum =
|
pData[i].touchData.touchNum =
|
||||||
(states[i].touchpad[0].state ? 1 : 0) + (states[i].touchpad[1].state ? 1 : 0);
|
(states[i].touchpad[0].state ? 1 : 0) + (states[i].touchpad[1].state ? 1 : 0);
|
||||||
pData[i].touchData.touch[0].x = states[i].touchpad[0].x;
|
pData[i].touchData.touch[0].x = states[i].touchpad[0].x;
|
||||||
@ -352,6 +352,7 @@ int PS4_SYSV_ABI scePadReadHistory() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) {
|
int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) {
|
||||||
|
LOG_TRACE(Lib_Pad, "called");
|
||||||
if (handle == ORBIS_PAD_ERROR_DEVICE_NO_HANDLE) {
|
if (handle == ORBIS_PAD_ERROR_DEVICE_NO_HANDLE) {
|
||||||
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
return ORBIS_PAD_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
@ -367,16 +368,15 @@ int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) {
|
|||||||
pData->rightStick.y = state.axes[static_cast<int>(Input::Axis::RightY)];
|
pData->rightStick.y = state.axes[static_cast<int>(Input::Axis::RightY)];
|
||||||
pData->analogButtons.l2 = state.axes[static_cast<int>(Input::Axis::TriggerLeft)];
|
pData->analogButtons.l2 = state.axes[static_cast<int>(Input::Axis::TriggerLeft)];
|
||||||
pData->analogButtons.r2 = state.axes[static_cast<int>(Input::Axis::TriggerRight)];
|
pData->analogButtons.r2 = state.axes[static_cast<int>(Input::Axis::TriggerRight)];
|
||||||
pData->orientation.x = 0;
|
pData->acceleration.x = state.acceleration.x;
|
||||||
pData->orientation.y = 0;
|
pData->acceleration.y = state.acceleration.y;
|
||||||
pData->orientation.z = 0;
|
pData->acceleration.z = state.acceleration.z;
|
||||||
pData->orientation.w = 1;
|
pData->angularVelocity.x = state.angularVelocity.x;
|
||||||
pData->acceleration.x = 0.0f;
|
pData->angularVelocity.y = state.angularVelocity.y;
|
||||||
pData->acceleration.y = 0.0f;
|
pData->angularVelocity.z = state.angularVelocity.z;
|
||||||
pData->acceleration.z = 0.0f;
|
Input::GameController::CalculateOrientation(pData->acceleration, pData->angularVelocity,
|
||||||
pData->angularVelocity.x = 0.0f;
|
1.0f / controller->accel_poll_rate,
|
||||||
pData->angularVelocity.y = 0.0f;
|
pData->orientation);
|
||||||
pData->angularVelocity.z = 0.0f;
|
|
||||||
pData->touchData.touchNum =
|
pData->touchData.touchNum =
|
||||||
(state.touchpad[0].state ? 1 : 0) + (state.touchpad[1].state ? 1 : 0);
|
(state.touchpad[0].state ? 1 : 0) + (state.touchpad[1].state ? 1 : 0);
|
||||||
pData->touchData.touch[0].x = state.touchpad[0].x;
|
pData->touchData.touch[0].x = state.touchpad[0].x;
|
||||||
@ -498,6 +498,8 @@ int PS4_SYSV_ABI scePadSetLoginUserNumber() {
|
|||||||
int PS4_SYSV_ABI scePadSetMotionSensorState(s32 handle, bool bEnable) {
|
int PS4_SYSV_ABI scePadSetMotionSensorState(s32 handle, bool bEnable) {
|
||||||
LOG_ERROR(Lib_Pad, "(STUBBED) called");
|
LOG_ERROR(Lib_Pad, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
|
// it's already handled by the SDL backend and will be on no matter what
|
||||||
|
// (assuming the controller supports it)
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI scePadSetProcessFocus() {
|
int PS4_SYSV_ABI scePadSetProcessFocus() {
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <span>
|
#include <span>
|
||||||
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <core/libraries/system/msgdialog_ui.h>
|
#include <core/libraries/system/msgdialog_ui.h>
|
||||||
@ -1139,10 +1140,6 @@ Error PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getPar
|
|||||||
LOG_INFO(Lib_SaveData, "called without save memory initialized");
|
LOG_INFO(Lib_SaveData, "called without save memory initialized");
|
||||||
return Error::MEMORY_NOT_READY;
|
return Error::MEMORY_NOT_READY;
|
||||||
}
|
}
|
||||||
if (SaveMemory::IsSaving()) {
|
|
||||||
LOG_TRACE(Lib_SaveData, "called while saving");
|
|
||||||
return Error::BUSY_FOR_SAVING;
|
|
||||||
}
|
|
||||||
LOG_DEBUG(Lib_SaveData, "called");
|
LOG_DEBUG(Lib_SaveData, "called");
|
||||||
auto data = getParam->data;
|
auto data = getParam->data;
|
||||||
if (data != nullptr) {
|
if (data != nullptr) {
|
||||||
@ -1502,8 +1499,14 @@ Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2*
|
|||||||
return Error::MEMORY_NOT_READY;
|
return Error::MEMORY_NOT_READY;
|
||||||
}
|
}
|
||||||
if (SaveMemory::IsSaving()) {
|
if (SaveMemory::IsSaving()) {
|
||||||
LOG_TRACE(Lib_SaveData, "called while saving");
|
int count = 0;
|
||||||
return Error::BUSY_FOR_SAVING;
|
while (++count < 100 && SaveMemory::IsSaving()) { // try for more 10 seconds
|
||||||
|
std::this_thread::sleep_for(chrono::milliseconds(100));
|
||||||
|
}
|
||||||
|
if (SaveMemory::IsSaving()) {
|
||||||
|
LOG_TRACE(Lib_SaveData, "called while saving");
|
||||||
|
return Error::BUSY_FOR_SAVING;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LOG_DEBUG(Lib_SaveData, "called");
|
LOG_DEBUG(Lib_SaveData, "called");
|
||||||
auto data = setParam->data;
|
auto data = setParam->data;
|
||||||
@ -1584,8 +1587,8 @@ Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetu
|
|||||||
} else {
|
} else {
|
||||||
SaveMemory::SetIcon(nullptr, 0);
|
SaveMemory::SetIcon(nullptr, 0);
|
||||||
}
|
}
|
||||||
|
SaveMemory::TriggerSaveWithoutEvent();
|
||||||
}
|
}
|
||||||
SaveMemory::TriggerSaveWithoutEvent();
|
|
||||||
if (g_fw_ver >= ElfInfo::FW_45 && result != nullptr) {
|
if (g_fw_ver >= ElfInfo::FW_45 && result != nullptr) {
|
||||||
result->existedMemorySize = existed_size;
|
result->existedMemorySize = existed_size;
|
||||||
}
|
}
|
||||||
|
@ -10,327 +10,327 @@
|
|||||||
namespace Libraries::Usbd {
|
namespace Libraries::Usbd {
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdAllocTransfer() {
|
int PS4_SYSV_ABI sceUsbdAllocTransfer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdAttachKernelDriver() {
|
int PS4_SYSV_ABI sceUsbdAttachKernelDriver() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdBulkTransfer() {
|
int PS4_SYSV_ABI sceUsbdBulkTransfer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdCancelTransfer() {
|
int PS4_SYSV_ABI sceUsbdCancelTransfer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdCheckConnected() {
|
int PS4_SYSV_ABI sceUsbdCheckConnected() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdClaimInterface() {
|
int PS4_SYSV_ABI sceUsbdClaimInterface() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdClearHalt() {
|
int PS4_SYSV_ABI sceUsbdClearHalt() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdClose() {
|
int PS4_SYSV_ABI sceUsbdClose() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdControlTransfer() {
|
int PS4_SYSV_ABI sceUsbdControlTransfer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdControlTransferGetData() {
|
int PS4_SYSV_ABI sceUsbdControlTransferGetData() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdControlTransferGetSetup() {
|
int PS4_SYSV_ABI sceUsbdControlTransferGetSetup() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdDetachKernelDriver() {
|
int PS4_SYSV_ABI sceUsbdDetachKernelDriver() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdEventHandlerActive() {
|
int PS4_SYSV_ABI sceUsbdEventHandlerActive() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdEventHandlingOk() {
|
int PS4_SYSV_ABI sceUsbdEventHandlingOk() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdExit() {
|
int PS4_SYSV_ABI sceUsbdExit() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdFillBulkTransfer() {
|
int PS4_SYSV_ABI sceUsbdFillBulkTransfer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdFillControlSetup() {
|
int PS4_SYSV_ABI sceUsbdFillControlSetup() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdFillControlTransfer() {
|
int PS4_SYSV_ABI sceUsbdFillControlTransfer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdFillInterruptTransfer() {
|
int PS4_SYSV_ABI sceUsbdFillInterruptTransfer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdFillIsoTransfer() {
|
int PS4_SYSV_ABI sceUsbdFillIsoTransfer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdFreeConfigDescriptor() {
|
int PS4_SYSV_ABI sceUsbdFreeConfigDescriptor() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdFreeDeviceList() {
|
int PS4_SYSV_ABI sceUsbdFreeDeviceList() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdFreeTransfer() {
|
int PS4_SYSV_ABI sceUsbdFreeTransfer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor() {
|
int PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetBusNumber() {
|
int PS4_SYSV_ABI sceUsbdGetBusNumber() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetConfigDescriptor() {
|
int PS4_SYSV_ABI sceUsbdGetConfigDescriptor() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue() {
|
int PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetConfiguration() {
|
int PS4_SYSV_ABI sceUsbdGetConfiguration() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetDescriptor() {
|
int PS4_SYSV_ABI sceUsbdGetDescriptor() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetDevice() {
|
int PS4_SYSV_ABI sceUsbdGetDevice() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetDeviceAddress() {
|
int PS4_SYSV_ABI sceUsbdGetDeviceAddress() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetDeviceDescriptor() {
|
int PS4_SYSV_ABI sceUsbdGetDeviceDescriptor() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetDeviceList() {
|
int PS4_SYSV_ABI sceUsbdGetDeviceList() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetDeviceSpeed() {
|
int PS4_SYSV_ABI sceUsbdGetDeviceSpeed() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer() {
|
int PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize() {
|
int PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetMaxPacketSize() {
|
int PS4_SYSV_ABI sceUsbdGetMaxPacketSize() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetStringDescriptor() {
|
int PS4_SYSV_ABI sceUsbdGetStringDescriptor() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii() {
|
int PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdHandleEvents() {
|
int PS4_SYSV_ABI sceUsbdHandleEvents() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdHandleEventsLocked() {
|
int PS4_SYSV_ABI sceUsbdHandleEventsLocked() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdHandleEventsTimeout() {
|
int PS4_SYSV_ABI sceUsbdHandleEventsTimeout() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_DEBUG(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdInit() {
|
int PS4_SYSV_ABI sceUsbdInit() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return 0x80240005; // Skip
|
return 0x80240005; // Skip
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdInterruptTransfer() {
|
int PS4_SYSV_ABI sceUsbdInterruptTransfer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdKernelDriverActive() {
|
int PS4_SYSV_ABI sceUsbdKernelDriverActive() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdLockEvents() {
|
int PS4_SYSV_ABI sceUsbdLockEvents() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdLockEventWaiters() {
|
int PS4_SYSV_ABI sceUsbdLockEventWaiters() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdOpen() {
|
int PS4_SYSV_ABI sceUsbdOpen() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid() {
|
int PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdRefDevice() {
|
int PS4_SYSV_ABI sceUsbdRefDevice() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdReleaseInterface() {
|
int PS4_SYSV_ABI sceUsbdReleaseInterface() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdResetDevice() {
|
int PS4_SYSV_ABI sceUsbdResetDevice() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdSetConfiguration() {
|
int PS4_SYSV_ABI sceUsbdSetConfiguration() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting() {
|
int PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdSetIsoPacketLengths() {
|
int PS4_SYSV_ABI sceUsbdSetIsoPacketLengths() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdSubmitTransfer() {
|
int PS4_SYSV_ABI sceUsbdSubmitTransfer() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdTryLockEvents() {
|
int PS4_SYSV_ABI sceUsbdTryLockEvents() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdUnlockEvents() {
|
int PS4_SYSV_ABI sceUsbdUnlockEvents() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdUnlockEventWaiters() {
|
int PS4_SYSV_ABI sceUsbdUnlockEventWaiters() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdUnrefDevice() {
|
int PS4_SYSV_ABI sceUsbdUnrefDevice() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceUsbdWaitForEvent() {
|
int PS4_SYSV_ABI sceUsbdWaitForEvent() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI Func_65F6EF33E38FFF50() {
|
int PS4_SYSV_ABI Func_65F6EF33E38FFF50() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI Func_97F056BAD90AADE7() {
|
int PS4_SYSV_ABI Func_97F056BAD90AADE7() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI Func_C55104A33B35B264() {
|
int PS4_SYSV_ABI Func_C55104A33B35B264() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI Func_D56B43060720B1E0() {
|
int PS4_SYSV_ABI Func_D56B43060720B1E0() {
|
||||||
LOG_ERROR(Lib_Usbd, "(STUBBED)called");
|
LOG_ERROR(Lib_Usbd, "(STUBBED) called");
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,8 +52,7 @@ s32 PS4_SYSV_ABI sceVideoOutAddFlipEvent(Kernel::SceKernelEqueue eq, s32 handle,
|
|||||||
Kernel::EqueueEvent event{};
|
Kernel::EqueueEvent event{};
|
||||||
event.event.ident = u64(OrbisVideoOutEventId::Flip);
|
event.event.ident = u64(OrbisVideoOutEventId::Flip);
|
||||||
event.event.filter = Kernel::SceKernelEvent::Filter::VideoOut;
|
event.event.filter = Kernel::SceKernelEvent::Filter::VideoOut;
|
||||||
// The library only sets EV_ADD but kernel driver forces EV_CLEAR
|
event.event.flags = Kernel::SceKernelEvent::Flags::Add;
|
||||||
event.event.flags = Kernel::SceKernelEvent::Flags::Clear;
|
|
||||||
event.event.udata = udata;
|
event.event.udata = udata;
|
||||||
event.event.fflags = 0;
|
event.event.fflags = 0;
|
||||||
event.event.data = 0;
|
event.event.data = 0;
|
||||||
@ -79,8 +78,7 @@ s32 PS4_SYSV_ABI sceVideoOutAddVblankEvent(Kernel::SceKernelEqueue eq, s32 handl
|
|||||||
Kernel::EqueueEvent event{};
|
Kernel::EqueueEvent event{};
|
||||||
event.event.ident = u64(OrbisVideoOutEventId::Vblank);
|
event.event.ident = u64(OrbisVideoOutEventId::Vblank);
|
||||||
event.event.filter = Kernel::SceKernelEvent::Filter::VideoOut;
|
event.event.filter = Kernel::SceKernelEvent::Filter::VideoOut;
|
||||||
// The library only sets EV_ADD but kernel driver forces EV_CLEAR
|
event.event.flags = Kernel::SceKernelEvent::Flags::Add;
|
||||||
event.event.flags = Kernel::SceKernelEvent::Flags::Clear;
|
|
||||||
event.event.udata = udata;
|
event.event.udata = udata;
|
||||||
event.event.fflags = 0;
|
event.event.fflags = 0;
|
||||||
event.event.data = 0;
|
event.event.data = 0;
|
||||||
|
@ -282,16 +282,14 @@ void Emulator::Run(const std::filesystem::path& file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string game_serial) {
|
void Emulator::LoadSystemModules(const std::filesystem::path& file, std::string game_serial) {
|
||||||
constexpr std::array<SysModules, 13> ModulesToLoad{
|
constexpr std::array<SysModules, 11> ModulesToLoad{
|
||||||
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
|
{{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2},
|
||||||
{"libSceFiber.sprx", &Libraries::Fiber::RegisterlibSceFiber},
|
|
||||||
{"libSceUlt.sprx", nullptr},
|
{"libSceUlt.sprx", nullptr},
|
||||||
{"libSceJson.sprx", nullptr},
|
{"libSceJson.sprx", nullptr},
|
||||||
{"libSceJson2.sprx", nullptr},
|
{"libSceJson2.sprx", nullptr},
|
||||||
{"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterlibSceLibcInternal},
|
{"libSceLibcInternal.sprx", &Libraries::LibcInternal::RegisterlibSceLibcInternal},
|
||||||
{"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap},
|
{"libSceDiscMap.sprx", &Libraries::DiscMap::RegisterlibSceDiscMap},
|
||||||
{"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc},
|
{"libSceRtc.sprx", &Libraries::Rtc::RegisterlibSceRtc},
|
||||||
{"libSceJpegEnc.sprx", &Libraries::JpegEnc::RegisterlibSceJpegEnc},
|
|
||||||
{"libSceCesCs.sprx", nullptr},
|
{"libSceCesCs.sprx", nullptr},
|
||||||
{"libSceFont.sprx", nullptr},
|
{"libSceFont.sprx", nullptr},
|
||||||
{"libSceFontFt.sprx", nullptr},
|
{"libSceFontFt.sprx", nullptr},
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <SDL3/SDL.h>
|
#include <SDL3/SDL.h>
|
||||||
|
#include "common/logging/log.h"
|
||||||
#include "core/libraries/kernel/time.h"
|
#include "core/libraries/kernel/time.h"
|
||||||
#include "core/libraries/pad/pad.h"
|
#include "core/libraries/pad/pad.h"
|
||||||
#include "input/controller.h"
|
#include "input/controller.h"
|
||||||
@ -116,6 +117,103 @@ void GameController::Axis(int id, Input::Axis axis, int value) {
|
|||||||
AddState(state);
|
AddState(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameController::Gyro(int id, const float gyro[3]) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
|
auto state = GetLastState();
|
||||||
|
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||||
|
|
||||||
|
// Update the angular velocity (gyro data)
|
||||||
|
state.angularVelocity.x = gyro[0]; // X-axis
|
||||||
|
state.angularVelocity.y = gyro[1]; // Y-axis
|
||||||
|
state.angularVelocity.z = gyro[2]; // Z-axis
|
||||||
|
|
||||||
|
AddState(state);
|
||||||
|
}
|
||||||
|
void GameController::Acceleration(int id, const float acceleration[3]) {
|
||||||
|
std::scoped_lock lock{m_mutex};
|
||||||
|
auto state = GetLastState();
|
||||||
|
state.time = Libraries::Kernel::sceKernelGetProcessTime();
|
||||||
|
|
||||||
|
// Update the acceleration values
|
||||||
|
state.acceleration.x = acceleration[0]; // X-axis
|
||||||
|
state.acceleration.y = acceleration[1]; // Y-axis
|
||||||
|
state.acceleration.z = acceleration[2]; // Z-axis
|
||||||
|
|
||||||
|
AddState(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stolen from
|
||||||
|
// https://github.com/xioTechnologies/Open-Source-AHRS-With-x-IMU/blob/master/x-IMU%20IMU%20and%20AHRS%20Algorithms/x-IMU%20IMU%20and%20AHRS%20Algorithms/AHRS/MahonyAHRS.cs
|
||||||
|
float eInt[3] = {0.0f, 0.0f, 0.0f}; // Integral error terms
|
||||||
|
const float Kp = 50.0f; // Proportional gain
|
||||||
|
const float Ki = 1.0f; // Integral gain
|
||||||
|
Libraries::Pad::OrbisFQuaternion o = {1, 0, 0, 0};
|
||||||
|
void GameController::CalculateOrientation(Libraries::Pad::OrbisFVector3& acceleration,
|
||||||
|
Libraries::Pad::OrbisFVector3& angularVelocity,
|
||||||
|
float deltaTime,
|
||||||
|
Libraries::Pad::OrbisFQuaternion& orientation) {
|
||||||
|
float ax = acceleration.x, ay = acceleration.y, az = acceleration.z;
|
||||||
|
float gx = angularVelocity.x, gy = angularVelocity.y, gz = angularVelocity.z;
|
||||||
|
|
||||||
|
float q1 = o.w, q2 = o.x, q3 = o.y, q4 = o.z;
|
||||||
|
|
||||||
|
// Normalize accelerometer measurement
|
||||||
|
float norm = std::sqrt(ax * ax + ay * ay + az * az);
|
||||||
|
if (norm == 0.0f)
|
||||||
|
return; // Handle NaN
|
||||||
|
norm = 1.0f / norm;
|
||||||
|
ax *= norm;
|
||||||
|
ay *= norm;
|
||||||
|
az *= norm;
|
||||||
|
|
||||||
|
// Estimated direction of gravity
|
||||||
|
float vx = 2.0f * (q2 * q4 - q1 * q3);
|
||||||
|
float vy = 2.0f * (q1 * q2 + q3 * q4);
|
||||||
|
float vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4;
|
||||||
|
|
||||||
|
// Error is cross product between estimated direction and measured direction of gravity
|
||||||
|
float ex = (ay * vz - az * vy);
|
||||||
|
float ey = (az * vx - ax * vz);
|
||||||
|
float ez = (ax * vy - ay * vx);
|
||||||
|
if (Ki > 0.0f) {
|
||||||
|
eInt[0] += ex * deltaTime; // Accumulate integral error
|
||||||
|
eInt[1] += ey * deltaTime;
|
||||||
|
eInt[2] += ez * deltaTime;
|
||||||
|
} else {
|
||||||
|
eInt[0] = eInt[1] = eInt[2] = 0.0f; // Prevent integral wind-up
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply feedback terms
|
||||||
|
gx += Kp * ex + Ki * eInt[0];
|
||||||
|
gy += Kp * ey + Ki * eInt[1];
|
||||||
|
gz += Kp * ez + Ki * eInt[2];
|
||||||
|
|
||||||
|
//// Integrate rate of change of quaternion
|
||||||
|
// float pa = q2, pb = q3, pc = q4;
|
||||||
|
// q1 += (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * deltaTime);
|
||||||
|
// q2 += (pa * gx + pb * gz - pc * gy) * (0.5f * deltaTime);
|
||||||
|
// q3 += (pb * gy - pa * gz + pc * gx) * (0.5f * deltaTime);
|
||||||
|
// q4 += (pc * gz + pa * gy - pb * gx) * (0.5f * deltaTime);
|
||||||
|
q1 += (-q2 * gx - q3 * gy - q4 * gz) * (0.5f * deltaTime);
|
||||||
|
q2 += (q1 * gx + q3 * gz - q4 * gy) * (0.5f * deltaTime);
|
||||||
|
q3 += (q1 * gy - q2 * gz + q4 * gx) * (0.5f * deltaTime);
|
||||||
|
q4 += (q1 * gz + q2 * gy - q3 * gx) * (0.5f * deltaTime);
|
||||||
|
|
||||||
|
// Normalize quaternion
|
||||||
|
norm = std::sqrt(q1 * q1 + q2 * q2 + q3 * q3 + q4 * q4);
|
||||||
|
norm = 1.0f / norm;
|
||||||
|
orientation.w = q1 * norm;
|
||||||
|
orientation.x = q2 * norm;
|
||||||
|
orientation.y = q3 * norm;
|
||||||
|
orientation.z = q4 * norm;
|
||||||
|
o.w = q1 * norm;
|
||||||
|
o.x = q2 * norm;
|
||||||
|
o.y = q3 * norm;
|
||||||
|
o.z = q4 * norm;
|
||||||
|
LOG_DEBUG(Lib_Pad, "Calculated orientation: {:.2f} {:.2f} {:.2f} {:.2f}", orientation.x,
|
||||||
|
orientation.y, orientation.z, orientation.w);
|
||||||
|
}
|
||||||
|
|
||||||
void GameController::SetLightBarRGB(u8 r, u8 g, u8 b) {
|
void GameController::SetLightBarRGB(u8 r, u8 g, u8 b) {
|
||||||
if (m_sdl_gamepad != nullptr) {
|
if (m_sdl_gamepad != nullptr) {
|
||||||
SDL_SetGamepadLED(m_sdl_gamepad, r, g, b);
|
SDL_SetGamepadLED(m_sdl_gamepad, r, g, b);
|
||||||
@ -149,6 +247,18 @@ void GameController::TryOpenSDLController() {
|
|||||||
int gamepad_count;
|
int gamepad_count;
|
||||||
SDL_JoystickID* gamepads = SDL_GetGamepads(&gamepad_count);
|
SDL_JoystickID* gamepads = SDL_GetGamepads(&gamepad_count);
|
||||||
m_sdl_gamepad = gamepad_count > 0 ? SDL_OpenGamepad(gamepads[0]) : nullptr;
|
m_sdl_gamepad = gamepad_count > 0 ? SDL_OpenGamepad(gamepads[0]) : nullptr;
|
||||||
|
if (SDL_SetGamepadSensorEnabled(m_sdl_gamepad, SDL_SENSOR_GYRO, true)) {
|
||||||
|
gyro_poll_rate = SDL_GetGamepadSensorDataRate(m_sdl_gamepad, SDL_SENSOR_GYRO);
|
||||||
|
LOG_INFO(Input, "Gyro initialized, poll rate: {}", gyro_poll_rate);
|
||||||
|
} else {
|
||||||
|
LOG_ERROR(Input, "Failed to initialize gyro controls for gamepad");
|
||||||
|
}
|
||||||
|
if (SDL_SetGamepadSensorEnabled(m_sdl_gamepad, SDL_SENSOR_ACCEL, true)) {
|
||||||
|
accel_poll_rate = SDL_GetGamepadSensorDataRate(m_sdl_gamepad, SDL_SENSOR_ACCEL);
|
||||||
|
LOG_INFO(Input, "Accel initialized, poll rate: {}", accel_poll_rate);
|
||||||
|
} else {
|
||||||
|
LOG_ERROR(Input, "Failed to initialize accel controls for gamepad");
|
||||||
|
}
|
||||||
SDL_free(gamepads);
|
SDL_free(gamepads);
|
||||||
|
|
||||||
SetLightBarRGB(0, 0, 255);
|
SetLightBarRGB(0, 0, 255);
|
||||||
|
@ -33,6 +33,9 @@ struct State {
|
|||||||
u64 time = 0;
|
u64 time = 0;
|
||||||
int axes[static_cast<int>(Axis::AxisMax)] = {128, 128, 128, 128, 0, 0};
|
int axes[static_cast<int>(Axis::AxisMax)] = {128, 128, 128, 128, 0, 0};
|
||||||
TouchpadEntry touchpad[2] = {{false, 0, 0}, {false, 0, 0}};
|
TouchpadEntry touchpad[2] = {{false, 0, 0}, {false, 0, 0}};
|
||||||
|
Libraries::Pad::OrbisFVector3 acceleration = {0.0f, 0.0f, 0.0f};
|
||||||
|
Libraries::Pad::OrbisFVector3 angularVelocity = {0.0f, 0.0f, 0.0f};
|
||||||
|
Libraries::Pad::OrbisFQuaternion orientation = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int GetAxis(int min, int max, int value) {
|
inline int GetAxis(int min, int max, int value) {
|
||||||
@ -53,12 +56,21 @@ public:
|
|||||||
void CheckButton(int id, Libraries::Pad::OrbisPadButtonDataOffset button, bool isPressed);
|
void CheckButton(int id, Libraries::Pad::OrbisPadButtonDataOffset button, bool isPressed);
|
||||||
void AddState(const State& state);
|
void AddState(const State& state);
|
||||||
void Axis(int id, Input::Axis axis, int value);
|
void Axis(int id, Input::Axis axis, int value);
|
||||||
|
void Gyro(int id, const float gyro[3]);
|
||||||
|
void Acceleration(int id, const float acceleration[3]);
|
||||||
void SetLightBarRGB(u8 r, u8 g, u8 b);
|
void SetLightBarRGB(u8 r, u8 g, u8 b);
|
||||||
bool SetVibration(u8 smallMotor, u8 largeMotor);
|
bool SetVibration(u8 smallMotor, u8 largeMotor);
|
||||||
void SetTouchpadState(int touchIndex, bool touchDown, float x, float y);
|
void SetTouchpadState(int touchIndex, bool touchDown, float x, float y);
|
||||||
void TryOpenSDLController();
|
void TryOpenSDLController();
|
||||||
u32 Poll();
|
u32 Poll();
|
||||||
|
|
||||||
|
float gyro_poll_rate;
|
||||||
|
float accel_poll_rate;
|
||||||
|
static void CalculateOrientation(Libraries::Pad::OrbisFVector3& acceleration,
|
||||||
|
Libraries::Pad::OrbisFVector3& angularVelocity,
|
||||||
|
float deltaTime,
|
||||||
|
Libraries::Pad::OrbisFQuaternion& orientation);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct StateInternal {
|
struct StateInternal {
|
||||||
bool obtained = false;
|
bool obtained = false;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
#include <QNetworkRequest>
|
#include <QNetworkRequest>
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
#include <QProgressBar>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@ -24,11 +25,9 @@
|
|||||||
#include <common/path_util.h>
|
#include <common/path_util.h>
|
||||||
#include <common/scm_rev.h>
|
#include <common/scm_rev.h>
|
||||||
#include <common/version.h>
|
#include <common/version.h>
|
||||||
#include <qprogressbar.h>
|
|
||||||
#include "check_update.h"
|
#include "check_update.h"
|
||||||
|
|
||||||
using namespace Common::FS;
|
using namespace Common::FS;
|
||||||
namespace fs = std::filesystem;
|
|
||||||
|
|
||||||
CheckUpdate::CheckUpdate(const bool showMessage, QWidget* parent)
|
CheckUpdate::CheckUpdate(const bool showMessage, QWidget* parent)
|
||||||
: QDialog(parent), networkManager(new QNetworkAccessManager(this)) {
|
: QDialog(parent), networkManager(new QNetworkAccessManager(this)) {
|
||||||
@ -254,7 +253,11 @@ void CheckUpdate::setupUI(const QString& downloadUrl, const QString& latestDate,
|
|||||||
connect(noButton, &QPushButton::clicked, this, [this]() { close(); });
|
connect(noButton, &QPushButton::clicked, this, [this]() { close(); });
|
||||||
|
|
||||||
autoUpdateCheckBox->setChecked(Config::autoUpdate());
|
autoUpdateCheckBox->setChecked(Config::autoUpdate());
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0))
|
||||||
connect(autoUpdateCheckBox, &QCheckBox::stateChanged, this, [](int state) {
|
connect(autoUpdateCheckBox, &QCheckBox::stateChanged, this, [](int state) {
|
||||||
|
#else
|
||||||
|
connect(autoUpdateCheckBox, &QCheckBox::checkStateChanged, this, [](Qt::CheckState state) {
|
||||||
|
#endif
|
||||||
const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
|
||||||
Config::setAutoUpdate(state == Qt::Checked);
|
Config::setAutoUpdate(state == Qt::Checked);
|
||||||
Config::save(user_dir / "config.toml");
|
Config::save(user_dir / "config.toml");
|
||||||
|
@ -3,22 +3,24 @@
|
|||||||
|
|
||||||
#include <QCompleter>
|
#include <QCompleter>
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QHoverEvent>
|
#include <QHoverEvent>
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
#include <common/version.h>
|
|
||||||
#include "common/config.h"
|
#include "common/config.h"
|
||||||
|
#include "common/version.h"
|
||||||
#include "qt_gui/compatibility_info.h"
|
#include "qt_gui/compatibility_info.h"
|
||||||
#ifdef ENABLE_DISCORD_RPC
|
#ifdef ENABLE_DISCORD_RPC
|
||||||
#include "common/discord_rpc_handler.h"
|
#include "common/discord_rpc_handler.h"
|
||||||
|
#include "common/singleton.h"
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_UPDATER
|
#ifdef ENABLE_UPDATER
|
||||||
#include "check_update.h"
|
#include "check_update.h"
|
||||||
#endif
|
#endif
|
||||||
#include <toml.hpp>
|
#include <toml.hpp>
|
||||||
|
#include "background_music_player.h"
|
||||||
#include "common/logging/backend.h"
|
#include "common/logging/backend.h"
|
||||||
#include "common/logging/filter.h"
|
#include "common/logging/filter.h"
|
||||||
#include "common/logging/formatter.h"
|
|
||||||
#include "main_window.h"
|
|
||||||
#include "settings_dialog.h"
|
#include "settings_dialog.h"
|
||||||
#include "ui_settings_dialog.h"
|
#include "ui_settings_dialog.h"
|
||||||
QStringList languageNames = {"Arabic",
|
QStringList languageNames = {"Arabic",
|
||||||
@ -130,8 +132,13 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
|
|||||||
// GENERAL TAB
|
// GENERAL TAB
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_UPDATER
|
#ifdef ENABLE_UPDATER
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0))
|
||||||
connect(ui->updateCheckBox, &QCheckBox::stateChanged, this,
|
connect(ui->updateCheckBox, &QCheckBox::stateChanged, this,
|
||||||
[](int state) { Config::setAutoUpdate(state == Qt::Checked); });
|
[](int state) { Config::setAutoUpdate(state == Qt::Checked); });
|
||||||
|
#else
|
||||||
|
connect(ui->updateCheckBox, &QCheckBox::checkStateChanged, this,
|
||||||
|
[](Qt::CheckState state) { Config::setAutoUpdate(state == Qt::Checked); });
|
||||||
|
#endif
|
||||||
|
|
||||||
connect(ui->updateComboBox, &QComboBox::currentTextChanged, this,
|
connect(ui->updateComboBox, &QComboBox::currentTextChanged, this,
|
||||||
[](const QString& channel) { Config::setUpdateChannel(channel.toStdString()); });
|
[](const QString& channel) { Config::setUpdateChannel(channel.toStdString()); });
|
||||||
@ -150,7 +157,12 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
|
|||||||
emit CompatibilityChanged();
|
emit CompatibilityChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0))
|
||||||
connect(ui->enableCompatibilityCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
|
connect(ui->enableCompatibilityCheckBox, &QCheckBox::stateChanged, this, [this](int state) {
|
||||||
|
#else
|
||||||
|
connect(ui->enableCompatibilityCheckBox, &QCheckBox::checkStateChanged, this,
|
||||||
|
[this](Qt::CheckState state) {
|
||||||
|
#endif
|
||||||
Config::setCompatibilityEnabled(state);
|
Config::setCompatibilityEnabled(state);
|
||||||
emit CompatibilityChanged();
|
emit CompatibilityChanged();
|
||||||
});
|
});
|
||||||
@ -201,6 +213,8 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
|
|||||||
ui->showSplashCheckBox->installEventFilter(this);
|
ui->showSplashCheckBox->installEventFilter(this);
|
||||||
ui->discordRPCCheckbox->installEventFilter(this);
|
ui->discordRPCCheckbox->installEventFilter(this);
|
||||||
ui->userName->installEventFilter(this);
|
ui->userName->installEventFilter(this);
|
||||||
|
ui->label_Trophy->installEventFilter(this);
|
||||||
|
ui->trophyKeyLineEdit->installEventFilter(this);
|
||||||
ui->logTypeGroupBox->installEventFilter(this);
|
ui->logTypeGroupBox->installEventFilter(this);
|
||||||
ui->logFilter->installEventFilter(this);
|
ui->logFilter->installEventFilter(this);
|
||||||
#ifdef ENABLE_UPDATER
|
#ifdef ENABLE_UPDATER
|
||||||
@ -295,6 +309,9 @@ void SettingsDialog::LoadValuesFromConfig() {
|
|||||||
QString::fromStdString(toml::find_or<std::string>(data, "General", "logFilter", "")));
|
QString::fromStdString(toml::find_or<std::string>(data, "General", "logFilter", "")));
|
||||||
ui->userNameLineEdit->setText(
|
ui->userNameLineEdit->setText(
|
||||||
QString::fromStdString(toml::find_or<std::string>(data, "General", "userName", "shadPS4")));
|
QString::fromStdString(toml::find_or<std::string>(data, "General", "userName", "shadPS4")));
|
||||||
|
ui->trophyKeyLineEdit->setText(
|
||||||
|
QString::fromStdString(toml::find_or<std::string>(data, "Keys", "TrophyKey", "")));
|
||||||
|
ui->trophyKeyLineEdit->setEchoMode(QLineEdit::Password);
|
||||||
ui->debugDump->setChecked(toml::find_or<bool>(data, "Debug", "DebugDump", false));
|
ui->debugDump->setChecked(toml::find_or<bool>(data, "Debug", "DebugDump", false));
|
||||||
ui->vkValidationCheckBox->setChecked(toml::find_or<bool>(data, "Vulkan", "validation", false));
|
ui->vkValidationCheckBox->setChecked(toml::find_or<bool>(data, "Vulkan", "validation", false));
|
||||||
ui->vkSyncValidationCheckBox->setChecked(
|
ui->vkSyncValidationCheckBox->setChecked(
|
||||||
@ -358,7 +375,7 @@ void SettingsDialog::InitializeEmulatorLanguages() {
|
|||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(ui->emulatorLanguageComboBox, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
connect(ui->emulatorLanguageComboBox, &QComboBox::currentIndexChanged, this,
|
||||||
&SettingsDialog::OnLanguageChanged);
|
&SettingsDialog::OnLanguageChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -407,6 +424,10 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) {
|
|||||||
text = tr("discordRPCCheckbox");
|
text = tr("discordRPCCheckbox");
|
||||||
} else if (elementName == "userName") {
|
} else if (elementName == "userName") {
|
||||||
text = tr("userName");
|
text = tr("userName");
|
||||||
|
} else if (elementName == "label_Trophy") {
|
||||||
|
text = tr("TrophyKey");
|
||||||
|
} else if (elementName == "trophyKeyLineEdit") {
|
||||||
|
text = tr("TrophyKey");
|
||||||
} else if (elementName == "logTypeGroupBox") {
|
} else if (elementName == "logTypeGroupBox") {
|
||||||
text = tr("logTypeGroupBox");
|
text = tr("logTypeGroupBox");
|
||||||
} else if (elementName == "logFilter") {
|
} else if (elementName == "logFilter") {
|
||||||
@ -517,6 +538,7 @@ void SettingsDialog::UpdateSettings() {
|
|||||||
Config::setLogType(ui->logTypeComboBox->currentText().toStdString());
|
Config::setLogType(ui->logTypeComboBox->currentText().toStdString());
|
||||||
Config::setLogFilter(ui->logFilterLineEdit->text().toStdString());
|
Config::setLogFilter(ui->logFilterLineEdit->text().toStdString());
|
||||||
Config::setUserName(ui->userNameLineEdit->text().toStdString());
|
Config::setUserName(ui->userNameLineEdit->text().toStdString());
|
||||||
|
Config::setTrophyKey(ui->trophyKeyLineEdit->text().toStdString());
|
||||||
Config::setCursorState(ui->hideCursorComboBox->currentIndex());
|
Config::setCursorState(ui->hideCursorComboBox->currentIndex());
|
||||||
Config::setCursorHideTimeout(ui->idleTimeoutSpinBox->value());
|
Config::setCursorHideTimeout(ui->idleTimeoutSpinBox->value());
|
||||||
Config::setGpuId(ui->graphicsAdapterBox->currentIndex() - 1);
|
Config::setGpuId(ui->graphicsAdapterBox->currentIndex() - 1);
|
||||||
@ -578,4 +600,4 @@ void SettingsDialog::ResetInstallFolders() {
|
|||||||
}
|
}
|
||||||
Config::setGameInstallDirs(settings_install_dirs_config);
|
Config::setGameInstallDirs(settings_install_dirs_config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>950</width>
|
<width>970</width>
|
||||||
<height>780</height>
|
<height>670</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -67,8 +67,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>822</width>
|
<width>946</width>
|
||||||
<height>487</height>
|
<height>536</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="generalTabVLayout" stretch="0">
|
<layout class="QVBoxLayout" name="generalTabVLayout" stretch="0">
|
||||||
@ -77,87 +77,7 @@
|
|||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="2">
|
<item row="1" column="0">
|
||||||
<layout class="QVBoxLayout" name="loggerTabLayoutRight">
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="loggerGroupBox">
|
|
||||||
<property name="title">
|
|
||||||
<string>Logger</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="loggerLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QWidget" name="LogTypeWidget" native="true">
|
|
||||||
<layout class="QVBoxLayout" name="LogTypeLayout">
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="logTypeGroupBox">
|
|
||||||
<property name="title">
|
|
||||||
<string>Log Type</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="logTypeBoxLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="logTypeComboBox">
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>async</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>sync</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="vLayoutLogFilter">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>6</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="hLayoutLogFilter">
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="logFilter">
|
|
||||||
<property name="title">
|
|
||||||
<string>Log Filter</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="logFilterLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="logFilterLineEdit"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="0">
|
|
||||||
<layout class="QVBoxLayout" name="systemTabLayoutLeft">
|
<layout class="QVBoxLayout" name="systemTabLayoutLeft">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="SystemSettings">
|
<widget class="QGroupBox" name="SystemSettings">
|
||||||
@ -194,7 +114,7 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="0">
|
||||||
<layout class="QVBoxLayout" name="emulatorTabLayoutMiddle">
|
<layout class="QVBoxLayout" name="emulatorTabLayoutMiddle">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="emulatorSettingsGroupBox">
|
<widget class="QGroupBox" name="emulatorSettingsGroupBox">
|
||||||
@ -268,10 +188,10 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0">
|
<item row="1" column="2">
|
||||||
<layout class="QVBoxLayout" name="updaterTabLayoutLeft">
|
<layout class="QVBoxLayout" name="updaterTabLayoutLeft">
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>-1</number>
|
<number>6</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeConstraint">
|
<property name="sizeConstraint">
|
||||||
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||||
@ -436,138 +356,8 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1">
|
<item row="1" column="1">
|
||||||
<layout class="QVBoxLayout" name="GUITabLayoutMiddle" stretch="0">
|
|
||||||
<item alignment="Qt::AlignmentFlag::AlignTop">
|
|
||||||
<widget class="QGroupBox" name="GUIgroupBox">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>0</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="title">
|
|
||||||
<string>GUI Settings</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="GUILayout">
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>11</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="disableTrophycheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Disable Trophy Pop-ups</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="playBGMCheckBox">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Play title music</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QVBoxLayout" name="GUIMusicLayout">
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>1</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<spacer name="GUIverticalSpacer_3">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Orientation::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::Policy::Fixed</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>13</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="maximumSize">
|
|
||||||
<size>
|
|
||||||
<width>16777215</width>
|
|
||||||
<height>16777215</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Volume</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSlider" name="BGMVolumeSlider">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>Set the volume of the background music.</string>
|
|
||||||
</property>
|
|
||||||
<property name="maximum">
|
|
||||||
<number>100</number>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<number>10</number>
|
|
||||||
</property>
|
|
||||||
<property name="pageStep">
|
|
||||||
<number>20</number>
|
|
||||||
</property>
|
|
||||||
<property name="value">
|
|
||||||
<number>50</number>
|
|
||||||
</property>
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Orientation::Horizontal</enum>
|
|
||||||
</property>
|
|
||||||
<property name="invertedAppearance">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="invertedControls">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<property name="tickPosition">
|
|
||||||
<enum>QSlider::TickPosition::NoTicks</enum>
|
|
||||||
</property>
|
|
||||||
<property name="tickInterval">
|
|
||||||
<number>10</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="2">
|
|
||||||
<layout class="QVBoxLayout" name="CompatTabLayoutRight" stretch="0">
|
<layout class="QVBoxLayout" name="CompatTabLayoutRight" stretch="0">
|
||||||
<item alignment="Qt::AlignmentFlag::AlignTop">
|
<item>
|
||||||
<widget class="QGroupBox" name="CompatgroupBox">
|
<widget class="QGroupBox" name="CompatgroupBox">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
@ -638,6 +428,160 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<layout class="QVBoxLayout" name="GUITabLayoutMiddle" stretch="0">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="GUIgroupBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>GUI Settings</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="GUILayout">
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>11</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="playBGMCheckBox">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Play title music</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="GUIMusicLayout">
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_Volume">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>16777215</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Volume</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="BGMVolumeSlider">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Set the volume of the background music.</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>20</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>50</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="invertedAppearance">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="invertedControls">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="tickPosition">
|
||||||
|
<enum>QSlider::TickPosition::NoTicks</enum>
|
||||||
|
</property>
|
||||||
|
<property name="tickInterval">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="vLayoutTrophy">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="hLayoutTrophy">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="trophyGroupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Trophy</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="userNameLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="disableTrophycheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Disable Trophy Pop-ups</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_Trophy">
|
||||||
|
<property name="text">
|
||||||
|
<string>Trophy Key</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="trophyKeyLineEdit">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -655,8 +599,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>396</width>
|
<width>926</width>
|
||||||
<height>222</height>
|
<height>536</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="inputTabVLayout" stretch="0,0">
|
<layout class="QVBoxLayout" name="inputTabVLayout" stretch="0,0">
|
||||||
@ -946,8 +890,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>536</width>
|
<width>926</width>
|
||||||
<height>192</height>
|
<height>536</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="graphicsTabVLayout" stretch="0,0">
|
<layout class="QVBoxLayout" name="graphicsTabVLayout" stretch="0,0">
|
||||||
@ -1197,8 +1141,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>146</width>
|
<width>926</width>
|
||||||
<height>215</height>
|
<height>536</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="pathsTabLayout" stretch="0">
|
<layout class="QVBoxLayout" name="pathsTabLayout" stretch="0">
|
||||||
@ -1211,18 +1155,25 @@
|
|||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QPushButton" name="removeFolderButton">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<property name="text">
|
<property name="topMargin">
|
||||||
<string>Remove</string>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<item>
|
||||||
</item>
|
<widget class="QPushButton" name="addFolderButton">
|
||||||
<item>
|
<property name="text">
|
||||||
<widget class="QPushButton" name="addFolderButton">
|
<string>Add...</string>
|
||||||
<property name="text">
|
</property>
|
||||||
<string>Add...</string>
|
</widget>
|
||||||
</property>
|
</item>
|
||||||
</widget>
|
<item>
|
||||||
|
<widget class="QPushButton" name="removeFolderButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QListWidget" name="gameFoldersListWidget"/>
|
<widget class="QListWidget" name="gameFoldersListWidget"/>
|
||||||
@ -1263,71 +1214,145 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>288</width>
|
<width>926</width>
|
||||||
<height>163</height>
|
<height>536</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="debugTabVLayout" stretch="0,1">
|
<layout class="QVBoxLayout" name="debugTabVLayout" stretch="0,1">
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="debugTabHLayout" stretch="1">
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="debugTabGroupBox">
|
<layout class="QHBoxLayout" name="debugTabHLayout" stretch="1">
|
||||||
<property name="enabled">
|
<item>
|
||||||
<bool>true</bool>
|
<widget class="QGroupBox" name="debugTabGroupBox">
|
||||||
</property>
|
<property name="enabled">
|
||||||
<property name="title">
|
<bool>true</bool>
|
||||||
<string>General</string>
|
</property>
|
||||||
</property>
|
<property name="title">
|
||||||
<property name="alignment">
|
<string>General</string>
|
||||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
</property>
|
||||||
</property>
|
<property name="alignment">
|
||||||
<layout class="QVBoxLayout" name="debugTabLayout">
|
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
|
||||||
<item alignment="Qt::AlignmentFlag::AlignTop">
|
</property>
|
||||||
<widget class="QCheckBox" name="debugDump">
|
<layout class="QVBoxLayout" name="debugTabLayout">
|
||||||
<property name="text">
|
<item>
|
||||||
<string>Enable Debug Dumping</string>
|
<widget class="QCheckBox" name="debugDump">
|
||||||
</property>
|
<property name="text">
|
||||||
</widget>
|
<string>Enable Debug Dumping</string>
|
||||||
</item>
|
</property>
|
||||||
<item>
|
</widget>
|
||||||
<spacer name="verticalSpacer">
|
</item>
|
||||||
<property name="orientation">
|
<item>
|
||||||
<enum>Qt::Orientation::Vertical</enum>
|
<widget class="QCheckBox" name="vkValidationCheckBox">
|
||||||
</property>
|
<property name="text">
|
||||||
<property name="sizeType">
|
<string>Enable Vulkan Validation Layers</string>
|
||||||
<enum>QSizePolicy::Policy::MinimumExpanding</enum>
|
</property>
|
||||||
</property>
|
</widget>
|
||||||
<property name="sizeHint" stdset="0">
|
</item>
|
||||||
<size>
|
<item>
|
||||||
<width>0</width>
|
<widget class="QCheckBox" name="vkSyncValidationCheckBox">
|
||||||
<height>0</height>
|
<property name="text">
|
||||||
</size>
|
<string>Enable Vulkan Synchronization Validation</string>
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="vkValidationCheckBox">
|
<widget class="QCheckBox" name="rdocCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Enable Vulkan Validation Layers</string>
|
<string>Enable RenderDoc Debugging</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
</layout>
|
||||||
<widget class="QCheckBox" name="vkSyncValidationCheckBox">
|
</widget>
|
||||||
<property name="text">
|
</item>
|
||||||
<string>Enable Vulkan Synchronization Validation</string>
|
</layout>
|
||||||
</property>
|
</item>
|
||||||
</widget>
|
<item>
|
||||||
</item>
|
<layout class="QVBoxLayout" name="loggerTabLayoutRight">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="rdocCheckBox">
|
<widget class="QGroupBox" name="loggerGroupBox">
|
||||||
<property name="text">
|
<property name="title">
|
||||||
<string>Enable RenderDoc Debugging</string>
|
<string>Logger</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<layout class="QVBoxLayout" name="loggerLayout">
|
||||||
</item>
|
<item>
|
||||||
</layout>
|
<widget class="QWidget" name="LogTypeWidget" native="true">
|
||||||
</widget>
|
<layout class="QVBoxLayout" name="LogTypeLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="logTypeGroupBox">
|
||||||
|
<property name="title">
|
||||||
|
<string>Log Type</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="logTypeBoxLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="logTypeComboBox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>async</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>sync</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="vLayoutLogFilter">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="hLayoutLogFilter">
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="logFilter">
|
||||||
|
<property name="title">
|
||||||
|
<string>Log Filter</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="logFilterLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="logFilterLineEdit"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>اسم المستخدم</translation>
|
<translation>اسم المستخدم</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>اسم المستخدم:\nيضبط اسم حساب PS4، الذي قد يتم عرضه في بعض الألعاب.</translation>
|
<translation>اسم المستخدم:\nيضبط اسم حساب PS4، الذي قد يتم عرضه في بعض الألعاب.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Username</translation>
|
<translation>Username</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Brugernavn:\nIndstiller PS4-kontoens navn, som kan blive vist i nogle spil.</translation>
|
<translation>Brugernavn:\nIndstiller PS4-kontoens navn, som kan blive vist i nogle spil.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Benutzername</translation>
|
<translation>Benutzername</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Benutzername:\nLegt den Namen des PS4-Kontos fest, der in einigen Spielen angezeigt werden kann.</translation>
|
<translation>Benutzername:\nLegt den Namen des PS4-Kontos fest, der in einigen Spielen angezeigt werden kann.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Username</translation>
|
<translation>Username</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Όνομα Χρήστη:\nΟρίζει το όνομα του λογαριασμού PS4, το οποίο μπορεί να εμφανιστεί σε ορισμένα παιχνίδια.</translation>
|
<translation>Όνομα Χρήστη:\nΟρίζει το όνομα του λογαριασμού PS4, το οποίο μπορεί να εμφανιστεί σε ορισμένα παιχνίδια.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Username</translation>
|
<translation>Username</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Username:\nSets the PS4's account username, which may be displayed by some games.</translation>
|
<translation>Username:\nSets the PS4's account username, which may be displayed by some games.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Nombre de usuario</translation>
|
<translation>Nombre de usuario</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Nombre de Usuario:\nEstablece el nombre de usuario de la cuenta de PS4, que puede ser mostrado por algunos juegos.</translation>
|
<translation>Nombre de Usuario:\nEstablece el nombre de usuario de la cuenta de PS4, que puede ser mostrado por algunos juegos.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>نام کاربری</translation>
|
<translation>نام کاربری</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>نام کاربری:\nنام کاربری حساب PS4 را تنظیم میکند که ممکن است توسط برخی بازیها نمایش داده شود.</translation>
|
<translation>نام کاربری:\nنام کاربری حساب PS4 را تنظیم میکند که ممکن است توسط برخی بازیها نمایش داده شود.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Username</translation>
|
<translation>Username</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Käyttäjänimi:\nAsettaa PS4-tilin käyttäjänimen, joka voi näkyä joissakin peleissä.</translation>
|
<translation>Käyttäjänimi:\nAsettaa PS4-tilin käyttäjänimen, joka voi näkyä joissakin peleissä.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Nom d'utilisateur</translation>
|
<translation>Nom d'utilisateur</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Nom d'utilisateur:\nDéfinit le nom d'utilisateur du compte PS4, qui peut être affiché par certains jeux.</translation>
|
<translation>Nom d'utilisateur:\nDéfinit le nom d'utilisateur du compte PS4, qui peut être affiché par certains jeux.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Felhasználónév</translation>
|
<translation>Felhasználónév</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Felhasználónév:\nBeállítja a PS4 fiók felhasználónevét, amelyet egyes játékok megjeleníthetnek.</translation>
|
<translation>Felhasználónév:\nBeállítja a PS4 fiók felhasználónevét, amelyet egyes játékok megjeleníthetnek.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Username</translation>
|
<translation>Username</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Nama Pengguna:\nMenetapkan nama pengguna akun PS4, yang mungkin ditampilkan oleh beberapa permainan.</translation>
|
<translation>Nama Pengguna:\nMenetapkan nama pengguna akun PS4, yang mungkin ditampilkan oleh beberapa permainan.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Nome Utente</translation>
|
<translation>Nome Utente</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Nome Utente:\nImposta il nome utente dell'account PS4, che potrebbe essere visualizzato da alcuni giochi.</translation>
|
<translation>Nome Utente:\nImposta il nome utente dell'account PS4, che potrebbe essere visualizzato da alcuni giochi.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>ユーザー名</translation>
|
<translation>ユーザー名</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>ユーザー名:\nPS4のアカウントユーザー名を設定します。これは、一部のゲームで表示される場合があります。</translation>
|
<translation>ユーザー名:\nPS4のアカウントユーザー名を設定します。これは、一部のゲームで表示される場合があります。</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Username</translation>
|
<translation>Username</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Username:\nSets the PS4's account username, which may be displayed by some games.</translation>
|
<translation>Username:\nSets the PS4's account username, which may be displayed by some games.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Username</translation>
|
<translation>Username</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Vartotojo vardas:\nNustato PS4 paskyros vartotojo vardą, kuris gali būti rodomas kai kuriuose žaidimuose.</translation>
|
<translation>Vartotojo vardas:\nNustato PS4 paskyros vartotojo vardą, kuris gali būti rodomas kai kuriuose žaidimuose.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Brukernavn</translation>
|
<translation>Brukernavn</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Brukernavn:\nAngir brukernavnet for PS4-kontoen, som kan vises av enkelte spill.</translation>
|
<translation>Brukernavn:\nAngir brukernavnet for PS4-kontoen, som kan vises av enkelte spill.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Username</translation>
|
<translation>Username</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Gebruikersnaam:\nStelt de gebruikersnaam van het PS4-account in, die door sommige games kan worden weergegeven.</translation>
|
<translation>Gebruikersnaam:\nStelt de gebruikersnaam van het PS4-account in, die door sommige games kan worden weergegeven.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Nazwa użytkownika</translation>
|
<translation>Nazwa użytkownika</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Nazwa użytkownika:\nUstala nazwę użytkownika konta PS4, która może być wyświetlana w niektórych grach.</translation>
|
<translation>Nazwa użytkownika:\nUstala nazwę użytkownika konta PS4, która może być wyświetlana w niektórych grach.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Nome de usuário</translation>
|
<translation>Nome de usuário</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Troféus</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Nome de usuário:\nDefine o nome de usuário da conta PS4 que pode ser exibido por alguns jogos.</translation>
|
<translation>Nome de usuário:\nDefine o nome de usuário da conta PS4 que pode ser exibido por alguns jogos.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Username</translation>
|
<translation>Username</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Nume utilizator:\nSetează numele de utilizator al contului PS4, care poate fi afișat de unele jocuri.</translation>
|
<translation>Nume utilizator:\nSetează numele de utilizator al contului PS4, care poate fi afișat de unele jocuri.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Имя пользователя</translation>
|
<translation>Имя пользователя</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Имя пользователя:\nУстановите имя пользователя аккаунта PS4. Это может отображаться в некоторых играх.</translation>
|
<translation>Имя пользователя:\nУстановите имя пользователя аккаунта PS4. Это может отображаться в некоторых играх.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Përdoruesi</translation>
|
<translation>Përdoruesi</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Përdoruesi:\nPërcakton emrin e përdoruesit të llogarisë PS4, i cili mund të shfaqet nga disa lojra.</translation>
|
<translation>Përdoruesi:\nPërcakton emrin e përdoruesit të llogarisë PS4, i cili mund të shfaqet nga disa lojra.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Kullanıcı Adı</translation>
|
<translation>Kullanıcı Adı</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Kullanıcı Adı:\nBazı oyunlar tarafından gösterilebilen PS4 hesabının kullanıcı adını ayarlar.</translation>
|
<translation>Kullanıcı Adı:\nBazı oyunlar tarafından gösterilebilen PS4 hesabının kullanıcı adını ayarlar.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Ім'я користувача</translation>
|
<translation>Ім'я користувача</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Ім'я користувача:\nВстановіть ім'я користувача акаунта PS4. Це може відображатися в деяких іграх.</translation>
|
<translation>Ім'я користувача:\nВстановіть ім'я користувача акаунта PS4. Це може відображатися в деяких іграх.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Username</translation>
|
<translation>Username</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>Tên người dùng:\nChọn tên người dùng của tài khoản PS4, có thể được một số trò chơi hiển thị.</translation>
|
<translation>Tên người dùng:\nChọn tên người dùng của tài khoản PS4, có thể được một số trò chơi hiển thị.</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>用户名</translation>
|
<translation>用户名</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>用户名:\n设置 PS4 帐户的用户名,某些游戏中可能会显示此名称。</translation>
|
<translation>用户名:\n设置 PS4 帐户的用户名,某些游戏中可能会显示此名称。</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -537,6 +537,16 @@
|
|||||||
<source>Username</source>
|
<source>Username</source>
|
||||||
<translation>Username</translation>
|
<translation>Username</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy Key</source>
|
||||||
|
<translation>Trophy Key</translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.ui"/>
|
||||||
|
<source>Trophy</source>
|
||||||
|
<translation>Trophy</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.ui" line="178"/>
|
<location filename="../settings_dialog.ui" line="178"/>
|
||||||
<source>Logger</source>
|
<source>Logger</source>
|
||||||
@ -1236,6 +1246,11 @@
|
|||||||
<source>userName</source>
|
<source>userName</source>
|
||||||
<translation>用戶名:\n設定PS4帳號的用戶名,某些遊戲中可能會顯示。</translation>
|
<translation>用戶名:\n設定PS4帳號的用戶名,某些遊戲中可能會顯示。</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../settings_dialog.cpp"/>
|
||||||
|
<source>TrophyKey</source>
|
||||||
|
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../settings_dialog.cpp" line="301"/>
|
<location filename="../settings_dialog.cpp" line="301"/>
|
||||||
<source>logTypeGroupBox</source>
|
<source>logTypeGroupBox</source>
|
||||||
|
@ -161,6 +161,20 @@ void WindowSDL::WaitEvent() {
|
|||||||
case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION:
|
case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION:
|
||||||
OnGamepadEvent(&event);
|
OnGamepadEvent(&event);
|
||||||
break;
|
break;
|
||||||
|
// i really would have appreciated ANY KIND OF DOCUMENTATION ON THIS
|
||||||
|
// AND IT DOESN'T EVEN USE PROPER ENUMS
|
||||||
|
case SDL_EVENT_GAMEPAD_SENSOR_UPDATE:
|
||||||
|
switch ((SDL_SensorType)event.gsensor.sensor) {
|
||||||
|
case SDL_SENSOR_GYRO:
|
||||||
|
controller->Gyro(0, event.gsensor.data);
|
||||||
|
break;
|
||||||
|
case SDL_SENSOR_ACCEL:
|
||||||
|
controller->Acceleration(0, event.gsensor.data);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case SDL_EVENT_QUIT:
|
case SDL_EVENT_QUIT:
|
||||||
is_open = false;
|
is_open = false;
|
||||||
break;
|
break;
|
||||||
|
@ -205,7 +205,6 @@ void Translator::DS_WRITE(int bit_size, bool is_signed, bool is_pair, bool strid
|
|||||||
addr, ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0)));
|
addr, ir.Imm32((u32(inst.control.ds.offset1) << 8u) + u32(inst.control.ds.offset0)));
|
||||||
ir.WriteShared(bit_size, ir.GetVectorReg(data0), addr0);
|
ir.WriteShared(bit_size, ir.GetVectorReg(data0), addr0);
|
||||||
}
|
}
|
||||||
emit_ds_read_barrier = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::DS_SWIZZLE_B32(const GcnInst& inst) {
|
void Translator::DS_SWIZZLE_B32(const GcnInst& inst) {
|
||||||
@ -222,11 +221,6 @@ void Translator::DS_SWIZZLE_B32(const GcnInst& inst) {
|
|||||||
|
|
||||||
void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64,
|
void Translator::DS_READ(int bit_size, bool is_signed, bool is_pair, bool stride64,
|
||||||
const GcnInst& inst) {
|
const GcnInst& inst) {
|
||||||
if (emit_ds_read_barrier && profile.needs_lds_barriers) {
|
|
||||||
ir.Barrier();
|
|
||||||
emit_ds_read_barrier = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))};
|
const IR::U32 addr{ir.GetVectorReg(IR::VectorReg(inst.src[0].code))};
|
||||||
IR::VectorReg dst_reg{inst.dst[0].code};
|
IR::VectorReg dst_reg{inst.dst[0].code};
|
||||||
if (is_pair) {
|
if (is_pair) {
|
||||||
|
@ -308,7 +308,6 @@ private:
|
|||||||
const RuntimeInfo& runtime_info;
|
const RuntimeInfo& runtime_info;
|
||||||
const Profile& profile;
|
const Profile& profile;
|
||||||
bool opcode_missing = false;
|
bool opcode_missing = false;
|
||||||
bool emit_ds_read_barrier = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void Translate(IR::Block* block, u32 block_base, std::span<const GcnInst> inst_list, Info& info,
|
void Translate(IR::Block* block, u32 block_base, std::span<const GcnInst> inst_list, Info& info,
|
||||||
|
@ -8,6 +8,54 @@
|
|||||||
|
|
||||||
namespace Shader::Optimization {
|
namespace Shader::Optimization {
|
||||||
|
|
||||||
|
static void EmitBarrierInBlock(IR::Block* block) {
|
||||||
|
// This is inteded to insert a barrier when shared memory write and read
|
||||||
|
// occur in the same basic block. Also checks if branch depth is zero as
|
||||||
|
// we don't want to insert barrier in potentially divergent code.
|
||||||
|
bool emit_barrier_on_write = false;
|
||||||
|
bool emit_barrier_on_read = false;
|
||||||
|
const auto emit_barrier = [block](bool& emit_cond, IR::Inst& inst) {
|
||||||
|
if (emit_cond) {
|
||||||
|
IR::IREmitter ir{*block, IR::Block::InstructionList::s_iterator_to(inst)};
|
||||||
|
ir.Barrier();
|
||||||
|
emit_cond = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (IR::Inst& inst : block->Instructions()) {
|
||||||
|
if (inst.GetOpcode() == IR::Opcode::LoadSharedU32 ||
|
||||||
|
inst.GetOpcode() == IR::Opcode::LoadSharedU64) {
|
||||||
|
emit_barrier(emit_barrier_on_read, inst);
|
||||||
|
emit_barrier_on_write = true;
|
||||||
|
}
|
||||||
|
if (inst.GetOpcode() == IR::Opcode::WriteSharedU32 ||
|
||||||
|
inst.GetOpcode() == IR::Opcode::WriteSharedU64) {
|
||||||
|
emit_barrier(emit_barrier_on_write, inst);
|
||||||
|
emit_barrier_on_read = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void EmitBarrierInMergeBlock(const IR::AbstractSyntaxNode::Data& data) {
|
||||||
|
// Insert a barrier after divergent conditional blocks.
|
||||||
|
// This avoids potential softlocks and crashes when some threads
|
||||||
|
// initialize shared memory and others read from it.
|
||||||
|
const IR::U1 cond = data.if_node.cond;
|
||||||
|
const auto insert_barrier =
|
||||||
|
IR::BreadthFirstSearch(cond, [](IR::Inst* inst) -> std::optional<bool> {
|
||||||
|
if (inst->GetOpcode() == IR::Opcode::GetAttributeU32 &&
|
||||||
|
inst->Arg(0).Attribute() == IR::Attribute::LocalInvocationId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
});
|
||||||
|
if (insert_barrier) {
|
||||||
|
IR::Block* const merge = data.if_node.merge;
|
||||||
|
auto insert_point = std::ranges::find_if_not(merge->Instructions(), IR::IsPhi);
|
||||||
|
IR::IREmitter ir{*merge, insert_point};
|
||||||
|
ir.Barrier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SharedMemoryBarrierPass(IR::Program& program, const Profile& profile) {
|
void SharedMemoryBarrierPass(IR::Program& program, const Profile& profile) {
|
||||||
if (!program.info.uses_shared || !profile.needs_lds_barriers) {
|
if (!program.info.uses_shared || !profile.needs_lds_barriers) {
|
||||||
return;
|
return;
|
||||||
@ -19,27 +67,12 @@ void SharedMemoryBarrierPass(IR::Program& program, const Profile& profile) {
|
|||||||
--branch_depth;
|
--branch_depth;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (node.type != Type::If) {
|
if (node.type == Type::If && branch_depth++ == 0) {
|
||||||
|
EmitBarrierInMergeBlock(node.data);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
u32 curr_depth = branch_depth++;
|
if (node.type == Type::Block && branch_depth == 0) {
|
||||||
if (curr_depth != 0) {
|
EmitBarrierInBlock(node.data.block);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const IR::U1 cond = node.data.if_node.cond;
|
|
||||||
const auto insert_barrier =
|
|
||||||
IR::BreadthFirstSearch(cond, [](IR::Inst* inst) -> std::optional<bool> {
|
|
||||||
if (inst->GetOpcode() == IR::Opcode::GetAttributeU32 &&
|
|
||||||
inst->Arg(0).Attribute() == IR::Attribute::LocalInvocationId) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return std::nullopt;
|
|
||||||
});
|
|
||||||
if (insert_barrier) {
|
|
||||||
IR::Block* const merge = node.data.if_node.merge;
|
|
||||||
auto insert_point = std::ranges::find_if_not(merge->Instructions(), IR::IsPhi);
|
|
||||||
IR::IREmitter ir{*merge, insert_point};
|
|
||||||
ir.Barrier();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -815,7 +815,8 @@ Liverpool::Task Liverpool::ProcessCompute(std::span<const u32> acb, u32 vqid) {
|
|||||||
}
|
}
|
||||||
if (rasterizer && (cs_program.dispatch_initiator & 1)) {
|
if (rasterizer && (cs_program.dispatch_initiator & 1)) {
|
||||||
const auto cmd_address = reinterpret_cast<const void*>(header);
|
const auto cmd_address = reinterpret_cast<const void*>(header);
|
||||||
rasterizer->ScopeMarkerBegin(fmt::format("acb[{}]:{}:Dispatch", vqid, cmd_address));
|
rasterizer->ScopeMarkerBegin(
|
||||||
|
fmt::format("acb[{}]:{}:DispatchIndirect", vqid, cmd_address));
|
||||||
rasterizer->DispatchDirect();
|
rasterizer->DispatchDirect();
|
||||||
rasterizer->ScopeMarkerEnd();
|
rasterizer->ScopeMarkerEnd();
|
||||||
}
|
}
|
||||||
|
@ -889,11 +889,11 @@ struct Liverpool {
|
|||||||
return !info.linear_general;
|
return !info.linear_general;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] DataFormat DataFormat() const {
|
[[nodiscard]] DataFormat GetDataFmt() const {
|
||||||
return RemapDataFormat(info.format);
|
return RemapDataFormat(info.format);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] NumberFormat NumFormat() const {
|
[[nodiscard]] NumberFormat GetNumberFmt() const {
|
||||||
// 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
|
||||||
|
@ -79,21 +79,23 @@ inline NumberFormat RemapNumberFormat(const NumberFormat format) {
|
|||||||
|
|
||||||
inline CompMapping RemapComponents(const DataFormat format, const CompMapping components) {
|
inline CompMapping RemapComponents(const DataFormat format, const CompMapping components) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case DataFormat::Format11_11_10:
|
case DataFormat::Format11_11_10: {
|
||||||
return {
|
CompMapping result;
|
||||||
.r = components.b,
|
result.r = components.b;
|
||||||
.g = components.g,
|
result.g = components.g;
|
||||||
.b = components.r,
|
result.b = components.r;
|
||||||
.a = components.a,
|
result.a = components.a;
|
||||||
};
|
return result;
|
||||||
|
}
|
||||||
case DataFormat::Format10_10_10_2:
|
case DataFormat::Format10_10_10_2:
|
||||||
case DataFormat::Format5_5_5_1:
|
case DataFormat::Format5_5_5_1: {
|
||||||
return {
|
CompMapping result;
|
||||||
.r = components.a,
|
result.r = components.a;
|
||||||
.g = components.b,
|
result.g = components.b;
|
||||||
.b = components.g,
|
result.b = components.g;
|
||||||
.a = components.r,
|
result.a = components.r;
|
||||||
};
|
return result;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return components;
|
return components;
|
||||||
}
|
}
|
||||||
|
@ -54,18 +54,10 @@ BufferCache::BufferCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& s
|
|||||||
BufferCache::~BufferCache() = default;
|
BufferCache::~BufferCache() = default;
|
||||||
|
|
||||||
void BufferCache::InvalidateMemory(VAddr device_addr, u64 size) {
|
void BufferCache::InvalidateMemory(VAddr device_addr, u64 size) {
|
||||||
std::scoped_lock lk{mutex};
|
|
||||||
const bool is_tracked = IsRegionRegistered(device_addr, size);
|
const bool is_tracked = IsRegionRegistered(device_addr, size);
|
||||||
if (!is_tracked) {
|
if (is_tracked) {
|
||||||
return;
|
// Mark the page as CPU modified to stop tracking writes.
|
||||||
}
|
|
||||||
// Mark the page as CPU modified to stop tracking writes.
|
|
||||||
SCOPE_EXIT {
|
|
||||||
memory_tracker.MarkRegionAsCpuModified(device_addr, size);
|
memory_tracker.MarkRegionAsCpuModified(device_addr, size);
|
||||||
};
|
|
||||||
if (!memory_tracker.IsRegionGpuModified(device_addr, size)) {
|
|
||||||
// Page has not been modified by the GPU, nothing to do.
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +259,16 @@ void BufferCache::InlineData(VAddr address, const void* value, u32 num_bytes, bo
|
|||||||
const BufferId buffer_id = FindBuffer(address, num_bytes);
|
const BufferId buffer_id = FindBuffer(address, num_bytes);
|
||||||
return &slot_buffers[buffer_id];
|
return &slot_buffers[buffer_id];
|
||||||
}();
|
}();
|
||||||
const vk::BufferMemoryBarrier2 buf_barrier = {
|
const vk::BufferMemoryBarrier2 pre_barrier = {
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eMemoryRead,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
||||||
|
.buffer = buffer->Handle(),
|
||||||
|
.offset = buffer->Offset(address),
|
||||||
|
.size = num_bytes,
|
||||||
|
};
|
||||||
|
const vk::BufferMemoryBarrier2 post_barrier = {
|
||||||
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
.srcAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
.srcAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
||||||
.dstStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
.dstStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
@ -279,9 +280,14 @@ void BufferCache::InlineData(VAddr address, const void* value, u32 num_bytes, bo
|
|||||||
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
.bufferMemoryBarrierCount = 1,
|
.bufferMemoryBarrierCount = 1,
|
||||||
.pBufferMemoryBarriers = &buf_barrier,
|
.pBufferMemoryBarriers = &pre_barrier,
|
||||||
|
});
|
||||||
|
cmdbuf.updateBuffer(buffer->Handle(), buffer->Offset(address), num_bytes, value);
|
||||||
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
|
.bufferMemoryBarrierCount = 1,
|
||||||
|
.pBufferMemoryBarriers = &post_barrier,
|
||||||
});
|
});
|
||||||
cmdbuf.updateBuffer(buffer->Handle(), buf_barrier.offset, num_bytes, value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Buffer*, u32> BufferCache::ObtainHostUBO(std::span<const u32> data) {
|
std::pair<Buffer*, u32> BufferCache::ObtainHostUBO(std::span<const u32> data) {
|
||||||
@ -346,6 +352,7 @@ bool BufferCache::IsRegionRegistered(VAddr addr, size_t size) {
|
|||||||
++page;
|
++page;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
std::shared_lock lk{mutex};
|
||||||
Buffer& buffer = slot_buffers[buffer_id];
|
Buffer& buffer = slot_buffers[buffer_id];
|
||||||
const VAddr buf_start_addr = buffer.CpuAddr();
|
const VAddr buf_start_addr = buffer.CpuAddr();
|
||||||
const VAddr buf_end_addr = buf_start_addr + buffer.SizeBytes();
|
const VAddr buf_end_addr = buf_start_addr + buffer.SizeBytes();
|
||||||
@ -472,21 +479,48 @@ void BufferCache::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id,
|
|||||||
};
|
};
|
||||||
scheduler.EndRendering();
|
scheduler.EndRendering();
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
static constexpr vk::MemoryBarrier READ_BARRIER{
|
const std::array pre_barriers = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eMemoryWrite,
|
vk::BufferMemoryBarrier2{
|
||||||
.dstAccessMask = vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite,
|
.srcStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eTransferRead,
|
||||||
|
.buffer = overlap.Handle(),
|
||||||
|
.offset = 0,
|
||||||
|
.size = overlap.SizeBytes(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
static constexpr vk::MemoryBarrier WRITE_BARRIER{
|
const std::array post_barriers = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
vk::BufferMemoryBarrier2{
|
||||||
.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite,
|
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eTransferRead,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eMemoryWrite,
|
||||||
|
.buffer = overlap.Handle(),
|
||||||
|
.offset = 0,
|
||||||
|
.size = overlap.SizeBytes(),
|
||||||
|
},
|
||||||
|
vk::BufferMemoryBarrier2{
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite,
|
||||||
|
.buffer = new_buffer.Handle(),
|
||||||
|
.offset = dst_base_offset,
|
||||||
|
.size = overlap.SizeBytes(),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion,
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
READ_BARRIER, {}, {});
|
.bufferMemoryBarrierCount = 1,
|
||||||
cmdbuf.copyBuffer(overlap.buffer, new_buffer.buffer, copy);
|
.pBufferMemoryBarriers = pre_barriers.data(),
|
||||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
});
|
||||||
vk::PipelineStageFlagBits::eAllCommands,
|
cmdbuf.copyBuffer(overlap.Handle(), new_buffer.Handle(), copy);
|
||||||
vk::DependencyFlagBits::eByRegion, WRITE_BARRIER, {}, {});
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
|
.bufferMemoryBarrierCount = static_cast<u32>(post_barriers.size()),
|
||||||
|
.pBufferMemoryBarriers = post_barriers.data(),
|
||||||
|
});
|
||||||
DeleteBuffer(overlap_id);
|
DeleteBuffer(overlap_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,8 +530,11 @@ BufferId BufferCache::CreateBuffer(VAddr device_addr, u32 wanted_size) {
|
|||||||
wanted_size = static_cast<u32>(device_addr_end - device_addr);
|
wanted_size = static_cast<u32>(device_addr_end - device_addr);
|
||||||
const OverlapResult overlap = ResolveOverlaps(device_addr, wanted_size);
|
const OverlapResult overlap = ResolveOverlaps(device_addr, wanted_size);
|
||||||
const u32 size = static_cast<u32>(overlap.end - overlap.begin);
|
const u32 size = static_cast<u32>(overlap.end - overlap.begin);
|
||||||
const BufferId new_buffer_id = slot_buffers.insert(
|
const BufferId new_buffer_id = [&] {
|
||||||
instance, scheduler, MemoryUsage::DeviceLocal, overlap.begin, AllFlags, size);
|
std::scoped_lock lk{mutex};
|
||||||
|
return slot_buffers.insert(instance, scheduler, MemoryUsage::DeviceLocal, overlap.begin,
|
||||||
|
AllFlags, size);
|
||||||
|
}();
|
||||||
auto& new_buffer = slot_buffers[new_buffer_id];
|
auto& new_buffer = slot_buffers[new_buffer_id];
|
||||||
const size_t size_bytes = new_buffer.SizeBytes();
|
const size_t size_bytes = new_buffer.SizeBytes();
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
@ -537,10 +574,8 @@ void BufferCache::ChangeRegister(BufferId buffer_id) {
|
|||||||
|
|
||||||
void BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size,
|
void BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size,
|
||||||
bool is_texel_buffer) {
|
bool is_texel_buffer) {
|
||||||
std::scoped_lock lk{mutex};
|
|
||||||
boost::container::small_vector<vk::BufferCopy, 4> copies;
|
boost::container::small_vector<vk::BufferCopy, 4> copies;
|
||||||
u64 total_size_bytes = 0;
|
u64 total_size_bytes = 0;
|
||||||
u64 largest_copy = 0;
|
|
||||||
VAddr buffer_start = buffer.CpuAddr();
|
VAddr buffer_start = buffer.CpuAddr();
|
||||||
memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) {
|
memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) {
|
||||||
copies.push_back(vk::BufferCopy{
|
copies.push_back(vk::BufferCopy{
|
||||||
@ -549,7 +584,6 @@ void BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size,
|
|||||||
.size = range_size,
|
.size = range_size,
|
||||||
});
|
});
|
||||||
total_size_bytes += range_size;
|
total_size_bytes += range_size;
|
||||||
largest_copy = std::max(largest_copy, range_size);
|
|
||||||
});
|
});
|
||||||
SCOPE_EXIT {
|
SCOPE_EXIT {
|
||||||
if (is_texel_buffer) {
|
if (is_texel_buffer) {
|
||||||
@ -590,21 +624,35 @@ void BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size,
|
|||||||
}
|
}
|
||||||
scheduler.EndRendering();
|
scheduler.EndRendering();
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
static constexpr vk::MemoryBarrier READ_BARRIER{
|
const vk::BufferMemoryBarrier2 pre_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eMemoryWrite,
|
.srcStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
.dstAccessMask = vk::AccessFlagBits::eTransferRead | vk::AccessFlagBits::eTransferWrite,
|
.srcAccessMask = vk::AccessFlagBits2::eMemoryRead,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
||||||
|
.buffer = buffer.Handle(),
|
||||||
|
.offset = 0,
|
||||||
|
.size = buffer.SizeBytes(),
|
||||||
};
|
};
|
||||||
static constexpr vk::MemoryBarrier WRITE_BARRIER{
|
const vk::BufferMemoryBarrier2 post_barrier = {
|
||||||
.srcAccessMask = vk::AccessFlagBits::eTransferWrite,
|
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
.dstAccessMask = vk::AccessFlagBits::eMemoryRead | vk::AccessFlagBits::eMemoryWrite,
|
.srcAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite,
|
||||||
|
.buffer = buffer.Handle(),
|
||||||
|
.offset = 0,
|
||||||
|
.size = buffer.SizeBytes(),
|
||||||
};
|
};
|
||||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eAllCommands,
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion,
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
READ_BARRIER, {}, {});
|
.bufferMemoryBarrierCount = 1,
|
||||||
|
.pBufferMemoryBarriers = &pre_barrier,
|
||||||
|
});
|
||||||
cmdbuf.copyBuffer(src_buffer, buffer.buffer, copies);
|
cmdbuf.copyBuffer(src_buffer, buffer.buffer, copies);
|
||||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eTransfer,
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
vk::PipelineStageFlagBits::eAllCommands,
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
vk::DependencyFlagBits::eByRegion, WRITE_BARRIER, {}, {});
|
.bufferMemoryBarrierCount = 1,
|
||||||
|
.pBufferMemoryBarriers = &post_barrier,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr, u32 size) {
|
bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr, u32 size) {
|
||||||
@ -654,10 +702,42 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr,
|
|||||||
}
|
}
|
||||||
if (!copies.empty()) {
|
if (!copies.empty()) {
|
||||||
scheduler.EndRendering();
|
scheduler.EndRendering();
|
||||||
image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits2::eTransferRead, {});
|
const vk::BufferMemoryBarrier2 pre_barrier = {
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eMemoryRead,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
||||||
|
.buffer = buffer.Handle(),
|
||||||
|
.offset = max_offset - size,
|
||||||
|
.size = size,
|
||||||
|
};
|
||||||
|
const vk::BufferMemoryBarrier2 post_barrier = {
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eMemoryRead,
|
||||||
|
.buffer = buffer.Handle(),
|
||||||
|
.offset = max_offset - size,
|
||||||
|
.size = size,
|
||||||
|
};
|
||||||
|
auto barriers = image.GetBarriers(vk::ImageLayout::eTransferSrcOptimal,
|
||||||
|
vk::AccessFlagBits2::eTransferRead,
|
||||||
|
vk::PipelineStageFlagBits2::eTransfer, {});
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
cmdbuf.copyImageToBuffer(image.image, vk::ImageLayout::eTransferSrcOptimal, buffer.buffer,
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
|
.bufferMemoryBarrierCount = 1,
|
||||||
|
.pBufferMemoryBarriers = &pre_barrier,
|
||||||
|
.imageMemoryBarrierCount = static_cast<u32>(barriers.size()),
|
||||||
|
.pImageMemoryBarriers = barriers.data(),
|
||||||
|
});
|
||||||
|
cmdbuf.copyImageToBuffer(image.image, vk::ImageLayout::eTransferSrcOptimal, buffer.Handle(),
|
||||||
copies);
|
copies);
|
||||||
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
|
.bufferMemoryBarrierCount = 1,
|
||||||
|
.pBufferMemoryBarriers = &post_barrier,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mutex>
|
#include <shared_mutex>
|
||||||
#include <boost/container/small_vector.hpp>
|
#include <boost/container/small_vector.hpp>
|
||||||
#include <boost/icl/interval_map.hpp>
|
#include <boost/icl/interval_map.hpp>
|
||||||
#include <tsl/robin_map.h>
|
#include <tsl/robin_map.h>
|
||||||
@ -157,7 +157,7 @@ private:
|
|||||||
StreamBuffer staging_buffer;
|
StreamBuffer staging_buffer;
|
||||||
StreamBuffer stream_buffer;
|
StreamBuffer stream_buffer;
|
||||||
Buffer gds_buffer;
|
Buffer gds_buffer;
|
||||||
std::mutex mutex;
|
std::shared_mutex mutex;
|
||||||
Common::SlotVector<Buffer> slot_buffers;
|
Common::SlotVector<Buffer> slot_buffers;
|
||||||
RangeSet gpu_modified_ranges;
|
RangeSet gpu_modified_ranges;
|
||||||
vk::BufferView null_buffer_view;
|
vk::BufferView null_buffer_view;
|
||||||
|
@ -15,13 +15,8 @@ namespace VideoCore {
|
|||||||
class MemoryTracker {
|
class MemoryTracker {
|
||||||
public:
|
public:
|
||||||
static constexpr size_t MAX_CPU_PAGE_BITS = 40;
|
static constexpr size_t MAX_CPU_PAGE_BITS = 40;
|
||||||
static constexpr size_t HIGHER_PAGE_BITS = 22;
|
|
||||||
static constexpr size_t HIGHER_PAGE_SIZE = 1ULL << HIGHER_PAGE_BITS;
|
|
||||||
static constexpr size_t HIGHER_PAGE_MASK = HIGHER_PAGE_SIZE - 1ULL;
|
|
||||||
static constexpr size_t NUM_HIGH_PAGES = 1ULL << (MAX_CPU_PAGE_BITS - HIGHER_PAGE_BITS);
|
static constexpr size_t NUM_HIGH_PAGES = 1ULL << (MAX_CPU_PAGE_BITS - HIGHER_PAGE_BITS);
|
||||||
static constexpr size_t MANAGER_POOL_SIZE = 32;
|
static constexpr size_t MANAGER_POOL_SIZE = 32;
|
||||||
static constexpr size_t WORDS_STACK_NEEDED = HIGHER_PAGE_SIZE / BYTES_PER_WORD;
|
|
||||||
using Manager = WordManager<WORDS_STACK_NEEDED>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MemoryTracker(PageManager* tracker_) : tracker{tracker_} {}
|
explicit MemoryTracker(PageManager* tracker_) : tracker{tracker_} {}
|
||||||
@ -30,7 +25,7 @@ public:
|
|||||||
/// Returns true if a region has been modified from the CPU
|
/// Returns true if a region has been modified from the CPU
|
||||||
[[nodiscard]] bool IsRegionCpuModified(VAddr query_cpu_addr, u64 query_size) noexcept {
|
[[nodiscard]] bool IsRegionCpuModified(VAddr query_cpu_addr, u64 query_size) noexcept {
|
||||||
return IteratePages<true>(
|
return IteratePages<true>(
|
||||||
query_cpu_addr, query_size, [](Manager* manager, u64 offset, size_t size) {
|
query_cpu_addr, query_size, [](RegionManager* manager, u64 offset, size_t size) {
|
||||||
return manager->template IsRegionModified<Type::CPU>(offset, size);
|
return manager->template IsRegionModified<Type::CPU>(offset, size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -38,52 +33,34 @@ public:
|
|||||||
/// Returns true if a region has been modified from the GPU
|
/// Returns true if a region has been modified from the GPU
|
||||||
[[nodiscard]] bool IsRegionGpuModified(VAddr query_cpu_addr, u64 query_size) noexcept {
|
[[nodiscard]] bool IsRegionGpuModified(VAddr query_cpu_addr, u64 query_size) noexcept {
|
||||||
return IteratePages<false>(
|
return IteratePages<false>(
|
||||||
query_cpu_addr, query_size, [](Manager* manager, u64 offset, size_t size) {
|
query_cpu_addr, query_size, [](RegionManager* manager, u64 offset, size_t size) {
|
||||||
return manager->template IsRegionModified<Type::GPU>(offset, size);
|
return manager->template IsRegionModified<Type::GPU>(offset, size);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark region as CPU modified, notifying the device_tracker about this change
|
/// Mark region as CPU modified, notifying the device_tracker about this change
|
||||||
void MarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) {
|
void MarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) {
|
||||||
IteratePages<true>(dirty_cpu_addr, query_size,
|
IteratePages<false>(dirty_cpu_addr, query_size,
|
||||||
[](Manager* manager, u64 offset, size_t size) {
|
[](RegionManager* manager, u64 offset, size_t size) {
|
||||||
manager->template ChangeRegionState<Type::CPU, true>(
|
manager->template ChangeRegionState<Type::CPU, true>(
|
||||||
manager->GetCpuAddr() + offset, size);
|
manager->GetCpuAddr() + offset, size);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
/// Unmark region as CPU modified, notifying the device_tracker about this change
|
|
||||||
void UnmarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) {
|
|
||||||
IteratePages<true>(dirty_cpu_addr, query_size,
|
|
||||||
[](Manager* manager, u64 offset, size_t size) {
|
|
||||||
manager->template ChangeRegionState<Type::CPU, false>(
|
|
||||||
manager->GetCpuAddr() + offset, size);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mark region as modified from the host GPU
|
/// Mark region as modified from the host GPU
|
||||||
void MarkRegionAsGpuModified(VAddr dirty_cpu_addr, u64 query_size) noexcept {
|
void MarkRegionAsGpuModified(VAddr dirty_cpu_addr, u64 query_size) noexcept {
|
||||||
IteratePages<true>(dirty_cpu_addr, query_size,
|
IteratePages<false>(dirty_cpu_addr, query_size,
|
||||||
[](Manager* manager, u64 offset, size_t size) {
|
[](RegionManager* manager, u64 offset, size_t size) {
|
||||||
manager->template ChangeRegionState<Type::GPU, true>(
|
manager->template ChangeRegionState<Type::GPU, true>(
|
||||||
manager->GetCpuAddr() + offset, size);
|
manager->GetCpuAddr() + offset, size);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
/// Unmark region as modified from the host GPU
|
|
||||||
void UnmarkRegionAsGpuModified(VAddr dirty_cpu_addr, u64 query_size) noexcept {
|
|
||||||
IteratePages<true>(dirty_cpu_addr, query_size,
|
|
||||||
[](Manager* manager, u64 offset, size_t size) {
|
|
||||||
manager->template ChangeRegionState<Type::GPU, false>(
|
|
||||||
manager->GetCpuAddr() + offset, size);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call 'func' for each CPU modified range and unmark those pages as CPU modified
|
/// Call 'func' for each CPU modified range and unmark those pages as CPU modified
|
||||||
template <typename Func>
|
template <typename Func>
|
||||||
void ForEachUploadRange(VAddr query_cpu_range, u64 query_size, Func&& func) {
|
void ForEachUploadRange(VAddr query_cpu_range, u64 query_size, Func&& func) {
|
||||||
IteratePages<true>(query_cpu_range, query_size,
|
IteratePages<true>(query_cpu_range, query_size,
|
||||||
[&func](Manager* manager, u64 offset, size_t size) {
|
[&func](RegionManager* manager, u64 offset, size_t size) {
|
||||||
manager->template ForEachModifiedRange<Type::CPU, true>(
|
manager->template ForEachModifiedRange<Type::CPU, true>(
|
||||||
manager->GetCpuAddr() + offset, size, func);
|
manager->GetCpuAddr() + offset, size, func);
|
||||||
});
|
});
|
||||||
@ -93,7 +70,7 @@ public:
|
|||||||
template <bool clear, typename Func>
|
template <bool clear, typename Func>
|
||||||
void ForEachDownloadRange(VAddr query_cpu_range, u64 query_size, Func&& func) {
|
void ForEachDownloadRange(VAddr query_cpu_range, u64 query_size, Func&& func) {
|
||||||
IteratePages<false>(query_cpu_range, query_size,
|
IteratePages<false>(query_cpu_range, query_size,
|
||||||
[&func](Manager* manager, u64 offset, size_t size) {
|
[&func](RegionManager* manager, u64 offset, size_t size) {
|
||||||
if constexpr (clear) {
|
if constexpr (clear) {
|
||||||
manager->template ForEachModifiedRange<Type::GPU, true>(
|
manager->template ForEachModifiedRange<Type::GPU, true>(
|
||||||
manager->GetCpuAddr() + offset, size, func);
|
manager->GetCpuAddr() + offset, size, func);
|
||||||
@ -114,7 +91,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
template <bool create_region_on_fail, typename Func>
|
template <bool create_region_on_fail, typename Func>
|
||||||
bool IteratePages(VAddr cpu_address, size_t size, Func&& func) {
|
bool IteratePages(VAddr cpu_address, size_t size, Func&& func) {
|
||||||
using FuncReturn = typename std::invoke_result<Func, Manager*, u64, size_t>::type;
|
using FuncReturn = typename std::invoke_result<Func, RegionManager*, u64, size_t>::type;
|
||||||
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
||||||
std::size_t remaining_size{size};
|
std::size_t remaining_size{size};
|
||||||
std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS};
|
std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS};
|
||||||
@ -155,7 +132,7 @@ private:
|
|||||||
manager_pool.emplace_back();
|
manager_pool.emplace_back();
|
||||||
auto& last_pool = manager_pool.back();
|
auto& last_pool = manager_pool.back();
|
||||||
for (size_t i = 0; i < MANAGER_POOL_SIZE; i++) {
|
for (size_t i = 0; i < MANAGER_POOL_SIZE; i++) {
|
||||||
std::construct_at(&last_pool[i], tracker, 0, HIGHER_PAGE_SIZE);
|
std::construct_at(&last_pool[i], tracker, 0);
|
||||||
free_managers.push_back(&last_pool[i]);
|
free_managers.push_back(&last_pool[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,9 +144,9 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
PageManager* tracker;
|
PageManager* tracker;
|
||||||
std::deque<std::array<Manager, MANAGER_POOL_SIZE>> manager_pool;
|
std::deque<std::array<RegionManager, MANAGER_POOL_SIZE>> manager_pool;
|
||||||
std::vector<Manager*> free_managers;
|
std::vector<RegionManager*> free_managers;
|
||||||
std::array<Manager*, NUM_HIGH_PAGES> top_tier{};
|
std::array<RegionManager*, NUM_HIGH_PAGES> top_tier{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
@ -3,10 +3,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm>
|
#include <array>
|
||||||
|
#include <mutex>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include "common/div_ceil.h"
|
|
||||||
|
#include "common/spin_lock.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "video_core/page_manager.h"
|
#include "video_core/page_manager.h"
|
||||||
|
|
||||||
@ -16,135 +18,32 @@ constexpr u64 PAGES_PER_WORD = 64;
|
|||||||
constexpr u64 BYTES_PER_PAGE = 4_KB;
|
constexpr u64 BYTES_PER_PAGE = 4_KB;
|
||||||
constexpr u64 BYTES_PER_WORD = PAGES_PER_WORD * BYTES_PER_PAGE;
|
constexpr u64 BYTES_PER_WORD = PAGES_PER_WORD * BYTES_PER_PAGE;
|
||||||
|
|
||||||
|
constexpr u64 HIGHER_PAGE_BITS = 22;
|
||||||
|
constexpr u64 HIGHER_PAGE_SIZE = 1ULL << HIGHER_PAGE_BITS;
|
||||||
|
constexpr u64 HIGHER_PAGE_MASK = HIGHER_PAGE_SIZE - 1ULL;
|
||||||
|
constexpr u64 NUM_REGION_WORDS = HIGHER_PAGE_SIZE / BYTES_PER_WORD;
|
||||||
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
CPU,
|
CPU,
|
||||||
GPU,
|
GPU,
|
||||||
Untracked,
|
Untracked,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Vector tracking modified pages tightly packed with small vector optimization
|
using WordsArray = std::array<u64, NUM_REGION_WORDS>;
|
||||||
template <size_t stack_words = 1>
|
|
||||||
struct WordsArray {
|
|
||||||
/// Returns the pointer to the words state
|
|
||||||
[[nodiscard]] const u64* Pointer(bool is_short) const noexcept {
|
|
||||||
return is_short ? stack.data() : heap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the pointer to the words state
|
/**
|
||||||
[[nodiscard]] u64* Pointer(bool is_short) noexcept {
|
* Allows tracking CPU and GPU modification of pages in a contigious 4MB virtual address region.
|
||||||
return is_short ? stack.data() : heap;
|
* Information is stored in bitsets for spacial locality and fast update of single pages.
|
||||||
}
|
*/
|
||||||
|
class RegionManager {
|
||||||
std::array<u64, stack_words> stack{}; ///< Small buffers storage
|
|
||||||
u64* heap; ///< Not-small buffers pointer to the storage
|
|
||||||
};
|
|
||||||
|
|
||||||
template <size_t stack_words = 1>
|
|
||||||
struct Words {
|
|
||||||
explicit Words() = default;
|
|
||||||
explicit Words(u64 size_bytes_) : size_bytes{size_bytes_} {
|
|
||||||
num_words = Common::DivCeil(size_bytes, BYTES_PER_WORD);
|
|
||||||
if (IsShort()) {
|
|
||||||
cpu.stack.fill(~u64{0});
|
|
||||||
gpu.stack.fill(0);
|
|
||||||
untracked.stack.fill(~u64{0});
|
|
||||||
} else {
|
|
||||||
// Share allocation between CPU and GPU pages and set their default values
|
|
||||||
u64* const alloc = new u64[num_words * 3];
|
|
||||||
cpu.heap = alloc;
|
|
||||||
gpu.heap = alloc + num_words;
|
|
||||||
untracked.heap = alloc + num_words * 2;
|
|
||||||
std::fill_n(cpu.heap, num_words, ~u64{0});
|
|
||||||
std::fill_n(gpu.heap, num_words, 0);
|
|
||||||
std::fill_n(untracked.heap, num_words, ~u64{0});
|
|
||||||
}
|
|
||||||
// Clean up tailing bits
|
|
||||||
const u64 last_word_size = size_bytes % BYTES_PER_WORD;
|
|
||||||
const u64 last_local_page = Common::DivCeil(last_word_size, BYTES_PER_PAGE);
|
|
||||||
const u64 shift = (PAGES_PER_WORD - last_local_page) % PAGES_PER_WORD;
|
|
||||||
const u64 last_word = (~u64{0} << shift) >> shift;
|
|
||||||
cpu.Pointer(IsShort())[NumWords() - 1] = last_word;
|
|
||||||
untracked.Pointer(IsShort())[NumWords() - 1] = last_word;
|
|
||||||
}
|
|
||||||
|
|
||||||
~Words() {
|
|
||||||
Release();
|
|
||||||
}
|
|
||||||
|
|
||||||
Words& operator=(Words&& rhs) noexcept {
|
|
||||||
Release();
|
|
||||||
size_bytes = rhs.size_bytes;
|
|
||||||
num_words = rhs.num_words;
|
|
||||||
cpu = rhs.cpu;
|
|
||||||
gpu = rhs.gpu;
|
|
||||||
untracked = rhs.untracked;
|
|
||||||
rhs.cpu.heap = nullptr;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Words(Words&& rhs) noexcept
|
|
||||||
: size_bytes{rhs.size_bytes}, num_words{rhs.num_words}, cpu{rhs.cpu}, gpu{rhs.gpu},
|
|
||||||
untracked{rhs.untracked} {
|
|
||||||
rhs.cpu.heap = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Words& operator=(const Words&) = delete;
|
|
||||||
Words(const Words&) = delete;
|
|
||||||
|
|
||||||
/// Returns true when the buffer fits in the small vector optimization
|
|
||||||
[[nodiscard]] bool IsShort() const noexcept {
|
|
||||||
return num_words <= stack_words;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of words of the buffer
|
|
||||||
[[nodiscard]] size_t NumWords() const noexcept {
|
|
||||||
return num_words;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Release buffer resources
|
|
||||||
void Release() {
|
|
||||||
if (!IsShort()) {
|
|
||||||
// CPU written words is the base for the heap allocation
|
|
||||||
delete[] cpu.heap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <Type type>
|
|
||||||
std::span<u64> Span() noexcept {
|
|
||||||
if constexpr (type == Type::CPU) {
|
|
||||||
return std::span<u64>(cpu.Pointer(IsShort()), num_words);
|
|
||||||
} else if constexpr (type == Type::GPU) {
|
|
||||||
return std::span<u64>(gpu.Pointer(IsShort()), num_words);
|
|
||||||
} else if constexpr (type == Type::Untracked) {
|
|
||||||
return std::span<u64>(untracked.Pointer(IsShort()), num_words);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <Type type>
|
|
||||||
std::span<const u64> Span() const noexcept {
|
|
||||||
if constexpr (type == Type::CPU) {
|
|
||||||
return std::span<const u64>(cpu.Pointer(IsShort()), num_words);
|
|
||||||
} else if constexpr (type == Type::GPU) {
|
|
||||||
return std::span<const u64>(gpu.Pointer(IsShort()), num_words);
|
|
||||||
} else if constexpr (type == Type::Untracked) {
|
|
||||||
return std::span<const u64>(untracked.Pointer(IsShort()), num_words);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 size_bytes = 0;
|
|
||||||
size_t num_words = 0;
|
|
||||||
WordsArray<stack_words> cpu;
|
|
||||||
WordsArray<stack_words> gpu;
|
|
||||||
WordsArray<stack_words> untracked;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <size_t stack_words = 1>
|
|
||||||
class WordManager {
|
|
||||||
public:
|
public:
|
||||||
explicit WordManager(PageManager* tracker_, VAddr cpu_addr_, u64 size_bytes)
|
explicit RegionManager(PageManager* tracker_, VAddr cpu_addr_)
|
||||||
: tracker{tracker_}, cpu_addr{cpu_addr_}, words{size_bytes} {}
|
: tracker{tracker_}, cpu_addr{cpu_addr_} {
|
||||||
|
cpu.fill(~u64{0});
|
||||||
explicit WordManager() = default;
|
gpu.fill(0);
|
||||||
|
untracked.fill(~u64{0});
|
||||||
|
}
|
||||||
|
explicit RegionManager() = default;
|
||||||
|
|
||||||
void SetCpuAddress(VAddr new_cpu_addr) {
|
void SetCpuAddress(VAddr new_cpu_addr) {
|
||||||
cpu_addr = new_cpu_addr;
|
cpu_addr = new_cpu_addr;
|
||||||
@ -175,12 +74,12 @@ public:
|
|||||||
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
||||||
const size_t start = static_cast<size_t>(std::max<s64>(static_cast<s64>(offset), 0LL));
|
const size_t start = static_cast<size_t>(std::max<s64>(static_cast<s64>(offset), 0LL));
|
||||||
const size_t end = static_cast<size_t>(std::max<s64>(static_cast<s64>(offset + size), 0LL));
|
const size_t end = static_cast<size_t>(std::max<s64>(static_cast<s64>(offset + size), 0LL));
|
||||||
if (start >= SizeBytes() || end <= start) {
|
if (start >= HIGHER_PAGE_SIZE || end <= start) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto [start_word, start_page] = GetWordPage(start);
|
auto [start_word, start_page] = GetWordPage(start);
|
||||||
auto [end_word, end_page] = GetWordPage(end + BYTES_PER_PAGE - 1ULL);
|
auto [end_word, end_page] = GetWordPage(end + BYTES_PER_PAGE - 1ULL);
|
||||||
const size_t num_words = NumWords();
|
constexpr size_t num_words = NUM_REGION_WORDS;
|
||||||
start_word = std::min(start_word, num_words);
|
start_word = std::min(start_word, num_words);
|
||||||
end_word = std::min(end_word, num_words);
|
end_word = std::min(end_word, num_words);
|
||||||
const size_t diff = end_word - start_word;
|
const size_t diff = end_word - start_word;
|
||||||
@ -225,21 +124,21 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <Type type, bool enable>
|
template <Type type, bool enable>
|
||||||
void ChangeRegionState(u64 dirty_addr, u64 size) noexcept(type == Type::GPU) {
|
void ChangeRegionState(u64 dirty_addr, u64 size) noexcept(type == Type::GPU) {
|
||||||
std::span<u64> state_words = words.template Span<type>();
|
std::scoped_lock lk{lock};
|
||||||
[[maybe_unused]] std::span<u64> untracked_words = words.template Span<Type::Untracked>();
|
std::span<u64> state_words = Span<type>();
|
||||||
IterateWords(dirty_addr - cpu_addr, size, [&](size_t index, u64 mask) {
|
IterateWords(dirty_addr - cpu_addr, size, [&](size_t index, u64 mask) {
|
||||||
if constexpr (type == Type::CPU) {
|
if constexpr (type == Type::CPU) {
|
||||||
NotifyPageTracker<!enable>(index, untracked_words[index], mask);
|
UpdateProtection<!enable>(index, untracked[index], mask);
|
||||||
}
|
}
|
||||||
if constexpr (enable) {
|
if constexpr (enable) {
|
||||||
state_words[index] |= mask;
|
state_words[index] |= mask;
|
||||||
if constexpr (type == Type::CPU) {
|
if constexpr (type == Type::CPU) {
|
||||||
untracked_words[index] |= mask;
|
untracked[index] |= mask;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
state_words[index] &= ~mask;
|
state_words[index] &= ~mask;
|
||||||
if constexpr (type == Type::CPU) {
|
if constexpr (type == Type::CPU) {
|
||||||
untracked_words[index] &= ~mask;
|
untracked[index] &= ~mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -255,10 +154,10 @@ public:
|
|||||||
*/
|
*/
|
||||||
template <Type type, bool clear, typename Func>
|
template <Type type, bool clear, typename Func>
|
||||||
void ForEachModifiedRange(VAddr query_cpu_range, s64 size, Func&& func) {
|
void ForEachModifiedRange(VAddr query_cpu_range, s64 size, Func&& func) {
|
||||||
|
std::scoped_lock lk{lock};
|
||||||
static_assert(type != Type::Untracked);
|
static_assert(type != Type::Untracked);
|
||||||
|
|
||||||
std::span<u64> state_words = words.template Span<type>();
|
std::span<u64> state_words = Span<type>();
|
||||||
[[maybe_unused]] std::span<u64> untracked_words = words.template Span<Type::Untracked>();
|
|
||||||
const size_t offset = query_cpu_range - cpu_addr;
|
const size_t offset = query_cpu_range - cpu_addr;
|
||||||
bool pending = false;
|
bool pending = false;
|
||||||
size_t pending_offset{};
|
size_t pending_offset{};
|
||||||
@ -269,16 +168,16 @@ public:
|
|||||||
};
|
};
|
||||||
IterateWords(offset, size, [&](size_t index, u64 mask) {
|
IterateWords(offset, size, [&](size_t index, u64 mask) {
|
||||||
if constexpr (type == Type::GPU) {
|
if constexpr (type == Type::GPU) {
|
||||||
mask &= ~untracked_words[index];
|
mask &= ~untracked[index];
|
||||||
}
|
}
|
||||||
const u64 word = state_words[index] & mask;
|
const u64 word = state_words[index] & mask;
|
||||||
if constexpr (clear) {
|
if constexpr (clear) {
|
||||||
if constexpr (type == Type::CPU) {
|
if constexpr (type == Type::CPU) {
|
||||||
NotifyPageTracker<true>(index, untracked_words[index], mask);
|
UpdateProtection<true>(index, untracked[index], mask);
|
||||||
}
|
}
|
||||||
state_words[index] &= ~mask;
|
state_words[index] &= ~mask;
|
||||||
if constexpr (type == Type::CPU) {
|
if constexpr (type == Type::CPU) {
|
||||||
untracked_words[index] &= ~mask;
|
untracked[index] &= ~mask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const size_t base_offset = index * PAGES_PER_WORD;
|
const size_t base_offset = index * PAGES_PER_WORD;
|
||||||
@ -315,13 +214,11 @@ public:
|
|||||||
[[nodiscard]] bool IsRegionModified(u64 offset, u64 size) const noexcept {
|
[[nodiscard]] bool IsRegionModified(u64 offset, u64 size) const noexcept {
|
||||||
static_assert(type != Type::Untracked);
|
static_assert(type != Type::Untracked);
|
||||||
|
|
||||||
const std::span<const u64> state_words = words.template Span<type>();
|
const std::span<const u64> state_words = Span<type>();
|
||||||
[[maybe_unused]] const std::span<const u64> untracked_words =
|
|
||||||
words.template Span<Type::Untracked>();
|
|
||||||
bool result = false;
|
bool result = false;
|
||||||
IterateWords(offset, size, [&](size_t index, u64 mask) {
|
IterateWords(offset, size, [&](size_t index, u64 mask) {
|
||||||
if constexpr (type == Type::GPU) {
|
if constexpr (type == Type::GPU) {
|
||||||
mask &= ~untracked_words[index];
|
mask &= ~untracked[index];
|
||||||
}
|
}
|
||||||
const u64 word = state_words[index] & mask;
|
const u64 word = state_words[index] & mask;
|
||||||
if (word != 0) {
|
if (word != 0) {
|
||||||
@ -333,44 +230,7 @@ public:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of words of the manager
|
|
||||||
[[nodiscard]] size_t NumWords() const noexcept {
|
|
||||||
return words.NumWords();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the size in bytes of the manager
|
|
||||||
[[nodiscard]] u64 SizeBytes() const noexcept {
|
|
||||||
return words.size_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true when the buffer fits in the small vector optimization
|
|
||||||
[[nodiscard]] bool IsShort() const noexcept {
|
|
||||||
return words.IsShort();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <Type type>
|
|
||||||
u64* Array() noexcept {
|
|
||||||
if constexpr (type == Type::CPU) {
|
|
||||||
return words.cpu.Pointer(IsShort());
|
|
||||||
} else if constexpr (type == Type::GPU) {
|
|
||||||
return words.gpu.Pointer(IsShort());
|
|
||||||
} else if constexpr (type == Type::Untracked) {
|
|
||||||
return words.untracked.Pointer(IsShort());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <Type type>
|
|
||||||
const u64* Array() const noexcept {
|
|
||||||
if constexpr (type == Type::CPU) {
|
|
||||||
return words.cpu.Pointer(IsShort());
|
|
||||||
} else if constexpr (type == Type::GPU) {
|
|
||||||
return words.gpu.Pointer(IsShort());
|
|
||||||
} else if constexpr (type == Type::Untracked) {
|
|
||||||
return words.untracked.Pointer(IsShort());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify tracker about changes in the CPU tracking state of a word in the buffer
|
* Notify tracker about changes in the CPU tracking state of a word in the buffer
|
||||||
*
|
*
|
||||||
@ -381,7 +241,7 @@ private:
|
|||||||
* @tparam add_to_tracker True when the tracker should start tracking the new pages
|
* @tparam add_to_tracker True when the tracker should start tracking the new pages
|
||||||
*/
|
*/
|
||||||
template <bool add_to_tracker>
|
template <bool add_to_tracker>
|
||||||
void NotifyPageTracker(u64 word_index, u64 current_bits, u64 new_bits) const {
|
void UpdateProtection(u64 word_index, u64 current_bits, u64 new_bits) const {
|
||||||
u64 changed_bits = (add_to_tracker ? current_bits : ~current_bits) & new_bits;
|
u64 changed_bits = (add_to_tracker ? current_bits : ~current_bits) & new_bits;
|
||||||
VAddr addr = cpu_addr + word_index * BYTES_PER_WORD;
|
VAddr addr = cpu_addr + word_index * BYTES_PER_WORD;
|
||||||
IteratePages(changed_bits, [&](size_t offset, size_t size) {
|
IteratePages(changed_bits, [&](size_t offset, size_t size) {
|
||||||
@ -390,9 +250,34 @@ private:
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <Type type>
|
||||||
|
std::span<u64> Span() noexcept {
|
||||||
|
if constexpr (type == Type::CPU) {
|
||||||
|
return cpu;
|
||||||
|
} else if constexpr (type == Type::GPU) {
|
||||||
|
return gpu;
|
||||||
|
} else if constexpr (type == Type::Untracked) {
|
||||||
|
return untracked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <Type type>
|
||||||
|
std::span<const u64> Span() const noexcept {
|
||||||
|
if constexpr (type == Type::CPU) {
|
||||||
|
return cpu;
|
||||||
|
} else if constexpr (type == Type::GPU) {
|
||||||
|
return gpu;
|
||||||
|
} else if constexpr (type == Type::Untracked) {
|
||||||
|
return untracked;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::SpinLock lock;
|
||||||
PageManager* tracker;
|
PageManager* tracker;
|
||||||
VAddr cpu_addr = 0;
|
VAddr cpu_addr = 0;
|
||||||
Words<stack_words> words;
|
WordsArray cpu;
|
||||||
|
WordsArray gpu;
|
||||||
|
WordsArray untracked;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
@ -7,6 +7,7 @@ set(SHADER_FILES
|
|||||||
detile_m32x1.comp
|
detile_m32x1.comp
|
||||||
detile_m32x2.comp
|
detile_m32x2.comp
|
||||||
detile_m32x4.comp
|
detile_m32x4.comp
|
||||||
|
detile_macro8x1.comp
|
||||||
detile_macro32x1.comp
|
detile_macro32x1.comp
|
||||||
detile_macro32x2.comp
|
detile_macro32x2.comp
|
||||||
fs_tri.vert
|
fs_tri.vert
|
||||||
|
@ -20,7 +20,7 @@ layout(push_constant) uniform image_info {
|
|||||||
} info;
|
} info;
|
||||||
|
|
||||||
// Inverse morton LUT, small enough to fit into K$
|
// Inverse morton LUT, small enough to fit into K$
|
||||||
uint rmort[16] = {
|
const uint rmort[16] = {
|
||||||
0x11011000, 0x31213020,
|
0x11011000, 0x31213020,
|
||||||
0x13031202, 0x33233222,
|
0x13031202, 0x33233222,
|
||||||
0x51415040, 0x71617060,
|
0x51415040, 0x71617060,
|
||||||
|
@ -20,7 +20,7 @@ layout(push_constant) uniform image_info {
|
|||||||
} info;
|
} info;
|
||||||
|
|
||||||
// Inverse morton LUT, small enough to fit into K$
|
// Inverse morton LUT, small enough to fit into K$
|
||||||
uint rmort[16] = {
|
const uint rmort[16] = {
|
||||||
0x11011000, 0x31213020,
|
0x11011000, 0x31213020,
|
||||||
0x13031202, 0x33233222,
|
0x13031202, 0x33233222,
|
||||||
0x51415040, 0x71617060,
|
0x51415040, 0x71617060,
|
||||||
|
@ -20,7 +20,7 @@ layout(push_constant) uniform image_info {
|
|||||||
} info;
|
} info;
|
||||||
|
|
||||||
// Inverse morton LUT, small enough to fit into K$
|
// Inverse morton LUT, small enough to fit into K$
|
||||||
uint rmort[16] = {
|
const uint rmort[16] = {
|
||||||
0x11011000, 0x31213020,
|
0x11011000, 0x31213020,
|
||||||
0x13031202, 0x33233222,
|
0x13031202, 0x33233222,
|
||||||
0x51415040, 0x71617060,
|
0x51415040, 0x71617060,
|
||||||
|
@ -48,4 +48,4 @@ void main() {
|
|||||||
uint dw_ofs_x = target_tile_x * 2 + col; // 2 = uints
|
uint dw_ofs_x = target_tile_x * 2 + col; // 2 = uints
|
||||||
uint dw_ofs_y = (target_tile_y * MICRO_TILE_DIM + row) * tiles_per_pitch * 2; // 2 = uints
|
uint dw_ofs_y = (target_tile_y * MICRO_TILE_DIM + row) * tiles_per_pitch * 2; // 2 = uints
|
||||||
out_data[dw_ofs_x + dw_ofs_y] = dst_tx;
|
out_data[dw_ofs_x + dw_ofs_y] = dst_tx;
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ layout(push_constant) uniform image_info {
|
|||||||
#define TEXELS_PER_ELEMENT 2
|
#define TEXELS_PER_ELEMENT 2
|
||||||
|
|
||||||
// Inverse morton LUT, small enough to fit into K$
|
// Inverse morton LUT, small enough to fit into K$
|
||||||
uint rmort[16] = {
|
const uint rmort[16] = {
|
||||||
0x11011000, 0x31213020,
|
0x11011000, 0x31213020,
|
||||||
0x13031202, 0x33233222,
|
0x13031202, 0x33233222,
|
||||||
0x51415040, 0x71617060,
|
0x51415040, 0x71617060,
|
||||||
|
@ -21,46 +21,46 @@ layout(push_constant) uniform image_info {
|
|||||||
} info;
|
} info;
|
||||||
|
|
||||||
// Each LUT is 64 bytes, so should fit into K$ given tiled slices locality
|
// Each LUT is 64 bytes, so should fit into K$ given tiled slices locality
|
||||||
const uint lut_32bpp[][64] = {
|
const uint lut_32bpp[][16] = {
|
||||||
{
|
{
|
||||||
0x00, 0x01, 0x04, 0x05, 0x40, 0x41, 0x44, 0x45,
|
0x05040100, 0x45444140,
|
||||||
0x02, 0x03, 0x06, 0x07, 0x42, 0x43, 0x46, 0x47,
|
0x07060302, 0x47464342,
|
||||||
0x10, 0x11, 0x14, 0x15, 0x50, 0x51, 0x54, 0x55,
|
0x15141110, 0x55545150,
|
||||||
0x12, 0x13, 0x16, 0x17, 0x52, 0x53, 0x56, 0x57,
|
0x17161312, 0x57565352,
|
||||||
0x80, 0x81, 0x84, 0x85, 0xc0, 0xc1, 0xc4, 0xc5,
|
0x85848180, 0xc5c4c1c0,
|
||||||
0x82, 0x83, 0x86, 0x87, 0xc2, 0xc3, 0xc6, 0xc7,
|
0x87868382, 0xc7c6c3c2,
|
||||||
0x90, 0x91, 0x94, 0x95, 0xd0, 0xd1, 0xd4, 0xd5,
|
0x95949190, 0xd5d4d1d0,
|
||||||
0x92, 0x93, 0x96, 0x97, 0xd2, 0xd3, 0xd6, 0xd7,
|
0x97969392, 0xd7d6d3d2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
0x08, 0x09, 0x0c, 0x0d, 0x48, 0x49, 0x4c, 0x4d,
|
0x0d0c0908, 0x4d4c4948,
|
||||||
0x0a, 0x0b, 0x0e, 0x0f, 0x4a, 0x4b, 0x4e, 0x4f,
|
0x0f0e0b0a, 0x4f4e4b4a,
|
||||||
0x18, 0x19, 0x1c, 0x1d, 0x58, 0x59, 0x5c, 0x5d,
|
0x1d1c1918, 0x5d5c5958,
|
||||||
0x1a, 0x1b, 0x1e, 0x1f, 0x5a, 0x5b, 0x5e, 0x5f,
|
0x1f1e1b1a, 0x5f5e5b5a,
|
||||||
0x88, 0x89, 0x8c, 0x8d, 0xc8, 0xc9, 0xcc, 0xcd,
|
0x8d8c8988, 0xcdccc9c8,
|
||||||
0x8a, 0x8b, 0x8e, 0x8f, 0xca, 0xcb, 0xce, 0xcf,
|
0x8f8e8b8a, 0xcfcecbca,
|
||||||
0x98, 0x99, 0x9c, 0x9d, 0xd8, 0xd9, 0xdc, 0xdd,
|
0x9d9c9998, 0xdddcd9d8,
|
||||||
0x9a, 0x9b, 0x9e, 0x9f, 0xda, 0xdb, 0xde, 0xdf,
|
0x9f9e9b9a, 0xdfdedbda,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
0x20, 0x21, 0x24, 0x25, 0x60, 0x61, 0x64, 0x65,
|
0x25242120, 0x65646160,
|
||||||
0x22, 0x23, 0x26, 0x27, 0x62, 0x63, 0x66, 0x67,
|
0x27262322, 0x67666362,
|
||||||
0x30, 0x31, 0x34, 0x35, 0x70, 0x71, 0x74, 0x75,
|
0x35343130, 0x75747170,
|
||||||
0x32, 0x33, 0x36, 0x37, 0x72, 0x73, 0x76, 0x77,
|
0x37363332, 0x77767372,
|
||||||
0xa0, 0xa1, 0xa4, 0xa5, 0xe0, 0xe1, 0xe4, 0xe5,
|
0xa5a4a1a0, 0xe5e4e1e0,
|
||||||
0xa2, 0xa3, 0xa6, 0xa7, 0xe2, 0xe3, 0xe6, 0xe7,
|
0xa7a6a3a2, 0xe7e6e3e2,
|
||||||
0xb0, 0xb1, 0xb4, 0xb5, 0xf0, 0xf1, 0xf4, 0xf5,
|
0xb5b4b1b0, 0xf5f4f1f0,
|
||||||
0xb2, 0xb3, 0xb6, 0xb7, 0xf2, 0xf3, 0xf6, 0xf7,
|
0xb7b6b3b2, 0xf7f6f3f2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
0x28, 0x29, 0x2c, 0x2d, 0x68, 0x69, 0x6c, 0x6d,
|
0x2d2c2928, 0x6d6c6968,
|
||||||
0x2a, 0x2b, 0x2e, 0x2f, 0x6a, 0x6b, 0x6e, 0x6f,
|
0x2f2e2b2a, 0x6f6e6b6a,
|
||||||
0x38, 0x39, 0x3c, 0x3d, 0x78, 0x79, 0x7c, 0x7d,
|
0x3d3c3938, 0x7d7c7978,
|
||||||
0x3a, 0x3b, 0x3e, 0x3f, 0x7a, 0x7b, 0x7e, 0x7f,
|
0x3f3e3b3a, 0x7f7e7b7a,
|
||||||
0xa8, 0xa9, 0xac, 0xad, 0xe8, 0xe9, 0xec, 0xed,
|
0xadaca9a8, 0xedece9e8,
|
||||||
0xaa, 0xab, 0xae, 0xaf, 0xea, 0xeb, 0xee, 0xef,
|
0xafaeabaa, 0xefeeebea,
|
||||||
0xb8, 0xb9, 0xbc, 0xbd, 0xf8, 0xf9, 0xfc, 0xfd,
|
0xbdbcb9b8, 0xfdfcf9f8,
|
||||||
0xba, 0xbb, 0xbe, 0xbf, 0xfa, 0xfb, 0xfe, 0xff,
|
0xbfbebbba, 0xfffefbfa,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -77,7 +77,9 @@ void main() {
|
|||||||
uint col = bitfieldExtract(x, 0, 3);
|
uint col = bitfieldExtract(x, 0, 3);
|
||||||
uint row = bitfieldExtract(y, 0, 3);
|
uint row = bitfieldExtract(y, 0, 3);
|
||||||
uint lut = bitfieldExtract(z, 0, 2);
|
uint lut = bitfieldExtract(z, 0, 2);
|
||||||
uint idx = lut_32bpp[lut][col + row * MICRO_TILE_DIM];
|
uint idx_dw = lut_32bpp[lut][(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 >> 2u) * info.c1 * MICRO_TILE_SZ;
|
uint slice_offs = (z >> 2u) * info.c1 * MICRO_TILE_SZ;
|
||||||
uint tile_row = y / MICRO_TILE_DIM;
|
uint tile_row = y / MICRO_TILE_DIM;
|
||||||
|
@ -20,46 +20,46 @@ layout(push_constant) uniform image_info {
|
|||||||
uint c1;
|
uint c1;
|
||||||
} info;
|
} info;
|
||||||
|
|
||||||
const uint lut_64bpp[][64] = {
|
const uint lut_64bpp[][16] = {
|
||||||
{
|
{
|
||||||
0x00, 0x01, 0x08, 0x09, 0x40, 0x41, 0x48, 0x49,
|
0x09080100, 0x49484140,
|
||||||
0x02, 0x03, 0x0a, 0x0b, 0x42, 0x43, 0x4a, 0x4b,
|
0x0b0a0302, 0x4a4b4342,
|
||||||
0x10, 0x11, 0x18, 0x19, 0x50, 0x51, 0x58, 0x59,
|
0x19181110, 0x59585150,
|
||||||
0x12, 0x13, 0x1a, 0x1b, 0x52, 0x53, 0x5a, 0x5b,
|
0x1b1a1312, 0x5a5b5352,
|
||||||
0x80, 0x81, 0x88, 0x89, 0xc0, 0xc1, 0xc8, 0xc9,
|
0x89888180, 0xc9c8c1c0,
|
||||||
0x82, 0x83, 0x8a, 0x8b, 0xc2, 0xc3, 0xca, 0xcb,
|
0x8b8a8382, 0xcacbc3c2,
|
||||||
0x90, 0x91, 0x98, 0x99, 0xd0, 0xd1, 0xd8, 0xd9,
|
0x99989190, 0xd9d8d1d0,
|
||||||
0x92, 0x93, 0x9a, 0x9b, 0xd2, 0xd3, 0xda, 0xdb,
|
0x9b9a9392, 0xdbdad3d2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
0x04, 0x05, 0x0c, 0x0d, 0x44, 0x45, 0x4c, 0x4d,
|
0x0d0c0504, 0x4d4c4544,
|
||||||
0x06, 0x07, 0x0e, 0x0f, 0x46, 0x47, 0x4e, 0x4f,
|
0x0f0e0706, 0x4f4e4746,
|
||||||
0x14, 0x15, 0x1c, 0x1d, 0x54, 0x55, 0x5c, 0x5d,
|
0x1d1c1514, 0x5d5c5554,
|
||||||
0x16, 0x17, 0x1e, 0x1f, 0x56, 0x57, 0x5e, 0x5f,
|
0x1f1e1716, 0x5f5e5756,
|
||||||
0x84, 0x85, 0x8c, 0x8d, 0xc4, 0xc5, 0xcc, 0xcd,
|
0x8d8c8584, 0xcdccc5c4,
|
||||||
0x86, 0x87, 0x8e, 0x8f, 0xc6, 0xc7, 0xce, 0xcf,
|
0x8f8e8786, 0xcfcec7c6,
|
||||||
0x94, 0x95, 0x9c, 0x9d, 0xd4, 0xd5, 0xdc, 0xdd,
|
0x9d9c9594, 0xdddcd5d4,
|
||||||
0x96, 0x97, 0x9e, 0x9f, 0xd6, 0xd7, 0xde, 0xdf,
|
0x9f9e9796, 0xdfded7d6,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
0x20, 0x21, 0x28, 0x29, 0x60, 0x61, 0x68, 0x69,
|
0x29282120, 0x69686160,
|
||||||
0x22, 0x23, 0x2a, 0x2b, 0x62, 0x63, 0x6a, 0x6b,
|
0x2b2a2322, 0x6b6a6362,
|
||||||
0x30, 0x31, 0x38, 0x39, 0x70, 0x71, 0x78, 0x79,
|
0x39383130, 0x79787170,
|
||||||
0x32, 0x33, 0x3a, 0x3b, 0x72, 0x73, 0x7a, 0x7b,
|
0x3b3a3332, 0x7b7a7372,
|
||||||
0xa0, 0xa1, 0xa8, 0xa9, 0xe0, 0xe1, 0xe8, 0xe9,
|
0xa9a8a1a0, 0xe9e8e1e0,
|
||||||
0xa2, 0xa3, 0xaa, 0xab, 0xe2, 0xe3, 0xea, 0xeb,
|
0xabaaa3a2, 0xebeae3e2,
|
||||||
0xb0, 0xb1, 0xb8, 0xb9, 0xf0, 0xf1, 0xf8, 0xf9,
|
0xb9b8b1b0, 0xf9f8f1f0,
|
||||||
0xb2, 0xb3, 0xba, 0xbb, 0xf2, 0xf3, 0xfa, 0xfb,
|
0xbbbab3b2, 0xfbfaf3f2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
0x24, 0x25, 0x2c, 0x2d, 0x64, 0x65, 0x6c, 0x6d,
|
0x2d2c2524, 0x6d6c6564,
|
||||||
0x26, 0x27, 0x2e, 0x2f, 0x66, 0x67, 0x6e, 0x6f,
|
0x2f2e2726, 0x6f6e6766,
|
||||||
0x34, 0x35, 0x3c, 0x3d, 0x74, 0x75, 0x7c, 0x7d,
|
0x3d3c3534, 0x7d7c7574,
|
||||||
0x36, 0x37, 0x3e, 0x3f, 0x76, 0x77, 0x7e, 0x7f,
|
0x3f3e3736, 0x7f7e7776,
|
||||||
0xa4, 0xa5, 0xac, 0xad, 0xe4, 0xe5, 0xec, 0xed,
|
0xadaca5a4, 0xedece5e4,
|
||||||
0xa6, 0xa7, 0xae, 0xaf, 0xe6, 0xe7, 0xee, 0xef,
|
0xafaea7a6, 0xefeee7e6,
|
||||||
0xb4, 0xb5, 0xbc, 0xbd, 0xf4, 0xf5, 0xfc, 0xfd,
|
0xbdbcb5b4, 0xfdfcf5f4,
|
||||||
0xb6, 0xb7, 0xbe, 0xbf, 0xf6, 0xf7, 0xfe, 0xff,
|
0xbfbeb7b6, 0xfffef7f6,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -76,7 +76,9 @@ void main() {
|
|||||||
uint col = bitfieldExtract(x, 0, 3);
|
uint col = bitfieldExtract(x, 0, 3);
|
||||||
uint row = bitfieldExtract(y, 0, 3);
|
uint row = bitfieldExtract(y, 0, 3);
|
||||||
uint lut = bitfieldExtract(z, 0, 2);
|
uint lut = bitfieldExtract(z, 0, 2);
|
||||||
uint idx = lut_64bpp[lut][col + row * MICRO_TILE_DIM];
|
uint idx_dw = lut_64bpp[lut][(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 >> 2u) * info.c1 * MICRO_TILE_SZ;
|
uint slice_offs = (z >> 2u) * info.c1 * MICRO_TILE_SZ;
|
||||||
uint tile_row = y / MICRO_TILE_DIM;
|
uint tile_row = y / MICRO_TILE_DIM;
|
||||||
@ -85,7 +87,7 @@ void main() {
|
|||||||
uint offs = slice_offs + tile_offs + (idx * BPP / 8);
|
uint offs = slice_offs + tile_offs + (idx * BPP / 8);
|
||||||
|
|
||||||
uint p0 = in_data[(offs >> 2) + 0];
|
uint p0 = in_data[(offs >> 2) + 0];
|
||||||
uint p1 = in_data[(offs >> 2) + 1];
|
uint p1 = in_data[(offs >> 2) + 1];
|
||||||
out_data[2 * gl_GlobalInvocationID.x + 0] = p0;
|
out_data[2 * gl_GlobalInvocationID.x + 0] = p0;
|
||||||
out_data[2 * gl_GlobalInvocationID.x + 1] = p1;
|
out_data[2 * gl_GlobalInvocationID.x + 1] = p1;
|
||||||
}
|
}
|
||||||
|
101
src/video_core/host_shaders/detile_macro8x1.comp
Normal file
101
src/video_core/host_shaders/detile_macro8x1.comp
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// 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_8bpp[][16] = {
|
||||||
|
{
|
||||||
|
0x05040100, 0x45444140,
|
||||||
|
0x07060302, 0x47464342,
|
||||||
|
0x0d0c0908, 0x4d4c4948,
|
||||||
|
0x0f0e0b0a, 0x4f4e4b4a,
|
||||||
|
0x85848180, 0xc5c4c1c0,
|
||||||
|
0x87868382, 0xc7c6c3c2,
|
||||||
|
0x8d8c8988, 0xcdccc9c8,
|
||||||
|
0x8f8e8b8a, 0xcfcecbca,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x15141110, 0x55545150,
|
||||||
|
0x17161312, 0x57565352,
|
||||||
|
0x1d1c1918, 0x5d5c5958,
|
||||||
|
0x1f1e1b1a, 0x5f5e5b5a,
|
||||||
|
0x95949190, 0xd5d4d1d0,
|
||||||
|
0x97969392, 0xd7d6d3d2,
|
||||||
|
0x9d9c9998, 0xdddcd9d8,
|
||||||
|
0x9f9e9b9a, 0xdfdedbda,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x25242120, 0x65646160,
|
||||||
|
0x27262322, 0x67666362,
|
||||||
|
0x2d2c2928, 0x6d6c6968,
|
||||||
|
0x2f2e2b2a, 0x6f6e6b6a,
|
||||||
|
0xa5a4a1a0, 0xe5e4e1e0,
|
||||||
|
0xa7a6a3a2, 0xe7e6e3e2,
|
||||||
|
0xadaca9a8, 0xedece9e8,
|
||||||
|
0xafaeabaa, 0xefeeebea,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
0x35343130, 0x75747170,
|
||||||
|
0x37363332, 0x77767372,
|
||||||
|
0x3d3c3938, 0x7d7c7978,
|
||||||
|
0x3f3e3b3a, 0x7f7e7b7a,
|
||||||
|
0xb5b4b1b0, 0xf5f4f1f0,
|
||||||
|
0xb7b6b3b2, 0xf7f6f3f2,
|
||||||
|
0xbdbcb9b8, 0xfdfcf9f8,
|
||||||
|
0xbfbebbba, 0xfffefbfa,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MICRO_TILE_DIM (8)
|
||||||
|
#define MICRO_TILE_SZ (256)
|
||||||
|
#define TEXELS_PER_ELEMENT (1)
|
||||||
|
#define BPP (8)
|
||||||
|
|
||||||
|
shared uint scratch[16];
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
uint slot = gl_LocalInvocationID.x >> 2u;
|
||||||
|
atomicAnd(scratch[slot], 0);
|
||||||
|
|
||||||
|
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 lut = bitfieldExtract(z, 0, 2);
|
||||||
|
uint idx_dw = lut_8bpp[lut][(col + row * MICRO_TILE_DIM) >> 2u];
|
||||||
|
uint byte_ofs = (gl_LocalInvocationID.x & 3u) * 8;
|
||||||
|
uint idx = bitfieldExtract(idx_dw >> byte_ofs, 0, 8);
|
||||||
|
|
||||||
|
uint slice_offs = (z >> 2u) * 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 / 8);
|
||||||
|
|
||||||
|
uint p0 = in_data[offs >> 2u];
|
||||||
|
uint byte = bitfieldExtract(p0 >> (offs * 8), 0, 8);
|
||||||
|
atomicOr(scratch[slot], byte << byte_ofs);
|
||||||
|
|
||||||
|
if (byte_ofs == 0) {
|
||||||
|
out_data[gl_GlobalInvocationID.x >> 2u] = scratch[slot];
|
||||||
|
}
|
||||||
|
}
|
@ -39,6 +39,15 @@ public:
|
|||||||
return &(*first_level_map[l1_page])[l2_page];
|
return &(*first_level_map[l1_page])[l2_page];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] const Entry* find(size_t page) const {
|
||||||
|
const size_t l1_page = page >> SecondLevelBits;
|
||||||
|
const size_t l2_page = page & (NumEntriesPerL1Page - 1);
|
||||||
|
if (!first_level_map[l1_page]) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &(*first_level_map[l1_page])[l2_page];
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] const Entry& operator[](size_t page) const {
|
[[nodiscard]] const Entry& operator[](size_t page) const {
|
||||||
const size_t l1_page = page >> SecondLevelBits;
|
const size_t l1_page = page >> SecondLevelBits;
|
||||||
const size_t l2_page = page & (NumEntriesPerL1Page - 1);
|
const size_t l2_page = page & (NumEntriesPerL1Page - 1);
|
||||||
|
@ -185,7 +185,7 @@ void PageManager::OnGpuUnmap(VAddr address, size_t size) {
|
|||||||
void PageManager::UpdatePagesCachedCount(VAddr addr, u64 size, s32 delta) {
|
void PageManager::UpdatePagesCachedCount(VAddr addr, u64 size, s32 delta) {
|
||||||
static constexpr u64 PageShift = 12;
|
static constexpr u64 PageShift = 12;
|
||||||
|
|
||||||
std::scoped_lock lk{mutex};
|
std::scoped_lock lk{lock};
|
||||||
const u64 num_pages = ((addr + size - 1) >> PageShift) - (addr >> PageShift) + 1;
|
const u64 num_pages = ((addr + size - 1) >> PageShift) - (addr >> PageShift) + 1;
|
||||||
const u64 page_start = addr >> PageShift;
|
const u64 page_start = addr >> PageShift;
|
||||||
const u64 page_end = page_start + num_pages;
|
const u64 page_end = page_start + num_pages;
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
#include <boost/icl/interval_map.hpp>
|
#include <boost/icl/interval_map.hpp>
|
||||||
|
#include "common/spin_lock.h"
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
|
|
||||||
namespace Vulkan {
|
namespace Vulkan {
|
||||||
@ -35,8 +35,8 @@ private:
|
|||||||
struct Impl;
|
struct Impl;
|
||||||
std::unique_ptr<Impl> impl;
|
std::unique_ptr<Impl> impl;
|
||||||
Vulkan::Rasterizer* rasterizer;
|
Vulkan::Rasterizer* rasterizer;
|
||||||
std::mutex mutex;
|
|
||||||
boost::icl::interval_map<VAddr, s32> cached_pages;
|
boost::icl::interval_map<VAddr, s32> cached_pages;
|
||||||
|
Common::SpinLock lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
@ -691,16 +691,40 @@ std::span<const SurfaceFormatInfo> SurfaceFormats() {
|
|||||||
return formats;
|
return formats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Table 8.13 Data and Image Formats [Sea Islands Series Instruction Set Architecture]
|
||||||
|
static const size_t amd_gpu_data_format_bit_size = 6; // All values are under 64
|
||||||
|
static const size_t amd_gpu_number_format_bit_size = 4; // All values are under 16
|
||||||
|
|
||||||
|
static size_t GetSurfaceFormatTableIndex(AmdGpu::DataFormat data_format,
|
||||||
|
AmdGpu::NumberFormat num_format) {
|
||||||
|
DEBUG_ASSERT(u32(data_format) < 1 << amd_gpu_data_format_bit_size);
|
||||||
|
DEBUG_ASSERT(u32(num_format) < 1 << amd_gpu_number_format_bit_size);
|
||||||
|
size_t result = static_cast<size_t>(num_format) |
|
||||||
|
(static_cast<size_t>(data_format) << amd_gpu_number_format_bit_size);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto surface_format_table = []() constexpr {
|
||||||
|
std::array<vk::Format, 1 << amd_gpu_data_format_bit_size * 1 << amd_gpu_number_format_bit_size>
|
||||||
|
result;
|
||||||
|
for (auto& entry : result) {
|
||||||
|
entry = vk::Format::eUndefined;
|
||||||
|
}
|
||||||
|
for (const auto& supported_format : SurfaceFormats()) {
|
||||||
|
result[GetSurfaceFormatTableIndex(supported_format.data_format,
|
||||||
|
supported_format.number_format)] =
|
||||||
|
supported_format.vk_format;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}();
|
||||||
|
|
||||||
vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) {
|
vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat num_format) {
|
||||||
const auto& formats = SurfaceFormats();
|
vk::Format result = surface_format_table[GetSurfaceFormatTableIndex(data_format, num_format)];
|
||||||
const auto format =
|
bool found =
|
||||||
std::find_if(formats.begin(), formats.end(), [&](const SurfaceFormatInfo& format_info) {
|
result != vk::Format::eUndefined || data_format == AmdGpu::DataFormat::FormatInvalid;
|
||||||
return format_info.data_format == data_format &&
|
ASSERT_MSG(found, "Unknown data_format={} and num_format={}", static_cast<u32>(data_format),
|
||||||
format_info.number_format == num_format;
|
static_cast<u32>(num_format));
|
||||||
});
|
return result;
|
||||||
ASSERT_MSG(format != formats.end(), "Unknown data_format={} and num_format={}",
|
|
||||||
static_cast<u32>(data_format), static_cast<u32>(num_format));
|
|
||||||
return format->vk_format;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr DepthFormatInfo CreateDepthFormatInfo(
|
static constexpr DepthFormatInfo CreateDepthFormatInfo(
|
||||||
@ -746,8 +770,8 @@ vk::Format DepthFormat(DepthBuffer::ZFormat z_format, DepthBuffer::StencilFormat
|
|||||||
|
|
||||||
vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer) {
|
vk::ClearValue ColorBufferClearValue(const AmdGpu::Liverpool::ColorBuffer& color_buffer) {
|
||||||
const auto comp_swizzle = color_buffer.Swizzle();
|
const auto comp_swizzle = color_buffer.Swizzle();
|
||||||
const auto format = color_buffer.DataFormat();
|
const auto format = color_buffer.GetDataFmt();
|
||||||
const auto number_type = color_buffer.NumFormat();
|
const auto number_type = color_buffer.GetNumberFmt();
|
||||||
|
|
||||||
const auto& c0 = color_buffer.clear_word0;
|
const auto& c0 = color_buffer.clear_word0;
|
||||||
const auto& c1 = color_buffer.clear_word1;
|
const auto& c1 = color_buffer.clear_word1;
|
||||||
|
@ -328,8 +328,8 @@ bool PipelineCache::RefreshGraphicsKey() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
key.color_formats[remapped_cb] =
|
key.color_formats[remapped_cb] =
|
||||||
LiverpoolToVK::SurfaceFormat(col_buf.DataFormat(), col_buf.NumFormat());
|
LiverpoolToVK::SurfaceFormat(col_buf.GetDataFmt(), col_buf.GetNumberFmt());
|
||||||
key.color_num_formats[remapped_cb] = col_buf.NumFormat();
|
key.color_num_formats[remapped_cb] = col_buf.GetNumberFmt();
|
||||||
key.color_swizzles[remapped_cb] = col_buf.Swizzle();
|
key.color_swizzles[remapped_cb] = col_buf.Swizzle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,6 +562,12 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding
|
|||||||
push_data.AddOffset(binding.buffer, adjust);
|
push_data.AddOffset(binding.buffer, adjust);
|
||||||
buffer_infos.emplace_back(vk_buffer->Handle(), offset_aligned,
|
buffer_infos.emplace_back(vk_buffer->Handle(), offset_aligned,
|
||||||
vsharp.GetSize() + adjust);
|
vsharp.GetSize() + adjust);
|
||||||
|
if (auto barrier =
|
||||||
|
vk_buffer->GetBarrier(desc.is_written ? vk::AccessFlagBits2::eShaderWrite
|
||||||
|
: vk::AccessFlagBits2::eShaderRead,
|
||||||
|
vk::PipelineStageFlagBits2::eAllCommands)) {
|
||||||
|
buffer_barriers.emplace_back(*barrier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
set_writes.push_back({
|
set_writes.push_back({
|
||||||
@ -600,7 +606,7 @@ void Rasterizer::BindBuffers(const Shader::Info& stage, Shader::Backend::Binding
|
|||||||
if (auto barrier =
|
if (auto barrier =
|
||||||
vk_buffer->GetBarrier(desc.is_written ? vk::AccessFlagBits2::eShaderWrite
|
vk_buffer->GetBarrier(desc.is_written ? vk::AccessFlagBits2::eShaderWrite
|
||||||
: vk::AccessFlagBits2::eShaderRead,
|
: vk::AccessFlagBits2::eShaderRead,
|
||||||
vk::PipelineStageFlagBits2::eComputeShader)) {
|
vk::PipelineStageFlagBits2::eAllCommands)) {
|
||||||
buffer_barriers.emplace_back(*barrier);
|
buffer_barriers.emplace_back(*barrier);
|
||||||
}
|
}
|
||||||
if (desc.is_written) {
|
if (desc.is_written) {
|
||||||
|
@ -265,9 +265,9 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer,
|
|||||||
const AmdGpu::Liverpool::CbDbExtent& hint /*= {}*/) noexcept {
|
const AmdGpu::Liverpool::CbDbExtent& hint /*= {}*/) noexcept {
|
||||||
props.is_tiled = buffer.IsTiled();
|
props.is_tiled = buffer.IsTiled();
|
||||||
tiling_mode = buffer.GetTilingMode();
|
tiling_mode = buffer.GetTilingMode();
|
||||||
pixel_format = LiverpoolToVK::SurfaceFormat(buffer.DataFormat(), buffer.NumFormat());
|
pixel_format = LiverpoolToVK::SurfaceFormat(buffer.GetDataFmt(), buffer.GetNumberFmt());
|
||||||
num_samples = buffer.NumSamples();
|
num_samples = buffer.NumSamples();
|
||||||
num_bits = NumBits(buffer.DataFormat());
|
num_bits = NumBits(buffer.GetDataFmt());
|
||||||
type = vk::ImageType::e2D;
|
type = vk::ImageType::e2D;
|
||||||
size.width = hint.Valid() ? hint.width : buffer.Pitch();
|
size.width = hint.Valid() ? hint.width : buffer.Pitch();
|
||||||
size.height = hint.Valid() ? hint.height : buffer.Height();
|
size.height = hint.Valid() ? hint.height : buffer.Height();
|
||||||
|
@ -76,7 +76,8 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer) n
|
|||||||
range.base.layer = col_buffer.view.slice_start;
|
range.base.layer = col_buffer.view.slice_start;
|
||||||
range.extent.layers = col_buffer.NumSlices() - range.base.layer;
|
range.extent.layers = col_buffer.NumSlices() - range.base.layer;
|
||||||
type = range.extent.layers > 1 ? vk::ImageViewType::e2DArray : vk::ImageViewType::e2D;
|
type = range.extent.layers > 1 ? vk::ImageViewType::e2DArray : vk::ImageViewType::e2D;
|
||||||
format = Vulkan::LiverpoolToVK::SurfaceFormat(col_buffer.DataFormat(), col_buffer.NumFormat());
|
format =
|
||||||
|
Vulkan::LiverpoolToVK::SurfaceFormat(col_buffer.GetDataFmt(), col_buffer.GetNumberFmt());
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::DepthBuffer& depth_buffer,
|
ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::DepthBuffer& depth_buffer,
|
||||||
|
@ -542,31 +542,62 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule
|
|||||||
sched_ptr->EndRendering();
|
sched_ptr->EndRendering();
|
||||||
|
|
||||||
const auto cmdbuf = sched_ptr->CommandBuffer();
|
const auto cmdbuf = sched_ptr->CommandBuffer();
|
||||||
image.Transit(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite, {},
|
|
||||||
cmdbuf);
|
|
||||||
|
|
||||||
const VAddr image_addr = image.info.guest_address;
|
const VAddr image_addr = image.info.guest_address;
|
||||||
const size_t image_size = image.info.guest_size_bytes;
|
const size_t image_size = image.info.guest_size_bytes;
|
||||||
const auto [vk_buffer, buf_offset] =
|
const auto [vk_buffer, buf_offset] =
|
||||||
buffer_cache.ObtainViewBuffer(image_addr, image_size, is_gpu_dirty);
|
buffer_cache.ObtainViewBuffer(image_addr, image_size, is_gpu_dirty);
|
||||||
|
|
||||||
// The obtained buffer may be written by a shader so we need to emit a barrier to prevent RAW
|
// The obtained buffer may be written by a shader so we need to emit a barrier to prevent RAW
|
||||||
// hazard
|
// hazard
|
||||||
if (auto barrier = vk_buffer->GetBarrier(vk::AccessFlagBits2::eTransferRead,
|
if (auto barrier = vk_buffer->GetBarrier(vk::AccessFlagBits2::eTransferRead,
|
||||||
vk::PipelineStageFlagBits2::eTransfer)) {
|
vk::PipelineStageFlagBits2::eTransfer)) {
|
||||||
const auto dependencies = vk::DependencyInfo{
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
.bufferMemoryBarrierCount = 1,
|
.bufferMemoryBarrierCount = 1,
|
||||||
.pBufferMemoryBarriers = &barrier.value(),
|
.pBufferMemoryBarriers = &barrier.value(),
|
||||||
};
|
});
|
||||||
cmdbuf.pipelineBarrier2(dependencies);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto [buffer, offset] = tile_manager.TryDetile(vk_buffer->Handle(), buf_offset, image);
|
const auto [buffer, offset] =
|
||||||
|
tile_manager.TryDetile(vk_buffer->Handle(), buf_offset, image.info);
|
||||||
for (auto& copy : image_copy) {
|
for (auto& copy : image_copy) {
|
||||||
copy.bufferOffset += offset;
|
copy.bufferOffset += offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const vk::BufferMemoryBarrier2 pre_barrier{
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eMemoryWrite,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eTransferRead,
|
||||||
|
.buffer = buffer,
|
||||||
|
.offset = offset,
|
||||||
|
.size = image_size,
|
||||||
|
};
|
||||||
|
const vk::BufferMemoryBarrier2 post_barrier{
|
||||||
|
.srcStageMask = vk::PipelineStageFlagBits2::eTransfer,
|
||||||
|
.srcAccessMask = vk::AccessFlagBits2::eTransferWrite,
|
||||||
|
.dstStageMask = vk::PipelineStageFlagBits2::eAllCommands,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits2::eMemoryRead | vk::AccessFlagBits2::eMemoryWrite,
|
||||||
|
.buffer = buffer,
|
||||||
|
.offset = offset,
|
||||||
|
.size = image_size,
|
||||||
|
};
|
||||||
|
const auto image_barriers =
|
||||||
|
image.GetBarriers(vk::ImageLayout::eTransferDstOptimal, vk::AccessFlagBits2::eTransferWrite,
|
||||||
|
vk::PipelineStageFlagBits2::eTransfer, {});
|
||||||
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
|
.bufferMemoryBarrierCount = 1,
|
||||||
|
.pBufferMemoryBarriers = &pre_barrier,
|
||||||
|
.imageMemoryBarrierCount = static_cast<u32>(image_barriers.size()),
|
||||||
|
.pImageMemoryBarriers = image_barriers.data(),
|
||||||
|
});
|
||||||
cmdbuf.copyBufferToImage(buffer, image.image, vk::ImageLayout::eTransferDstOptimal, image_copy);
|
cmdbuf.copyBufferToImage(buffer, image.image, vk::ImageLayout::eTransferDstOptimal, image_copy);
|
||||||
|
cmdbuf.pipelineBarrier2(vk::DependencyInfo{
|
||||||
|
.dependencyFlags = vk::DependencyFlagBits::eByRegion,
|
||||||
|
.bufferMemoryBarrierCount = 1,
|
||||||
|
.pBufferMemoryBarriers = &post_barrier,
|
||||||
|
});
|
||||||
image.flags &= ~ImageFlagBits::Dirty;
|
image.flags &= ~ImageFlagBits::Dirty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#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/renderer_vulkan/vk_shader_util.h"
|
#include "video_core/renderer_vulkan/vk_shader_util.h"
|
||||||
|
#include "video_core/texture_cache/image_info.h"
|
||||||
#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"
|
||||||
|
|
||||||
@ -14,6 +15,7 @@
|
|||||||
#include "video_core/host_shaders/detile_m8x2_comp.h"
|
#include "video_core/host_shaders/detile_m8x2_comp.h"
|
||||||
#include "video_core/host_shaders/detile_macro32x1_comp.h"
|
#include "video_core/host_shaders/detile_macro32x1_comp.h"
|
||||||
#include "video_core/host_shaders/detile_macro32x2_comp.h"
|
#include "video_core/host_shaders/detile_macro32x2_comp.h"
|
||||||
|
#include "video_core/host_shaders/detile_macro8x1_comp.h"
|
||||||
|
|
||||||
#include <boost/container/static_vector.hpp>
|
#include <boost/container/static_vector.hpp>
|
||||||
#include <magic_enum/magic_enum.hpp>
|
#include <magic_enum/magic_enum.hpp>
|
||||||
@ -32,6 +34,7 @@ static vk::Format DemoteImageFormatForDetiling(vk::Format format) {
|
|||||||
case vk::Format::eR5G5B5A1UnormPack16:
|
case vk::Format::eR5G5B5A1UnormPack16:
|
||||||
case vk::Format::eR8G8Unorm:
|
case vk::Format::eR8G8Unorm:
|
||||||
case vk::Format::eR16Sfloat:
|
case vk::Format::eR16Sfloat:
|
||||||
|
case vk::Format::eR16Uint:
|
||||||
case vk::Format::eR16Unorm:
|
case vk::Format::eR16Unorm:
|
||||||
case vk::Format::eD16Unorm:
|
case vk::Format::eD16Unorm:
|
||||||
return vk::Format::eR8G8Uint;
|
return vk::Format::eR8G8Uint;
|
||||||
@ -85,10 +88,10 @@ static vk::Format DemoteImageFormatForDetiling(vk::Format format) {
|
|||||||
return format;
|
return format;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DetilerContext* TileManager::GetDetiler(const Image& image) const {
|
const DetilerContext* TileManager::GetDetiler(const ImageInfo& info) const {
|
||||||
const auto format = DemoteImageFormatForDetiling(image.info.pixel_format);
|
const auto format = DemoteImageFormatForDetiling(info.pixel_format);
|
||||||
|
|
||||||
switch (image.info.tiling_mode) {
|
switch (info.tiling_mode) {
|
||||||
case AmdGpu::TilingMode::Texture_MicroTiled:
|
case AmdGpu::TilingMode::Texture_MicroTiled:
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case vk::Format::eR8Uint:
|
case vk::Format::eR8Uint:
|
||||||
@ -106,6 +109,8 @@ const DetilerContext* TileManager::GetDetiler(const Image& image) const {
|
|||||||
}
|
}
|
||||||
case AmdGpu::TilingMode::Texture_Volume:
|
case AmdGpu::TilingMode::Texture_Volume:
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
case vk::Format::eR8Uint:
|
||||||
|
return &detilers[DetilerType::Macro8x1];
|
||||||
case vk::Format::eR32Uint:
|
case vk::Format::eR32Uint:
|
||||||
return &detilers[DetilerType::Macro32x1];
|
return &detilers[DetilerType::Macro32x1];
|
||||||
case vk::Format::eR32G32Uint:
|
case vk::Format::eR32G32Uint:
|
||||||
@ -131,8 +136,8 @@ TileManager::TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& sc
|
|||||||
static const std::array detiler_shaders{
|
static const std::array detiler_shaders{
|
||||||
HostShaders::DETILE_M8X1_COMP, HostShaders::DETILE_M8X2_COMP,
|
HostShaders::DETILE_M8X1_COMP, HostShaders::DETILE_M8X2_COMP,
|
||||||
HostShaders::DETILE_M32X1_COMP, HostShaders::DETILE_M32X2_COMP,
|
HostShaders::DETILE_M32X1_COMP, HostShaders::DETILE_M32X2_COMP,
|
||||||
HostShaders::DETILE_M32X4_COMP, HostShaders::DETILE_MACRO32X1_COMP,
|
HostShaders::DETILE_M32X4_COMP, HostShaders::DETILE_MACRO8X1_COMP,
|
||||||
HostShaders::DETILE_MACRO32X2_COMP,
|
HostShaders::DETILE_MACRO32X1_COMP, HostShaders::DETILE_MACRO32X2_COMP,
|
||||||
};
|
};
|
||||||
|
|
||||||
boost::container::static_vector<vk::DescriptorSetLayoutBinding, 2> bindings{
|
boost::container::static_vector<vk::DescriptorSetLayoutBinding, 2> bindings{
|
||||||
@ -257,23 +262,23 @@ void TileManager::FreeBuffer(ScratchBuffer buffer) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::pair<vk::Buffer, u32> TileManager::TryDetile(vk::Buffer in_buffer, u32 in_offset,
|
std::pair<vk::Buffer, u32> TileManager::TryDetile(vk::Buffer in_buffer, u32 in_offset,
|
||||||
Image& image) {
|
const ImageInfo& info) {
|
||||||
if (!image.info.props.is_tiled) {
|
if (!info.props.is_tiled) {
|
||||||
return {in_buffer, in_offset};
|
return {in_buffer, in_offset};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto* detiler = GetDetiler(image);
|
const auto* detiler = GetDetiler(info);
|
||||||
if (!detiler) {
|
if (!detiler) {
|
||||||
if (image.info.tiling_mode != AmdGpu::TilingMode::Texture_MacroTiled &&
|
if (info.tiling_mode != AmdGpu::TilingMode::Texture_MacroTiled &&
|
||||||
image.info.tiling_mode != AmdGpu::TilingMode::Display_MacroTiled &&
|
info.tiling_mode != AmdGpu::TilingMode::Display_MacroTiled &&
|
||||||
image.info.tiling_mode != AmdGpu::TilingMode::Depth_MacroTiled) {
|
info.tiling_mode != AmdGpu::TilingMode::Depth_MacroTiled) {
|
||||||
LOG_ERROR(Render_Vulkan, "Unsupported tiled image: {} ({})",
|
LOG_ERROR(Render_Vulkan, "Unsupported tiled image: {} ({})",
|
||||||
vk::to_string(image.info.pixel_format), NameOf(image.info.tiling_mode));
|
vk::to_string(info.pixel_format), NameOf(info.tiling_mode));
|
||||||
}
|
}
|
||||||
return {in_buffer, in_offset};
|
return {in_buffer, in_offset};
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 image_size = image.info.guest_size_bytes;
|
const u32 image_size = info.guest_size_bytes;
|
||||||
|
|
||||||
// Prepare output buffer
|
// Prepare output buffer
|
||||||
auto out_buffer = AllocBuffer(image_size, true);
|
auto out_buffer = AllocBuffer(image_size, true);
|
||||||
@ -316,22 +321,20 @@ std::pair<vk::Buffer, u32> TileManager::TryDetile(vk::Buffer in_buffer, u32 in_o
|
|||||||
set_writes);
|
set_writes);
|
||||||
|
|
||||||
DetilerParams params;
|
DetilerParams params;
|
||||||
params.num_levels = image.info.resources.levels;
|
params.num_levels = info.resources.levels;
|
||||||
params.pitch0 = image.info.pitch >> (image.info.props.is_block ? 2u : 0u);
|
params.pitch0 = info.pitch >> (info.props.is_block ? 2u : 0u);
|
||||||
params.height = image.info.size.height;
|
params.height = info.size.height;
|
||||||
if (image.info.tiling_mode == AmdGpu::TilingMode::Texture_Volume) {
|
if (info.tiling_mode == AmdGpu::TilingMode::Texture_Volume) {
|
||||||
ASSERT(image.info.resources.levels == 1);
|
ASSERT(info.resources.levels == 1);
|
||||||
ASSERT(image.info.num_bits >= 32);
|
const auto tiles_per_row = info.pitch / 8u;
|
||||||
const auto tiles_per_row = image.info.pitch / 8u;
|
const auto tiles_per_slice = tiles_per_row * ((info.size.height + 7u) / 8u);
|
||||||
const auto tiles_per_slice = tiles_per_row * ((image.info.size.height + 7u) / 8u);
|
|
||||||
params.sizes[0] = tiles_per_row;
|
params.sizes[0] = tiles_per_row;
|
||||||
params.sizes[1] = tiles_per_slice;
|
params.sizes[1] = tiles_per_slice;
|
||||||
} else {
|
} else {
|
||||||
|
ASSERT(info.resources.levels <= 14);
|
||||||
ASSERT(image.info.resources.levels <= 14);
|
|
||||||
std::memset(¶ms.sizes, 0, sizeof(params.sizes));
|
std::memset(¶ms.sizes, 0, sizeof(params.sizes));
|
||||||
for (int m = 0; m < image.info.resources.levels; ++m) {
|
for (int m = 0; m < info.resources.levels; ++m) {
|
||||||
params.sizes[m] = image.info.mips_layout[m].size * image.info.resources.layers +
|
params.sizes[m] = info.mips_layout[m].size * info.resources.layers +
|
||||||
(m > 0 ? params.sizes[m - 1] : 0);
|
(m > 0 ? params.sizes[m - 1] : 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -340,20 +343,9 @@ std::pair<vk::Buffer, u32> TileManager::TryDetile(vk::Buffer in_buffer, u32 in_o
|
|||||||
¶ms);
|
¶ms);
|
||||||
|
|
||||||
ASSERT((image_size % 64) == 0);
|
ASSERT((image_size % 64) == 0);
|
||||||
const auto bpp = image.info.num_bits * (image.info.props.is_block ? 16u : 1u);
|
const auto bpp = info.num_bits * (info.props.is_block ? 16u : 1u);
|
||||||
const auto num_tiles = image_size / (64 * (bpp / 8));
|
const auto num_tiles = image_size / (64 * (bpp / 8));
|
||||||
cmdbuf.dispatch(num_tiles, 1, 1);
|
cmdbuf.dispatch(num_tiles, 1, 1);
|
||||||
|
|
||||||
const vk::BufferMemoryBarrier post_barrier{
|
|
||||||
.srcAccessMask = vk::AccessFlagBits::eShaderWrite,
|
|
||||||
.dstAccessMask = vk::AccessFlagBits::eTransferRead,
|
|
||||||
.buffer = out_buffer.first,
|
|
||||||
.size = image_size,
|
|
||||||
};
|
|
||||||
cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eComputeShader,
|
|
||||||
vk::PipelineStageFlagBits::eTransfer, vk::DependencyFlagBits::eByRegion,
|
|
||||||
{}, post_barrier, {});
|
|
||||||
|
|
||||||
return {out_buffer.first, 0};
|
return {out_buffer.first, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,11 +5,11 @@
|
|||||||
|
|
||||||
#include "common/types.h"
|
#include "common/types.h"
|
||||||
#include "video_core/buffer_cache/buffer.h"
|
#include "video_core/buffer_cache/buffer.h"
|
||||||
#include "video_core/texture_cache/image.h"
|
|
||||||
|
|
||||||
namespace VideoCore {
|
namespace VideoCore {
|
||||||
|
|
||||||
class TextureCache;
|
class TextureCache;
|
||||||
|
struct ImageInfo;
|
||||||
|
|
||||||
enum DetilerType : u32 {
|
enum DetilerType : u32 {
|
||||||
Micro8x1,
|
Micro8x1,
|
||||||
@ -18,6 +18,7 @@ enum DetilerType : u32 {
|
|||||||
Micro32x2,
|
Micro32x2,
|
||||||
Micro32x4,
|
Micro32x4,
|
||||||
|
|
||||||
|
Macro8x1,
|
||||||
Macro32x1,
|
Macro32x1,
|
||||||
Macro32x2,
|
Macro32x2,
|
||||||
|
|
||||||
@ -36,14 +37,15 @@ public:
|
|||||||
TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler);
|
TileManager(const Vulkan::Instance& instance, Vulkan::Scheduler& scheduler);
|
||||||
~TileManager();
|
~TileManager();
|
||||||
|
|
||||||
std::pair<vk::Buffer, u32> TryDetile(vk::Buffer in_buffer, u32 in_offset, Image& image);
|
std::pair<vk::Buffer, u32> TryDetile(vk::Buffer in_buffer, u32 in_offset,
|
||||||
|
const ImageInfo& info);
|
||||||
|
|
||||||
ScratchBuffer AllocBuffer(u32 size, bool is_storage = false);
|
ScratchBuffer AllocBuffer(u32 size, bool is_storage = false);
|
||||||
void Upload(ScratchBuffer buffer, const void* data, size_t size);
|
void Upload(ScratchBuffer buffer, const void* data, size_t size);
|
||||||
void FreeBuffer(ScratchBuffer buffer);
|
void FreeBuffer(ScratchBuffer buffer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const DetilerContext* GetDetiler(const Image& image) const;
|
const DetilerContext* GetDetiler(const ImageInfo& info) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Vulkan::Instance& instance;
|
const Vulkan::Instance& instance;
|
||||||
|
Loading…
Reference in New Issue
Block a user