diff --git a/src/core/devtools/widget/reg_popup.cpp b/src/core/devtools/widget/reg_popup.cpp index 2727e1745..fae620901 100644 --- a/src/core/devtools/widget/reg_popup.cpp +++ b/src/core/devtools/widget/reg_popup.cpp @@ -66,7 +66,7 @@ void RegPopup::DrawColorBuffer(const AmdGpu::Liverpool::ColorBuffer& buffer) { "GetColorSliceSize()", buffer.GetColorSliceSize(), "GetTilingMode()", buffer.GetTilingMode(), "IsTiled()", buffer.IsTiled(), - "NumFormat()", buffer.NumFormat() + "NumFormat()", buffer.GetNumberFmt() ); // clang-format on diff --git a/src/core/libraries/audio/audioout.cpp b/src/core/libraries/audio/audioout.cpp index d69454c39..f0ad59c3b 100644 --- a/src/core/libraries/audio/audioout.cpp +++ b/src/core/libraries/audio/audioout.cpp @@ -3,13 +3,13 @@ #include #include -#include +#include +#include #include #include "common/assert.h" #include "common/config.h" #include "common/logging/log.h" -#include "common/polyfill_thread.h" #include "common/thread.h" #include "core/libraries/audio/audioout.h" #include "core/libraries/audio/audioout_backend.h" @@ -18,7 +18,7 @@ namespace Libraries::AudioOut { -std::shared_mutex ports_mutex; +std::mutex port_open_mutex{}; std::array ports_out{}; static std::unique_ptr audio; @@ -93,17 +93,20 @@ int PS4_SYSV_ABI sceAudioOutClose(s32 handle) { 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); - 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(); - std::free(port.output_buffer); - port.output_buffer = nullptr; - port.output_ready = false; - port.impl = nullptr; return ORBIS_OK; } @@ -172,35 +175,34 @@ int PS4_SYSV_ABI sceAudioOutGetPortState(s32 handle, OrbisAudioOutPortState* sta return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; } - std::scoped_lock lock(ports_mutex); - const auto& port = ports_out.at(handle - 1); - if (!port.impl) { - return ORBIS_AUDIO_OUT_ERROR_INVALID_PORT; + auto& port = ports_out.at(handle - 1); + { + std::unique_lock lock{port.mutex}; + 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; } @@ -279,15 +281,16 @@ static void AudioOutputThread(PortOut* port, const std::stop_token& stop) { while (true) { timer.Start(); { - std::unique_lock lock{port->output_mutex}; - Common::CondvarWait(port->output_cv, lock, stop, [&] { return port->output_ready; }); - if (stop.stop_requested()) { - break; + std::unique_lock lock{port->mutex}; + if (port->output_cv.wait(lock, stop, [&] { return port->output_ready; })) { + port->impl->Output(port->output_buffer); + port->output_ready = false; } - port->impl->Output(port->output_buffer); - port->output_ready = false; } port->output_cv.notify_one(); + if (stop.stop_requested()) { + break; + } timer.End(); } } @@ -332,27 +335,30 @@ s32 PS4_SYSV_ABI sceAudioOutOpen(UserService::OrbisUserServiceUserId user_id, return ORBIS_AUDIO_OUT_ERROR_INVALID_FORMAT; } - std::scoped_lock lock{ports_mutex}; + std::unique_lock open_lock{port_open_mutex}; 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()) { LOG_ERROR(Lib_AudioOut, "Audio ports are full"); return ORBIS_AUDIO_OUT_ERROR_PORT_FULL; } - 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); + { + std::unique_lock port_lock(port->mutex); - 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->output_ready = false; - port->output_thread.Run( - [port](const std::stop_token& stop) { AudioOutputThread(&*port, stop); }); + port->impl = audio->Open(*port); + 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; } @@ -367,14 +373,13 @@ s32 PS4_SYSV_ABI sceAudioOutOutput(s32 handle, void* ptr) { } 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; }); - if (ptr != nullptr) { + if (ptr != nullptr && port.IsOpen()) { std::memcpy(port.output_buffer, ptr, port.BufferSize()); 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; } - std::scoped_lock lock(ports_mutex); auto& port = ports_out.at(handle - 1); - if (!port.impl) { - 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]; + { + 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]; + } + } + port.impl->SetVolume(port.volume); } - - port.impl->SetVolume(port.volume); return ORBIS_OK; } diff --git a/src/core/libraries/audio/audioout.h b/src/core/libraries/audio/audioout.h index 4f7378dcd..5eafb43a1 100644 --- a/src/core/libraries/audio/audioout.h +++ b/src/core/libraries/audio/audioout.h @@ -3,7 +3,9 @@ #pragma once +#include #include +#include #include "common/bit_field.h" #include "core/libraries/kernel/threads.h" @@ -74,10 +76,10 @@ struct AudioFormatInfo { }; struct PortOut { + std::mutex mutex; std::unique_ptr impl{}; void* output_buffer; - std::mutex output_mutex; std::condition_variable_any output_cv; bool output_ready; Kernel::Thread output_thread{}; @@ -88,6 +90,10 @@ struct PortOut { u32 buffer_frames; std::array volume; + [[nodiscard]] bool IsOpen() const { + return impl != nullptr; + } + [[nodiscard]] u32 BufferSize() const { return buffer_frames * format_info.FrameSize(); } diff --git a/src/core/libraries/audio/sdl_audio.cpp b/src/core/libraries/audio/sdl_audio.cpp index 59d2d5cfb..762a9f682 100644 --- a/src/core/libraries/audio/sdl_audio.cpp +++ b/src/core/libraries/audio/sdl_audio.cpp @@ -14,7 +14,7 @@ namespace Libraries::AudioOut { class SDLPortBackend : public PortBackend { public: 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, // so set the sample frames hint to the number of frames per buffer. 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()); return; } - queue_threshold = CalculateQueueThreshold(); + CalculateQueueThreshold(); if (!SDL_SetAudioStreamInputChannelMap(stream, port.format_info.channel_layout.data(), port.format_info.num_channels)) { LOG_ERROR(Lib_AudioOut, "Failed to configure SDL audio stream channel map: {}", @@ -71,9 +71,9 @@ public: queue_threshold); SDL_ClearAudioStream(stream); // Recalculate the threshold in case this happened because of a device change. - queue_threshold = CalculateQueueThreshold(); + CalculateQueueThreshold(); } - if (!SDL_PutAudioStreamData(stream, ptr, static_cast(buffer_size))) { + if (!SDL_PutAudioStreamData(stream, ptr, static_cast(guest_buffer_size))) { LOG_ERROR(Lib_AudioOut, "Failed to output to SDL audio stream: {}", SDL_GetError()); } } @@ -91,7 +91,7 @@ public: } private: - [[nodiscard]] u32 CalculateQueueThreshold() const { + void CalculateQueueThreshold() { SDL_AudioSpec discard; int sdl_buffer_frames; if (!SDL_GetAudioDeviceFormat(SDL_GetAudioStreamDevice(stream), &discard, @@ -100,13 +100,22 @@ private: SDL_GetError()); sdl_buffer_frames = 0; } - return std::max(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 buffer_size; - u32 queue_threshold; - SDL_AudioStream* stream; + u32 guest_buffer_size; + u32 host_buffer_size{}; + u32 queue_threshold{}; + SDL_AudioStream* stream{}; }; std::unique_ptr SDLAudioOut::Open(PortOut& port) { diff --git a/src/core/libraries/kernel/threads.h b/src/core/libraries/kernel/threads.h index ad1393599..409136968 100644 --- a/src/core/libraries/kernel/threads.h +++ b/src/core/libraries/kernel/threads.h @@ -55,6 +55,9 @@ public: stop.request_stop(); Join(); } + thread = nullptr; + func = nullptr; + stop = std::stop_source{}; } static void* PS4_SYSV_ABI RunWrapper(void* arg) { diff --git a/src/core/libraries/save_data/savedata.cpp b/src/core/libraries/save_data/savedata.cpp index 66899fb34..b573ded1e 100644 --- a/src/core/libraries/save_data/savedata.cpp +++ b/src/core/libraries/save_data/savedata.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include #include @@ -1139,10 +1140,6 @@ Error PS4_SYSV_ABI sceSaveDataGetSaveDataMemory2(OrbisSaveDataMemoryGet2* getPar LOG_INFO(Lib_SaveData, "called without save memory initialized"); 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"); auto data = getParam->data; if (data != nullptr) { @@ -1502,8 +1499,14 @@ Error PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* return Error::MEMORY_NOT_READY; } if (SaveMemory::IsSaving()) { - LOG_TRACE(Lib_SaveData, "called while saving"); - return Error::BUSY_FOR_SAVING; + int count = 0; + 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"); auto data = setParam->data; @@ -1584,8 +1587,8 @@ Error PS4_SYSV_ABI sceSaveDataSetupSaveDataMemory2(const OrbisSaveDataMemorySetu } else { SaveMemory::SetIcon(nullptr, 0); } + SaveMemory::TriggerSaveWithoutEvent(); } - SaveMemory::TriggerSaveWithoutEvent(); if (g_fw_ver >= ElfInfo::FW_45 && result != nullptr) { result->existedMemorySize = existed_size; } diff --git a/src/core/libraries/usbd/usbd.cpp b/src/core/libraries/usbd/usbd.cpp index c0e1b7ea8..fdfa50b23 100644 --- a/src/core/libraries/usbd/usbd.cpp +++ b/src/core/libraries/usbd/usbd.cpp @@ -10,327 +10,327 @@ namespace Libraries::Usbd { int PS4_SYSV_ABI sceUsbdAllocTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdAttachKernelDriver() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdBulkTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdCancelTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdCheckConnected() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdClaimInterface() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdClearHalt() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdClose() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdControlTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdControlTransferGetData() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdControlTransferGetSetup() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdDetachKernelDriver() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdEventHandlerActive() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdEventHandlingOk() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdExit() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFillBulkTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFillControlSetup() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFillControlTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFillInterruptTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFillIsoTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFreeConfigDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFreeDeviceList() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdFreeTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetActiveConfigDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetBusNumber() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetConfigDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetConfigDescriptorByValue() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetConfiguration() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDeviceAddress() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDeviceDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDeviceList() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetDeviceSpeed() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetIsoPacketBuffer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetMaxIsoPacketSize() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetMaxPacketSize() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetStringDescriptor() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdGetStringDescriptorAscii() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdHandleEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdHandleEventsLocked() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdHandleEventsTimeout() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_DEBUG(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdInit() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return 0x80240005; // Skip } int PS4_SYSV_ABI sceUsbdInterruptTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdKernelDriverActive() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdLockEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdLockEventWaiters() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdOpen() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdOpenDeviceWithVidPid() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdRefDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdReleaseInterface() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdResetDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdSetConfiguration() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdSetInterfaceAltSetting() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdSetIsoPacketLengths() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdSubmitTransfer() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdTryLockEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdUnlockEvents() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdUnlockEventWaiters() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdUnrefDevice() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI sceUsbdWaitForEvent() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_65F6EF33E38FFF50() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_97F056BAD90AADE7() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_C55104A33B35B264() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } int PS4_SYSV_ABI Func_D56B43060720B1E0() { - LOG_ERROR(Lib_Usbd, "(STUBBED)called"); + LOG_ERROR(Lib_Usbd, "(STUBBED) called"); return ORBIS_OK; } diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index 5cd0a4d65..6d76a5318 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -213,6 +213,8 @@ SettingsDialog::SettingsDialog(std::span physical_devices, ui->showSplashCheckBox->installEventFilter(this); ui->discordRPCCheckbox->installEventFilter(this); ui->userName->installEventFilter(this); + ui->label_Trophy->installEventFilter(this); + ui->trophyKeyLineEdit->installEventFilter(this); ui->logTypeGroupBox->installEventFilter(this); ui->logFilter->installEventFilter(this); #ifdef ENABLE_UPDATER @@ -307,6 +309,9 @@ void SettingsDialog::LoadValuesFromConfig() { QString::fromStdString(toml::find_or(data, "General", "logFilter", ""))); ui->userNameLineEdit->setText( QString::fromStdString(toml::find_or(data, "General", "userName", "shadPS4"))); + ui->trophyKeyLineEdit->setText( + QString::fromStdString(toml::find_or(data, "Keys", "TrophyKey", ""))); + ui->trophyKeyLineEdit->setEchoMode(QLineEdit::Password); ui->debugDump->setChecked(toml::find_or(data, "Debug", "DebugDump", false)); ui->vkValidationCheckBox->setChecked(toml::find_or(data, "Vulkan", "validation", false)); ui->vkSyncValidationCheckBox->setChecked( @@ -419,6 +424,10 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) { text = tr("discordRPCCheckbox"); } else if (elementName == "userName") { text = tr("userName"); + } else if (elementName == "label_Trophy") { + text = tr("TrophyKey"); + } else if (elementName == "trophyKeyLineEdit") { + text = tr("TrophyKey"); } else if (elementName == "logTypeGroupBox") { text = tr("logTypeGroupBox"); } else if (elementName == "logFilter") { @@ -529,6 +538,7 @@ void SettingsDialog::UpdateSettings() { Config::setLogType(ui->logTypeComboBox->currentText().toStdString()); Config::setLogFilter(ui->logFilterLineEdit->text().toStdString()); Config::setUserName(ui->userNameLineEdit->text().toStdString()); + Config::setTrophyKey(ui->trophyKeyLineEdit->text().toStdString()); Config::setCursorState(ui->hideCursorComboBox->currentIndex()); Config::setCursorHideTimeout(ui->idleTimeoutSpinBox->value()); Config::setGpuId(ui->graphicsAdapterBox->currentIndex() - 1); diff --git a/src/qt_gui/settings_dialog.ui b/src/qt_gui/settings_dialog.ui index af1edb0dd..2e7e3db37 100644 --- a/src/qt_gui/settings_dialog.ui +++ b/src/qt_gui/settings_dialog.ui @@ -11,8 +11,8 @@ 0 0 - 950 - 780 + 970 + 670 @@ -67,8 +67,8 @@ 0 0 - 822 - 487 + 946 + 536 @@ -77,87 +77,7 @@ 0 - - - - - - Logger - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Log Type - - - - - - - async - - - - - sync - - - - - - - - - - - - - - 6 - - - 0 - - - - - - - Log Filter - - - - - - - - - - - - - - - - - - + @@ -194,7 +114,7 @@ - + @@ -268,10 +188,10 @@ - + - -1 + 6 QLayout::SizeConstraint::SetDefaultConstraint @@ -436,138 +356,8 @@ - - - - - - 0 - 0 - - - - - 0 - 0 - - - - GUI Settings - - - - 1 - - - 11 - - - - - Disable Trophy Pop-ups - - - - - - - - 0 - 0 - - - - Play title music - - - - - - - 1 - - - 0 - - - - - Qt::Orientation::Vertical - - - QSizePolicy::Policy::Fixed - - - - 20 - 13 - - - - - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - Volume - - - - - - - Set the volume of the background music. - - - 100 - - - 10 - - - 20 - - - 50 - - - Qt::Orientation::Horizontal - - - false - - - false - - - QSlider::TickPosition::NoTicks - - - 10 - - - - - - - - - - - - + @@ -638,6 +428,160 @@ + + + + + + + 0 + 0 + + + + + 0 + 0 + + + + GUI Settings + + + + 1 + + + 11 + + + + + + 0 + 0 + + + + Play title music + + + + + + + 1 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + Volume + + + + + + + Set the volume of the background music. + + + 100 + + + 10 + + + 20 + + + 50 + + + Qt::Orientation::Horizontal + + + false + + + false + + + QSlider::TickPosition::NoTicks + + + 10 + + + + + + + 6 + + + 0 + + + + + + + Trophy + + + + + + Disable Trophy Pop-ups + + + + + + + Trophy Key + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + + + + @@ -655,8 +599,8 @@ 0 0 - 396 - 222 + 926 + 536 @@ -946,8 +890,8 @@ 0 0 - 536 - 192 + 926 + 536 @@ -1197,8 +1141,8 @@ 0 0 - 146 - 215 + 926 + 536 @@ -1211,18 +1155,25 @@ - - - Remove + + + 0 - - - - - - Add... - - + + + + Add... + + + + + + + Remove + + + + @@ -1263,71 +1214,145 @@ 0 0 - 288 - 163 + 926 + 536 - + + + 0 + + + 0 + - - - true - - - General - - - Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop - - - - - - Enable Debug Dumping - - - - - - - Qt::Orientation::Vertical - - - QSizePolicy::Policy::MinimumExpanding - - - - 0 - 0 - - - - - - - - Enable Vulkan Validation Layers - - - - - - - Enable Vulkan Synchronization Validation - - - - - - - Enable RenderDoc Debugging - - - - - + + + + + true + + + General + + + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop + + + + + + Enable Debug Dumping + + + + + + + Enable Vulkan Validation Layers + + + + + + + Enable Vulkan Synchronization Validation + + + + + + + Enable RenderDoc Debugging + + + + + + + + + + + + + + Logger + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Log Type + + + + + + + async + + + + + sync + + + + + + + + + + + + + + 6 + + + 0 + + + + + + + Log Filter + + + + + + + + + + + + + + + + diff --git a/src/qt_gui/translations/ar.ts b/src/qt_gui/translations/ar.ts index 1f65db04a..e851f59a7 100644 --- a/src/qt_gui/translations/ar.ts +++ b/src/qt_gui/translations/ar.ts @@ -537,6 +537,16 @@ Username اسم المستخدم + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName اسم المستخدم:\nيضبط اسم حساب PS4، الذي قد يتم عرضه في بعض الألعاب. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/da_DK.ts b/src/qt_gui/translations/da_DK.ts index 943e2d092..41319c7ff 100644 --- a/src/qt_gui/translations/da_DK.ts +++ b/src/qt_gui/translations/da_DK.ts @@ -537,6 +537,16 @@ Username Username + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Brugernavn:\nIndstiller PS4-kontoens navn, som kan blive vist i nogle spil. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/de.ts b/src/qt_gui/translations/de.ts index cbbef8215..62897fe24 100644 --- a/src/qt_gui/translations/de.ts +++ b/src/qt_gui/translations/de.ts @@ -537,6 +537,16 @@ Username Benutzername + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Benutzername:\nLegt den Namen des PS4-Kontos fest, der in einigen Spielen angezeigt werden kann. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/el.ts b/src/qt_gui/translations/el.ts index 8737f5216..43ed81c33 100644 --- a/src/qt_gui/translations/el.ts +++ b/src/qt_gui/translations/el.ts @@ -537,6 +537,16 @@ Username Username + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Όνομα Χρήστη:\nΟρίζει το όνομα του λογαριασμού PS4, το οποίο μπορεί να εμφανιστεί σε ορισμένα παιχνίδια. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/en.ts b/src/qt_gui/translations/en.ts index 692aa527e..293b5fae7 100644 --- a/src/qt_gui/translations/en.ts +++ b/src/qt_gui/translations/en.ts @@ -537,6 +537,16 @@ Username Username + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Username:\nSets the PS4's account username, which may be displayed by some games. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/es_ES.ts b/src/qt_gui/translations/es_ES.ts index 70be2253d..096e104e3 100644 --- a/src/qt_gui/translations/es_ES.ts +++ b/src/qt_gui/translations/es_ES.ts @@ -537,6 +537,16 @@ Username Nombre de usuario + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Nombre de Usuario:\nEstablece el nombre de usuario de la cuenta de PS4, que puede ser mostrado por algunos juegos. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/fa_IR.ts b/src/qt_gui/translations/fa_IR.ts index 54187cf9b..7b93c6769 100644 --- a/src/qt_gui/translations/fa_IR.ts +++ b/src/qt_gui/translations/fa_IR.ts @@ -537,6 +537,16 @@ Username نام کاربری + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName نام کاربری:\nنام کاربری حساب PS4 را تنظیم می‌کند که ممکن است توسط برخی بازی‌ها نمایش داده شود. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/fi.ts b/src/qt_gui/translations/fi.ts index bdc1eb703..cdf331796 100644 --- a/src/qt_gui/translations/fi.ts +++ b/src/qt_gui/translations/fi.ts @@ -537,6 +537,16 @@ Username Username + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Käyttäjänimi:\nAsettaa PS4-tilin käyttäjänimen, joka voi näkyä joissakin peleissä. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/fr.ts b/src/qt_gui/translations/fr.ts index 19b0f9358..441eaddb1 100644 --- a/src/qt_gui/translations/fr.ts +++ b/src/qt_gui/translations/fr.ts @@ -537,6 +537,16 @@ Username Nom d'utilisateur + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Nom d'utilisateur:\nDéfinit le nom d'utilisateur du compte PS4, qui peut être affiché par certains jeux. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts index bc337f2cd..f6b853e4b 100644 --- a/src/qt_gui/translations/hu_HU.ts +++ b/src/qt_gui/translations/hu_HU.ts @@ -537,6 +537,16 @@ Username Felhasználónév + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Felhasználónév:\nBeállítja a PS4 fiók felhasználónevét, amelyet egyes játékok megjeleníthetnek. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/id.ts b/src/qt_gui/translations/id.ts index 7a0bf5d05..bee61083c 100644 --- a/src/qt_gui/translations/id.ts +++ b/src/qt_gui/translations/id.ts @@ -537,6 +537,16 @@ Username Username + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Nama Pengguna:\nMenetapkan nama pengguna akun PS4, yang mungkin ditampilkan oleh beberapa permainan. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/it.ts b/src/qt_gui/translations/it.ts index 1391fbc55..9e375a45e 100644 --- a/src/qt_gui/translations/it.ts +++ b/src/qt_gui/translations/it.ts @@ -537,6 +537,16 @@ Username Nome Utente + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Nome Utente:\nImposta il nome utente dell'account PS4, che potrebbe essere visualizzato da alcuni giochi. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/ja_JP.ts b/src/qt_gui/translations/ja_JP.ts index 58f213e03..409900ade 100644 --- a/src/qt_gui/translations/ja_JP.ts +++ b/src/qt_gui/translations/ja_JP.ts @@ -537,6 +537,16 @@ Username ユーザー名 + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName ユーザー名:\nPS4のアカウントユーザー名を設定します。これは、一部のゲームで表示される場合があります。 + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/ko_KR.ts b/src/qt_gui/translations/ko_KR.ts index 75a1b53cf..ab6404a7e 100644 --- a/src/qt_gui/translations/ko_KR.ts +++ b/src/qt_gui/translations/ko_KR.ts @@ -537,6 +537,16 @@ Username Username + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Username:\nSets the PS4's account username, which may be displayed by some games. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/lt_LT.ts b/src/qt_gui/translations/lt_LT.ts index 092521fdf..0b9c5b542 100644 --- a/src/qt_gui/translations/lt_LT.ts +++ b/src/qt_gui/translations/lt_LT.ts @@ -537,6 +537,16 @@ Username Username + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Vartotojo vardas:\nNustato PS4 paskyros vartotojo vardą, kuris gali būti rodomas kai kuriuose žaidimuose. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/nb.ts b/src/qt_gui/translations/nb.ts index cc41573db..4d3c4f5af 100644 --- a/src/qt_gui/translations/nb.ts +++ b/src/qt_gui/translations/nb.ts @@ -537,6 +537,16 @@ Username Brukernavn + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Brukernavn:\nAngir brukernavnet for PS4-kontoen, som kan vises av enkelte spill. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/nl.ts b/src/qt_gui/translations/nl.ts index 5cd4a4224..0cb890186 100644 --- a/src/qt_gui/translations/nl.ts +++ b/src/qt_gui/translations/nl.ts @@ -537,6 +537,16 @@ Username Username + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Gebruikersnaam:\nStelt de gebruikersnaam van het PS4-account in, die door sommige games kan worden weergegeven. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/pl_PL.ts b/src/qt_gui/translations/pl_PL.ts index b85393bb0..1aed08394 100644 --- a/src/qt_gui/translations/pl_PL.ts +++ b/src/qt_gui/translations/pl_PL.ts @@ -537,6 +537,16 @@ Username Nazwa użytkownika + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Nazwa użytkownika:\nUstala nazwę użytkownika konta PS4, która może być wyświetlana w niektórych grach. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/pt_BR.ts b/src/qt_gui/translations/pt_BR.ts index 8ab8db093..cce66c105 100644 --- a/src/qt_gui/translations/pt_BR.ts +++ b/src/qt_gui/translations/pt_BR.ts @@ -537,6 +537,16 @@ Username Nome de usuário + + + Trophy Key + Trophy Key + + + + Trophy + Troféus + Logger @@ -1236,6 +1246,11 @@ userName Nome de usuário:\nDefine o nome de usuário da conta PS4 que pode ser exibido por alguns jogos. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/ro_RO.ts b/src/qt_gui/translations/ro_RO.ts index 00547d6ba..63df2ff80 100644 --- a/src/qt_gui/translations/ro_RO.ts +++ b/src/qt_gui/translations/ro_RO.ts @@ -537,6 +537,16 @@ Username Username + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Nume utilizator:\nSetează numele de utilizator al contului PS4, care poate fi afișat de unele jocuri. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/ru_RU.ts b/src/qt_gui/translations/ru_RU.ts index 505a05a3e..88eff1aeb 100644 --- a/src/qt_gui/translations/ru_RU.ts +++ b/src/qt_gui/translations/ru_RU.ts @@ -537,6 +537,16 @@ Username Имя пользователя + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Имя пользователя:\nУстановите имя пользователя аккаунта PS4. Это может отображаться в некоторых играх. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/sq.ts b/src/qt_gui/translations/sq.ts index 0c318f4f7..1df2a40e2 100644 --- a/src/qt_gui/translations/sq.ts +++ b/src/qt_gui/translations/sq.ts @@ -537,6 +537,16 @@ Username Përdoruesi + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Përdoruesi:\nPërcakton emrin e përdoruesit të llogarisë PS4, i cili mund të shfaqet nga disa lojra. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/tr_TR.ts b/src/qt_gui/translations/tr_TR.ts index 2845af462..a03a48660 100644 --- a/src/qt_gui/translations/tr_TR.ts +++ b/src/qt_gui/translations/tr_TR.ts @@ -537,6 +537,16 @@ Username Kullanıcı Adı + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Kullanıcı Adı:\nBazı oyunlar tarafından gösterilebilen PS4 hesabının kullanıcı adını ayarlar. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/uk_UA.ts b/src/qt_gui/translations/uk_UA.ts index 8abfca435..7e0a58ffb 100644 --- a/src/qt_gui/translations/uk_UA.ts +++ b/src/qt_gui/translations/uk_UA.ts @@ -537,6 +537,16 @@ Username Ім'я користувача + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName Ім'я користувача:\nВстановіть ім'я користувача акаунта PS4. Це може відображатися в деяких іграх. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/vi_VN.ts b/src/qt_gui/translations/vi_VN.ts index 7d0e9a2cd..997c3d3f9 100644 --- a/src/qt_gui/translations/vi_VN.ts +++ b/src/qt_gui/translations/vi_VN.ts @@ -537,6 +537,16 @@ Username Username + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName 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ị. + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/zh_CN.ts b/src/qt_gui/translations/zh_CN.ts index 32b838fac..fecb8857f 100644 --- a/src/qt_gui/translations/zh_CN.ts +++ b/src/qt_gui/translations/zh_CN.ts @@ -537,6 +537,16 @@ Username 用户名 + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName 用户名:\n设置 PS4 帐户的用户名,某些游戏中可能会显示此名称。 + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/qt_gui/translations/zh_TW.ts b/src/qt_gui/translations/zh_TW.ts index 3d27267b6..293ed81a6 100644 --- a/src/qt_gui/translations/zh_TW.ts +++ b/src/qt_gui/translations/zh_TW.ts @@ -537,6 +537,16 @@ Username Username + + + Trophy Key + Trophy Key + + + + Trophy + Trophy + Logger @@ -1236,6 +1246,11 @@ userName 用戶名:\n設定PS4帳號的用戶名,某些遊戲中可能會顯示。 + + + TrophyKey + Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters. + logTypeGroupBox diff --git a/src/video_core/amdgpu/liverpool.h b/src/video_core/amdgpu/liverpool.h index f1607f03e..d2d1aab3c 100644 --- a/src/video_core/amdgpu/liverpool.h +++ b/src/video_core/amdgpu/liverpool.h @@ -889,11 +889,11 @@ struct Liverpool { return !info.linear_general; } - [[nodiscard]] DataFormat DataFormat() const { + [[nodiscard]] DataFormat GetDataFmt() const { 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. return RemapNumberFormat(info.number_type == NumberFormat::SnormNz ? NumberFormat::Srgb diff --git a/src/video_core/amdgpu/resource.h b/src/video_core/amdgpu/resource.h index 4de25adbf..208f7f380 100644 --- a/src/video_core/amdgpu/resource.h +++ b/src/video_core/amdgpu/resource.h @@ -79,21 +79,23 @@ inline NumberFormat RemapNumberFormat(const NumberFormat format) { inline CompMapping RemapComponents(const DataFormat format, const CompMapping components) { switch (format) { - case DataFormat::Format11_11_10: - return { - .r = components.b, - .g = components.g, - .b = components.r, - .a = components.a, - }; + case DataFormat::Format11_11_10: { + CompMapping result; + result.r = components.b; + result.g = components.g; + result.b = components.r; + result.a = components.a; + return result; + } case DataFormat::Format10_10_10_2: - case DataFormat::Format5_5_5_1: - return { - .r = components.a, - .g = components.b, - .b = components.g, - .a = components.r, - }; + case DataFormat::Format5_5_5_1: { + CompMapping result; + result.r = components.a; + result.g = components.b; + result.b = components.g; + result.a = components.r; + return result; + } default: return components; } diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index 0088ea4fa..3ac6a3598 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -54,18 +54,10 @@ BufferCache::BufferCache(const Vulkan::Instance& instance_, Vulkan::Scheduler& s BufferCache::~BufferCache() = default; void BufferCache::InvalidateMemory(VAddr device_addr, u64 size) { - std::scoped_lock lk{mutex}; const bool is_tracked = IsRegionRegistered(device_addr, size); - if (!is_tracked) { - return; - } - // Mark the page as CPU modified to stop tracking writes. - SCOPE_EXIT { + if (is_tracked) { + // Mark the page as CPU modified to stop tracking writes. 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; } } @@ -346,6 +338,7 @@ bool BufferCache::IsRegionRegistered(VAddr addr, size_t size) { ++page; continue; } + std::shared_lock lk{mutex}; Buffer& buffer = slot_buffers[buffer_id]; const VAddr buf_start_addr = buffer.CpuAddr(); const VAddr buf_end_addr = buf_start_addr + buffer.SizeBytes(); @@ -496,8 +489,11 @@ BufferId BufferCache::CreateBuffer(VAddr device_addr, u32 wanted_size) { wanted_size = static_cast(device_addr_end - device_addr); const OverlapResult overlap = ResolveOverlaps(device_addr, wanted_size); const u32 size = static_cast(overlap.end - overlap.begin); - const BufferId new_buffer_id = slot_buffers.insert( - instance, scheduler, MemoryUsage::DeviceLocal, overlap.begin, AllFlags, size); + const BufferId new_buffer_id = [&] { + 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]; const size_t size_bytes = new_buffer.SizeBytes(); const auto cmdbuf = scheduler.CommandBuffer(); @@ -537,10 +533,8 @@ void BufferCache::ChangeRegister(BufferId buffer_id) { void BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size, bool is_texel_buffer) { - std::scoped_lock lk{mutex}; boost::container::small_vector copies; u64 total_size_bytes = 0; - u64 largest_copy = 0; VAddr buffer_start = buffer.CpuAddr(); memory_tracker.ForEachUploadRange(device_addr, size, [&](u64 device_addr_out, u64 range_size) { copies.push_back(vk::BufferCopy{ @@ -549,7 +543,6 @@ void BufferCache::SynchronizeBuffer(Buffer& buffer, VAddr device_addr, u32 size, .size = range_size, }); total_size_bytes += range_size; - largest_copy = std::max(largest_copy, range_size); }); SCOPE_EXIT { if (is_texel_buffer) { diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 0c70fa10b..c367795f1 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -3,7 +3,7 @@ #pragma once -#include +#include #include #include #include @@ -157,7 +157,7 @@ private: StreamBuffer staging_buffer; StreamBuffer stream_buffer; Buffer gds_buffer; - std::mutex mutex; + std::shared_mutex mutex; Common::SlotVector slot_buffers; RangeSet gpu_modified_ranges; vk::BufferView null_buffer_view; diff --git a/src/video_core/buffer_cache/memory_tracker_base.h b/src/video_core/buffer_cache/memory_tracker_base.h index ae61b55f2..d9166b11c 100644 --- a/src/video_core/buffer_cache/memory_tracker_base.h +++ b/src/video_core/buffer_cache/memory_tracker_base.h @@ -15,13 +15,8 @@ namespace VideoCore { class MemoryTracker { public: 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 MANAGER_POOL_SIZE = 32; - static constexpr size_t WORDS_STACK_NEEDED = HIGHER_PAGE_SIZE / BYTES_PER_WORD; - using Manager = WordManager; public: explicit MemoryTracker(PageManager* tracker_) : tracker{tracker_} {} @@ -30,7 +25,7 @@ public: /// Returns true if a region has been modified from the CPU [[nodiscard]] bool IsRegionCpuModified(VAddr query_cpu_addr, u64 query_size) noexcept { return IteratePages( - 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(offset, size); }); } @@ -38,52 +33,34 @@ public: /// Returns true if a region has been modified from the GPU [[nodiscard]] bool IsRegionGpuModified(VAddr query_cpu_addr, u64 query_size) noexcept { return IteratePages( - 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(offset, size); }); } /// Mark region as CPU modified, notifying the device_tracker about this change void MarkRegionAsCpuModified(VAddr dirty_cpu_addr, u64 query_size) { - IteratePages(dirty_cpu_addr, query_size, - [](Manager* manager, u64 offset, size_t size) { - manager->template ChangeRegionState( - 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(dirty_cpu_addr, query_size, - [](Manager* manager, u64 offset, size_t size) { - manager->template ChangeRegionState( - manager->GetCpuAddr() + offset, size); - }); + IteratePages(dirty_cpu_addr, query_size, + [](RegionManager* manager, u64 offset, size_t size) { + manager->template ChangeRegionState( + manager->GetCpuAddr() + offset, size); + }); } /// Mark region as modified from the host GPU void MarkRegionAsGpuModified(VAddr dirty_cpu_addr, u64 query_size) noexcept { - IteratePages(dirty_cpu_addr, query_size, - [](Manager* manager, u64 offset, size_t size) { - manager->template ChangeRegionState( - manager->GetCpuAddr() + offset, size); - }); - } - - /// Unmark region as modified from the host GPU - void UnmarkRegionAsGpuModified(VAddr dirty_cpu_addr, u64 query_size) noexcept { - IteratePages(dirty_cpu_addr, query_size, - [](Manager* manager, u64 offset, size_t size) { - manager->template ChangeRegionState( - manager->GetCpuAddr() + offset, size); - }); + IteratePages(dirty_cpu_addr, query_size, + [](RegionManager* manager, u64 offset, size_t size) { + manager->template ChangeRegionState( + manager->GetCpuAddr() + offset, size); + }); } /// Call 'func' for each CPU modified range and unmark those pages as CPU modified template void ForEachUploadRange(VAddr query_cpu_range, u64 query_size, Func&& func) { IteratePages(query_cpu_range, query_size, - [&func](Manager* manager, u64 offset, size_t size) { + [&func](RegionManager* manager, u64 offset, size_t size) { manager->template ForEachModifiedRange( manager->GetCpuAddr() + offset, size, func); }); @@ -93,7 +70,7 @@ public: template void ForEachDownloadRange(VAddr query_cpu_range, u64 query_size, Func&& func) { IteratePages(query_cpu_range, query_size, - [&func](Manager* manager, u64 offset, size_t size) { + [&func](RegionManager* manager, u64 offset, size_t size) { if constexpr (clear) { manager->template ForEachModifiedRange( manager->GetCpuAddr() + offset, size, func); @@ -114,7 +91,7 @@ private: */ template bool IteratePages(VAddr cpu_address, size_t size, Func&& func) { - using FuncReturn = typename std::invoke_result::type; + using FuncReturn = typename std::invoke_result::type; static constexpr bool BOOL_BREAK = std::is_same_v; std::size_t remaining_size{size}; std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS}; @@ -155,7 +132,7 @@ private: manager_pool.emplace_back(); auto& last_pool = manager_pool.back(); 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]); } } @@ -167,9 +144,9 @@ private: } PageManager* tracker; - std::deque> manager_pool; - std::vector free_managers; - std::array top_tier{}; + std::deque> manager_pool; + std::vector free_managers; + std::array top_tier{}; }; } // namespace VideoCore diff --git a/src/video_core/buffer_cache/word_manager.h b/src/video_core/buffer_cache/word_manager.h index ae85d1eb1..7ad33d7a6 100644 --- a/src/video_core/buffer_cache/word_manager.h +++ b/src/video_core/buffer_cache/word_manager.h @@ -3,10 +3,12 @@ #pragma once -#include +#include +#include #include #include -#include "common/div_ceil.h" + +#include "common/spin_lock.h" #include "common/types.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_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 { CPU, GPU, Untracked, }; -/// Vector tracking modified pages tightly packed with small vector optimization -template -struct WordsArray { - /// Returns the pointer to the words state - [[nodiscard]] const u64* Pointer(bool is_short) const noexcept { - return is_short ? stack.data() : heap; - } +using WordsArray = std::array; - /// Returns the pointer to the words state - [[nodiscard]] u64* Pointer(bool is_short) noexcept { - return is_short ? stack.data() : heap; - } - - std::array stack{}; ///< Small buffers storage - u64* heap; ///< Not-small buffers pointer to the storage -}; - -template -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 - std::span Span() noexcept { - if constexpr (type == Type::CPU) { - return std::span(cpu.Pointer(IsShort()), num_words); - } else if constexpr (type == Type::GPU) { - return std::span(gpu.Pointer(IsShort()), num_words); - } else if constexpr (type == Type::Untracked) { - return std::span(untracked.Pointer(IsShort()), num_words); - } - } - - template - std::span Span() const noexcept { - if constexpr (type == Type::CPU) { - return std::span(cpu.Pointer(IsShort()), num_words); - } else if constexpr (type == Type::GPU) { - return std::span(gpu.Pointer(IsShort()), num_words); - } else if constexpr (type == Type::Untracked) { - return std::span(untracked.Pointer(IsShort()), num_words); - } - } - - u64 size_bytes = 0; - size_t num_words = 0; - WordsArray cpu; - WordsArray gpu; - WordsArray untracked; -}; - -template -class WordManager { +/** + * Allows tracking CPU and GPU modification of pages in a contigious 4MB virtual address region. + * Information is stored in bitsets for spacial locality and fast update of single pages. + */ +class RegionManager { public: - explicit WordManager(PageManager* tracker_, VAddr cpu_addr_, u64 size_bytes) - : tracker{tracker_}, cpu_addr{cpu_addr_}, words{size_bytes} {} - - explicit WordManager() = default; + explicit RegionManager(PageManager* tracker_, VAddr cpu_addr_) + : tracker{tracker_}, cpu_addr{cpu_addr_} { + cpu.fill(~u64{0}); + gpu.fill(0); + untracked.fill(~u64{0}); + } + explicit RegionManager() = default; void SetCpuAddress(VAddr new_cpu_addr) { cpu_addr = new_cpu_addr; @@ -175,12 +74,12 @@ public: static constexpr bool BOOL_BREAK = std::is_same_v; const size_t start = static_cast(std::max(static_cast(offset), 0LL)); const size_t end = static_cast(std::max(static_cast(offset + size), 0LL)); - if (start >= SizeBytes() || end <= start) { + if (start >= HIGHER_PAGE_SIZE || end <= start) { return; } auto [start_word, start_page] = GetWordPage(start); 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); end_word = std::min(end_word, num_words); const size_t diff = end_word - start_word; @@ -225,21 +124,21 @@ public: */ template void ChangeRegionState(u64 dirty_addr, u64 size) noexcept(type == Type::GPU) { - std::span state_words = words.template Span(); - [[maybe_unused]] std::span untracked_words = words.template Span(); + std::scoped_lock lk{lock}; + std::span state_words = Span(); IterateWords(dirty_addr - cpu_addr, size, [&](size_t index, u64 mask) { if constexpr (type == Type::CPU) { - NotifyPageTracker(index, untracked_words[index], mask); + UpdateProtection(index, untracked[index], mask); } if constexpr (enable) { state_words[index] |= mask; if constexpr (type == Type::CPU) { - untracked_words[index] |= mask; + untracked[index] |= mask; } } else { state_words[index] &= ~mask; if constexpr (type == Type::CPU) { - untracked_words[index] &= ~mask; + untracked[index] &= ~mask; } } }); @@ -255,10 +154,10 @@ public: */ template void ForEachModifiedRange(VAddr query_cpu_range, s64 size, Func&& func) { + std::scoped_lock lk{lock}; static_assert(type != Type::Untracked); - std::span state_words = words.template Span(); - [[maybe_unused]] std::span untracked_words = words.template Span(); + std::span state_words = Span(); const size_t offset = query_cpu_range - cpu_addr; bool pending = false; size_t pending_offset{}; @@ -269,16 +168,16 @@ public: }; IterateWords(offset, size, [&](size_t index, u64 mask) { if constexpr (type == Type::GPU) { - mask &= ~untracked_words[index]; + mask &= ~untracked[index]; } const u64 word = state_words[index] & mask; if constexpr (clear) { if constexpr (type == Type::CPU) { - NotifyPageTracker(index, untracked_words[index], mask); + UpdateProtection(index, untracked[index], mask); } state_words[index] &= ~mask; if constexpr (type == Type::CPU) { - untracked_words[index] &= ~mask; + untracked[index] &= ~mask; } } const size_t base_offset = index * PAGES_PER_WORD; @@ -315,13 +214,11 @@ public: [[nodiscard]] bool IsRegionModified(u64 offset, u64 size) const noexcept { static_assert(type != Type::Untracked); - const std::span state_words = words.template Span(); - [[maybe_unused]] const std::span untracked_words = - words.template Span(); + const std::span state_words = Span(); bool result = false; IterateWords(offset, size, [&](size_t index, u64 mask) { if constexpr (type == Type::GPU) { - mask &= ~untracked_words[index]; + mask &= ~untracked[index]; } const u64 word = state_words[index] & mask; if (word != 0) { @@ -333,44 +230,7 @@ public: 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: - template - 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 - 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 * @@ -381,7 +241,7 @@ private: * @tparam add_to_tracker True when the tracker should start tracking the new pages */ template - 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; VAddr addr = cpu_addr + word_index * BYTES_PER_WORD; IteratePages(changed_bits, [&](size_t offset, size_t size) { @@ -390,9 +250,34 @@ private: }); } + template + std::span 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 + std::span 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; VAddr cpu_addr = 0; - Words words; + WordsArray cpu; + WordsArray gpu; + WordsArray untracked; }; } // namespace VideoCore diff --git a/src/video_core/multi_level_page_table.h b/src/video_core/multi_level_page_table.h index 527476f3b..7f3205e1a 100644 --- a/src/video_core/multi_level_page_table.h +++ b/src/video_core/multi_level_page_table.h @@ -39,6 +39,15 @@ public: 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 { const size_t l1_page = page >> SecondLevelBits; const size_t l2_page = page & (NumEntriesPerL1Page - 1); diff --git a/src/video_core/page_manager.cpp b/src/video_core/page_manager.cpp index 556555c25..47ed9e543 100644 --- a/src/video_core/page_manager.cpp +++ b/src/video_core/page_manager.cpp @@ -185,7 +185,7 @@ void PageManager::OnGpuUnmap(VAddr address, size_t size) { void PageManager::UpdatePagesCachedCount(VAddr addr, u64 size, s32 delta) { 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 page_start = addr >> PageShift; const u64 page_end = page_start + num_pages; diff --git a/src/video_core/page_manager.h b/src/video_core/page_manager.h index 29a946a8f..f44307f92 100644 --- a/src/video_core/page_manager.h +++ b/src/video_core/page_manager.h @@ -4,8 +4,8 @@ #pragma once #include -#include #include +#include "common/spin_lock.h" #include "common/types.h" namespace Vulkan { @@ -35,8 +35,8 @@ private: struct Impl; std::unique_ptr impl; Vulkan::Rasterizer* rasterizer; - std::mutex mutex; boost::icl::interval_map cached_pages; + Common::SpinLock lock; }; } // namespace VideoCore diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index c41b760ba..97825b1e1 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -691,16 +691,40 @@ std::span SurfaceFormats() { 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(data_format < 1 << amd_gpu_data_format_bit_size); + DEBUG_ASSERT(num_format < 1 << amd_gpu_number_format_bit_size); + size_t result = static_cast(num_format) | + (static_cast(data_format) << amd_gpu_number_format_bit_size); + return result; +} + +static auto surface_format_table = []() constexpr { + std::array + 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) { - const auto& formats = SurfaceFormats(); - const auto format = - std::find_if(formats.begin(), formats.end(), [&](const SurfaceFormatInfo& format_info) { - return format_info.data_format == data_format && - format_info.number_format == num_format; - }); - ASSERT_MSG(format != formats.end(), "Unknown data_format={} and num_format={}", - static_cast(data_format), static_cast(num_format)); - return format->vk_format; + vk::Format result = surface_format_table[GetSurfaceFormatTableIndex(data_format, num_format)]; + bool found = + result != vk::Format::eUndefined || data_format == AmdGpu::DataFormat::FormatInvalid; + ASSERT_MSG(found, "Unknown data_format={} and num_format={}", static_cast(data_format), + static_cast(num_format)); + return result; } 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) { const auto comp_swizzle = color_buffer.Swizzle(); - const auto format = color_buffer.DataFormat(); - const auto number_type = color_buffer.NumFormat(); + const auto format = color_buffer.GetDataFmt(); + const auto number_type = color_buffer.GetNumberFmt(); const auto& c0 = color_buffer.clear_word0; const auto& c1 = color_buffer.clear_word1; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index cd1b42b05..ba069dae1 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -328,8 +328,8 @@ bool PipelineCache::RefreshGraphicsKey() { } key.color_formats[remapped_cb] = - LiverpoolToVK::SurfaceFormat(col_buf.DataFormat(), col_buf.NumFormat()); - key.color_num_formats[remapped_cb] = col_buf.NumFormat(); + LiverpoolToVK::SurfaceFormat(col_buf.GetDataFmt(), col_buf.GetNumberFmt()); + key.color_num_formats[remapped_cb] = col_buf.GetNumberFmt(); key.color_swizzles[remapped_cb] = col_buf.Swizzle(); } diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index 0559f1be3..adc72c21f 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -265,9 +265,9 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::ColorBuffer& buffer, const AmdGpu::Liverpool::CbDbExtent& hint /*= {}*/) noexcept { props.is_tiled = buffer.IsTiled(); 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_bits = NumBits(buffer.DataFormat()); + num_bits = NumBits(buffer.GetDataFmt()); type = vk::ImageType::e2D; size.width = hint.Valid() ? hint.width : buffer.Pitch(); size.height = hint.Valid() ? hint.height : buffer.Height(); diff --git a/src/video_core/texture_cache/image_view.cpp b/src/video_core/texture_cache/image_view.cpp index a9ae41dd1..68b116558 100644 --- a/src/video_core/texture_cache/image_view.cpp +++ b/src/video_core/texture_cache/image_view.cpp @@ -76,7 +76,8 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer) n range.base.layer = col_buffer.view.slice_start; range.extent.layers = col_buffer.NumSlices() - range.base.layer; 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, diff --git a/src/video_core/texture_cache/tile_manager.cpp b/src/video_core/texture_cache/tile_manager.cpp index de108843b..fda7e511a 100644 --- a/src/video_core/texture_cache/tile_manager.cpp +++ b/src/video_core/texture_cache/tile_manager.cpp @@ -32,6 +32,7 @@ static vk::Format DemoteImageFormatForDetiling(vk::Format format) { case vk::Format::eR5G5B5A1UnormPack16: case vk::Format::eR8G8Unorm: case vk::Format::eR16Sfloat: + case vk::Format::eR16Uint: case vk::Format::eR16Unorm: case vk::Format::eD16Unorm: return vk::Format::eR8G8Uint;