diff --git a/.github/ISSUE_TEMPLATE/game-bug-report.yaml b/.github/ISSUE_TEMPLATE/game-bug-report.yaml index 848877037..d9ebd8347 100644 --- a/.github/ISSUE_TEMPLATE/game-bug-report.yaml +++ b/.github/ISSUE_TEMPLATE/game-bug-report.yaml @@ -17,7 +17,7 @@ body: 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-compatibility/shadps4-game-compatibility) for the information about the status of the game. + 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. diff --git a/CMakeLists.txt b/CMakeLists.txt index 24a81243f..adff454b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -126,7 +126,7 @@ execute_process( # If there's no upstream set or the command failed, check remote.pushDefault if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "") - message(STATUS "check default push") + message("check default push") execute_process( COMMAND git config --get remote.pushDefault OUTPUT_VARIABLE GIT_REMOTE_NAME @@ -134,30 +134,30 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "") ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE ) - message(STATUS "got remote: ${GIT_REMOTE_NAME}") + message("got remote: ${GIT_REMOTE_NAME}") endif() # If running in GitHub Actions and the above fails if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "") - message(STATUS "check github") + message("check github") set(GIT_REMOTE_NAME "origin") # Retrieve environment variables if (DEFINED ENV{GITHUB_HEAD_REF} AND NOT "$ENV{GITHUB_HEAD_REF}" STREQUAL "") - message(STATUS "github head ref: $ENV{GITHUB_HEAD_REF}") + message("github head ref: $ENV{GITHUB_HEAD_REF}") set(GITHUB_HEAD_REF "$ENV{GITHUB_HEAD_REF}") else() set(GITHUB_HEAD_REF "") endif() if (DEFINED ENV{GITHUB_REF} AND NOT "$ENV{GITHUB_REF}" STREQUAL "") - message(STATUS "github ref: $ENV{GITHUB_REF}") + message("github ref: $ENV{GITHUB_REF}") string(REGEX REPLACE "^refs/[^/]*/" "" GITHUB_BRANCH "$ENV{GITHUB_REF}") string(REGEX MATCH "refs/pull/([0-9]+)/merge" MATCHED_REF "$ENV{GITHUB_REF}") if (MATCHED_REF) set(PR_NUMBER "${CMAKE_MATCH_1}") set(GITHUB_BRANCH "") - message(STATUS "PR number: ${PR_NUMBER}") + message("PR number: ${PR_NUMBER}") else() set(PR_NUMBER "") endif() @@ -179,7 +179,7 @@ if (GIT_REMOTE_RESULT OR GIT_REMOTE_NAME STREQUAL "") elseif ("${PR_NUMBER}" STREQUAL "" AND NOT "${GITHUB_REF}" STREQUAL "") set(GIT_BRANCH "${GITHUB_REF}") elseif("${GIT_BRANCH}" STREQUAL "") - message(STATUS "couldn't find branch") + message("couldn't find branch") set(GIT_BRANCH "detached-head") endif() else() @@ -188,13 +188,13 @@ else() if (INDEX GREATER -1) string(SUBSTRING "${GIT_REMOTE_NAME}" 0 "${INDEX}" GIT_REMOTE_NAME) elseif("${GIT_REMOTE_NAME}" STREQUAL "") - message(STATUS "reset to origin") + message("reset to origin") set(GIT_REMOTE_NAME "origin") endif() endif() # Get remote link -message(STATUS "getting remote link") +message("getting remote link") execute_process( COMMAND git config --get remote.${GIT_REMOTE_NAME}.url OUTPUT_VARIABLE GIT_REMOTE_URL @@ -212,12 +212,7 @@ set(APP_VERSION "${EMULATOR_VERSION_MAJOR}.${EMULATOR_VERSION_MINOR}.${EMULATOR_ set(APP_IS_RELEASE false) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/common/scm_rev.cpp" @ONLY) -message("-- end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}, link: ${GIT_REMOTE_URL}") - -if(NOT GIT_REMOTE_URL MATCHES "shadps4-emu/shadPS4" OR NOT GIT_BRANCH STREQUAL "main") - message(STATUS "not main, disabling auto update") - set(ENABLE_UPDATER OFF) -endif() +message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}") if(WIN32 AND ENABLE_QT_GUI AND NOT CMAKE_PREFIX_PATH) include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/DetectQtInstallation.cmake") diff --git a/README.md b/README.md index 06da2d471..22fc27a33 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ SPDX-License-Identifier: GPL-2.0-or-later **shadPS4** is an early **PlayStation 4** emulator for **Windows**, **Linux** and **macOS** written in C++. If you encounter problems or have doubts, do not hesitate to look at the [**Quickstart**](https://github.com/shadps4-emu/shadPS4/wiki/I.-Quick-start-%5BUsers%5D).\ -To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-compatibility/shadps4-game-compatibility).\ +To verify that a game works, you can look at [**shadPS4 Game Compatibility**](https://github.com/shadps4-emu/shadps4-game-compatibility).\ To discuss shadPS4 development, suggest ideas or to ask for help, join our [**Discord server**](https://discord.gg/bFJxfftGW6).\ To get the latest news, go to our [**X (Twitter)**](https://x.com/shadps4) or our [**website**](https://shadps4.net/).\ For those who'd like to donate to the project, we now have a [**Kofi page**](https://ko-fi.com/shadps4)! diff --git a/documents/Debugging/Debugging.md b/documents/Debugging/Debugging.md index d2eda61b7..ef9aab879 100644 --- a/documents/Debugging/Debugging.md +++ b/documents/Debugging/Debugging.md @@ -147,7 +147,7 @@ Accurately identifying games will help other developers that own that game recog - If your issue is small or you aren't sure whether you have properly identified something, [join the Discord server](https://discord.gg/MyZRaBngxA) and use the #development channel to concisely explain the issue, as well as any findings you currently have. -- It is recommended that you check the [game compatibility issue tracker](https://github.com/shadps4-compatibility/shadps4-game-compatibility/issues) and post very short summaries of progress changes there, +- It is recommended that you check the [game compatibility issue tracker](https://github.com/shadps4-emu/shadps4-game-compatibility/issues) and post very short summaries of progress changes there, (such as the game now booting into the menu or getting in-game) for organizational and status update purposes. - ⚠ **Do not post theoretical, unproven game-specific issues in the emulator issue tracker that you cannot verify and locate in the emulator source code as being a bug.**\ diff --git a/src/common/config.cpp b/src/common/config.cpp index a1b12ee5d..6f8563377 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -32,7 +32,6 @@ std::filesystem::path find_fs_path_or(const basic_value& v, const K& ky, namespace Config { // General -static int volumeSlider = 100; static bool isNeo = false; static bool isDevKit = false; static bool isPSNSignedIn = false; @@ -109,9 +108,6 @@ static std::string trophyKey = ""; // Expected number of items in the config file static constexpr u64 total_entries = 54; -int getVolumeSlider() { - return volumeSlider; -} bool allowHDR() { return isHDRAllowed; } @@ -161,10 +157,6 @@ std::filesystem::path GetSaveDataPath() { return save_data_path; } -void setVolumeSlider(int volumeValue) { - volumeSlider = volumeValue; -} - void setLoadGameSizeEnabled(bool enable) { load_game_size = enable; } @@ -619,7 +611,6 @@ void load(const std::filesystem::path& path) { if (data.contains("General")) { const toml::value& general = data.at("General"); - volumeSlider = toml::find_or(general, "volumeSlider", volumeSlider); isNeo = toml::find_or(general, "isPS4Pro", isNeo); isDevKit = toml::find_or(general, "isDevKit", isDevKit); isPSNSignedIn = toml::find_or(general, "isPSNSignedIn", isPSNSignedIn); @@ -815,7 +806,6 @@ void save(const std::filesystem::path& path) { fmt::print("Saving new configuration file {}\n", fmt::UTF(path.u8string())); } - data["General"]["volumeSlider"] = volumeSlider; data["General"]["isPS4Pro"] = isNeo; data["General"]["isDevKit"] = isDevKit; data["General"]["isPSNSignedIn"] = isPSNSignedIn; @@ -911,7 +901,6 @@ void save(const std::filesystem::path& path) { void setDefaultValues() { // General - volumeSlider = 100; isNeo = false; isDevKit = false; isPSNSignedIn = false; diff --git a/src/common/config.h b/src/common/config.h index 4ace4d316..e54425676 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -19,8 +19,6 @@ enum HideCursorState : int { Never, Idle, Always }; void load(const std::filesystem::path& path); void save(const std::filesystem::path& path); -int getVolumeSlider(); -void setVolumeSlider(int volumeValue); std::string getTrophyKey(); void setTrophyKey(std::string key); bool getIsFullscreen(); diff --git a/src/core/libraries/audio/audioout.cpp b/src/core/libraries/audio/audioout.cpp index 22b6b17ea..f49125de0 100644 --- a/src/core/libraries/audio/audioout.cpp +++ b/src/core/libraries/audio/audioout.cpp @@ -536,24 +536,9 @@ s32 PS4_SYSV_ABI sceAudioOutSetVolume(s32 handle, s32 flag, s32* vol) { } port.impl->SetVolume(port.volume); } - AdjustVol(); return ORBIS_OK; } -void AdjustVol() { - if (audio == nullptr) { - return; - } - - for (int i = 0; i < ports_out.size(); i++) { - std::unique_lock lock{ports_out[i].mutex}; - if (!ports_out[i].IsOpen()) { - continue; - } - ports_out[i].impl->SetVolume(ports_out[i].volume); - } -} - int PS4_SYSV_ABI sceAudioOutSetVolumeDown() { LOG_ERROR(Lib_AudioOut, "(STUBBED) called"); return ORBIS_OK; diff --git a/src/core/libraries/audio/audioout.h b/src/core/libraries/audio/audioout.h index 6d3a6399b..4a20f49d8 100644 --- a/src/core/libraries/audio/audioout.h +++ b/src/core/libraries/audio/audioout.h @@ -182,6 +182,5 @@ int PS4_SYSV_ABI sceAudioOutSystemControlSet(); int PS4_SYSV_ABI sceAudioOutSparkControlSetEqCoef(); int PS4_SYSV_ABI sceAudioOutSetSystemDebugState(); -void AdjustVol(); void RegisterLib(Core::Loader::SymbolsResolver* sym); } // namespace Libraries::AudioOut diff --git a/src/core/libraries/audio/sdl_audio.cpp b/src/core/libraries/audio/sdl_audio.cpp index 94d624b0c..9aee2b447 100644 --- a/src/core/libraries/audio/sdl_audio.cpp +++ b/src/core/libraries/audio/sdl_audio.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include "common/logging/log.h" #include "core/libraries/audio/audioout.h" @@ -42,7 +41,6 @@ public: stream = nullptr; return; } - SDL_SetAudioStreamGain(stream, Config::getVolumeSlider() / 100.0f); } ~SDLPortBackend() override { @@ -79,8 +77,7 @@ public: } // SDL does not have per-channel volumes, for now just take the maximum of the channels. const auto vol = *std::ranges::max_element(ch_volumes); - if (!SDL_SetAudioStreamGain(stream, static_cast(vol) / SCE_AUDIO_OUT_VOLUME_0DB * - Config::getVolumeSlider() / 100.0f)) { + if (!SDL_SetAudioStreamGain(stream, static_cast(vol) / SCE_AUDIO_OUT_VOLUME_0DB)) { LOG_WARNING(Lib_AudioOut, "Failed to change SDL audio stream volume: {}", SDL_GetError()); } diff --git a/src/core/libraries/ime/ime.cpp b/src/core/libraries/ime/ime.cpp index 360f0fc54..090a9726d 100644 --- a/src/core/libraries/ime/ime.cpp +++ b/src/core/libraries/ime/ime.cpp @@ -18,9 +18,11 @@ static ImeUi g_ime_ui; class ImeHandler { public: ImeHandler(const OrbisImeKeyboardParam* param) { + LOG_INFO(Lib_Ime, "Creating ImeHandler for keyboard"); Init(param, false); } ImeHandler(const OrbisImeParam* param) { + LOG_INFO(Lib_Ime, "Creating ImeHandler for IME"); Init(param, true); } ~ImeHandler() = default; @@ -38,8 +40,13 @@ public: openEvent.id = (ime_mode ? OrbisImeEventId::Open : OrbisImeEventId::KeyboardOpen); if (ime_mode) { - sceImeGetPanelSize(&m_param.ime, &openEvent.param.rect.width, - &openEvent.param.rect.height); + LOG_INFO(Lib_Ime, "calling sceImeGetPanelSize"); + Error e = sceImeGetPanelSize(&m_param.ime, &openEvent.param.rect.width, + &openEvent.param.rect.height); + if (e != Error::OK) { + LOG_ERROR(Lib_Ime, "sceImeGetPanelSize returned 0x{:X}", static_cast(e)); + } + openEvent.param.rect.x = m_param.ime.posx; openEvent.param.rect.y = m_param.ime.posy; } else { @@ -152,8 +159,13 @@ Error PS4_SYSV_ABI sceImeClose() { } g_ime_handler.release(); + if (g_keyboard_handler) { + return Error::INTERNAL; + } g_ime_ui = ImeUi(); g_ime_state = ImeState(); + + LOG_INFO(Lib_Ime, "IME closed successfully"); return Error::OK; } @@ -226,21 +238,21 @@ Error PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u3 LOG_INFO(Lib_Ime, "sceImeGetPanelSize called"); if (!param) { - LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: param is NULL"); + LOG_ERROR(Lib_Ime, "Invalid param: NULL"); return Error::INVALID_ADDRESS; } + if (!width) { - LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: width pointer is NULL"); + LOG_ERROR(Lib_Ime, "Invalid *width: NULL"); return Error::INVALID_ADDRESS; } if (!height) { - LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: height pointer is NULL"); + LOG_ERROR(Lib_Ime, "Invalid *height: NULL"); return Error::INVALID_ADDRESS; } if (static_cast(param->option) & ~0x7BFF) { // Basic check for invalid options - LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: Invalid option 0x{:X}", - static_cast(param->option)); + LOG_ERROR(Lib_Ime, "Invalid option 0x{:X}", static_cast(param->option)); return Error::INVALID_OPTION; } @@ -248,38 +260,35 @@ Error PS4_SYSV_ABI sceImeGetPanelSize(const OrbisImeParam* param, u32* width, u3 case OrbisImeType::Default: *width = 500; // dummy value *height = 100; // dummy value - LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type Default ({})", - static_cast(param->type)); + LOG_DEBUG(Lib_Ime, "param->type: Default ({})", static_cast(param->type)); break; case OrbisImeType::BasicLatin: *width = 500; // dummy value *height = 100; // dummy value - LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type BasicLatin ({})", - static_cast(param->type)); + LOG_DEBUG(Lib_Ime, "param->type: BasicLatin ({})", static_cast(param->type)); break; case OrbisImeType::Url: *width = 500; // dummy value *height = 100; // dummy value - LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type Url ({})", static_cast(param->type)); + LOG_DEBUG(Lib_Ime, "param->type: Url ({})", static_cast(param->type)); break; case OrbisImeType::Mail: // We set our custom sizes, commented sizes are the original ones *width = 500; // 793 *height = 100; // 408 - LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type Mail ({})", static_cast(param->type)); + LOG_DEBUG(Lib_Ime, "param->type: Mail ({})", static_cast(param->type)); break; case OrbisImeType::Number: *width = 370; *height = 402; - LOG_INFO(Lib_Ime, "sceImeGetPanelSize: IME type Number ({})", - static_cast(param->type)); + LOG_DEBUG(Lib_Ime, "param->type: Number ({})", static_cast(param->type)); break; default: - LOG_ERROR(Lib_Ime, "sceImeGetPanelSize: Invalid IME type ({})", - static_cast(param->type)); + LOG_ERROR(Lib_Ime, "Invalid param->type: ({})", static_cast(param->type)); return Error::INVALID_TYPE; } + LOG_INFO(Lib_Ime, "IME panel size: width={}, height={}", *width, *height); return Error::OK; } @@ -287,10 +296,23 @@ Error PS4_SYSV_ABI sceImeKeyboardClose(Libraries::UserService::OrbisUserServiceU LOG_INFO(Lib_Ime, "called"); if (!g_keyboard_handler) { + LOG_ERROR(Lib_Ime, "No keyboard handler is open"); return Error::NOT_OPENED; } + if (userId < 0 || userId > 4) { // Todo: check valid user IDs + // Maybe g_keyboard_handler should hold a user ID and I must compare it here? + LOG_ERROR(Lib_Ime, "Invalid userId: {}", userId); + return Error::INVALID_USER_ID; + } + g_keyboard_handler.release(); + if (g_ime_handler) { + LOG_ERROR(Lib_Ime, "failed to close keyboard handler, IME handler is still open"); + return Error::INTERNAL; + } + + LOG_INFO(Lib_Ime, "Keyboard handler closed successfully for user ID: {}", userId); return Error::OK; } @@ -307,24 +329,57 @@ int PS4_SYSV_ABI sceImeKeyboardGetResourceId() { Error PS4_SYSV_ABI sceImeKeyboardOpen(Libraries::UserService::OrbisUserServiceUserId userId, const OrbisImeKeyboardParam* param) { LOG_INFO(Lib_Ime, "called"); - - LOG_INFO(Lib_Ime, "kValidImeDialogExtOptionMask=0x{:X}", kValidImeDialogExtOptionMask); - if (!param) { + LOG_ERROR(Lib_Ime, "Invalid param: NULL"); return Error::INVALID_ADDRESS; } - if (!param->arg) { - return Error::INVALID_ARG; - } if (!param->handler) { + LOG_ERROR(Lib_Ime, "Invalid param->handler: NULL"); return Error::INVALID_HANDLER; } - + // seems like arg is optional, need to check if it is used in the handler + if (!param->arg && false) { // Todo: check if arg is used in the handler, temporarily disabled + LOG_ERROR(Lib_Ime, "Invalid param->arg: NULL"); + return Error::INVALID_ARG; + } + if (static_cast(param->option) & ~kValidOrbisImeKeyboardOptionMask) { + LOG_ERROR(Lib_Ime, + "Invalid param->option\n" + "option: {:032b}\n" + "validMask: {:032b}", + static_cast(param->option), kValidOrbisImeKeyboardOptionMask); + return Error::INVALID_OPTION; + } + if (userId < 0 || userId > 4) { // Todo: check valid user IDs + LOG_ERROR(Lib_Ime, "Invalid userId: {}", userId); + return Error::INVALID_USER_ID; + } + for (size_t i = 0; i < sizeof(param->reserved1); ++i) { + if (param->reserved1[i] != 0) { + LOG_ERROR(Lib_Ime, "Invalid reserved1: not zeroed"); + return Error::INVALID_RESERVED; + } + } + for (size_t i = 0; i < sizeof(param->reserved2); ++i) { + if (param->reserved2[i] != 0) { + LOG_ERROR(Lib_Ime, "Invalid reserved2: not zeroed"); + return Error::INVALID_RESERVED; + } + } + if (false) { // Todo: check if usb keyboard is connected, always true for now + LOG_ERROR(Lib_Ime, "USB keyboard is not connected"); + return Error::CONNECTION_FAILED; + } if (g_keyboard_handler) { + LOG_ERROR(Lib_Ime, "Keyboard handler is already open"); return Error::BUSY; } - g_keyboard_handler = std::make_unique(param); + if (!g_keyboard_handler) { + LOG_ERROR(Lib_Ime, "Failed to create keyboard handler"); + return Error::INTERNAL; // or Error::NO_MEMORY; + } + LOG_INFO(Lib_Ime, "Keyboard handler created successfully for user ID: {}", userId); return Error::OK; } @@ -347,110 +402,110 @@ Error PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const OrbisImeParamExt LOG_INFO(Lib_Ime, "called"); if (!param) { - LOG_ERROR(Lib_Ime, "sceImeOpen: param is null"); + LOG_ERROR(Lib_Ime, "Invalid param: NULL"); return Error::INVALID_ADDRESS; } else { // LOG_DEBUG values for debugging purposes - LOG_DEBUG(Lib_Ime, "param: user_id={}", param->user_id); - LOG_DEBUG(Lib_Ime, "param: type={}", static_cast(param->type)); - LOG_DEBUG(Lib_Ime, "param: supported_languages={:064b}", + LOG_DEBUG(Lib_Ime, "param->user_id: {}", param->user_id); + LOG_DEBUG(Lib_Ime, "param->type: {}", static_cast(param->type)); + LOG_DEBUG(Lib_Ime, "param->supported_languages: {:064b}", static_cast(param->supported_languages)); - LOG_DEBUG(Lib_Ime, "param: enter_label={}", static_cast(param->enter_label)); - LOG_DEBUG(Lib_Ime, "param: input_method={}", static_cast(param->input_method)); - LOG_DEBUG(Lib_Ime, "param: filter={:p}", reinterpret_cast(param->filter)); - LOG_DEBUG(Lib_Ime, "param: option={:032b}", static_cast(param->option)); - LOG_DEBUG(Lib_Ime, "param: maxTextLength={}", param->maxTextLength); - LOG_DEBUG(Lib_Ime, "param: inputTextBuffer={:p}", + LOG_DEBUG(Lib_Ime, "param->enter_label: {}", static_cast(param->enter_label)); + LOG_DEBUG(Lib_Ime, "param->input_method: {}", static_cast(param->input_method)); + LOG_DEBUG(Lib_Ime, "param->filter: {:p}", reinterpret_cast(param->filter)); + LOG_DEBUG(Lib_Ime, "param->option: {:032b}", static_cast(param->option)); + LOG_DEBUG(Lib_Ime, "param->maxTextLength: {}", param->maxTextLength); + LOG_DEBUG(Lib_Ime, "param->inputTextBuffer: {:p}", static_cast(param->inputTextBuffer)); - LOG_DEBUG(Lib_Ime, "param: posx={}", param->posx); - LOG_DEBUG(Lib_Ime, "param: posy={}", param->posy); - LOG_DEBUG(Lib_Ime, "param: horizontal_alignment={}", + LOG_DEBUG(Lib_Ime, "param->posx: {}", param->posx); + LOG_DEBUG(Lib_Ime, "param->posy: {}", param->posy); + LOG_DEBUG(Lib_Ime, "param->horizontal_alignment: {}", static_cast(param->horizontal_alignment)); - LOG_DEBUG(Lib_Ime, "param: vertical_alignment={}", + LOG_DEBUG(Lib_Ime, "param->vertical_alignment: {}", static_cast(param->vertical_alignment)); - LOG_DEBUG(Lib_Ime, "param: work={:p}", param->work); - LOG_DEBUG(Lib_Ime, "param: arg={:p}", param->arg); - LOG_DEBUG(Lib_Ime, "param: handler={:p}", reinterpret_cast(param->handler)); + LOG_DEBUG(Lib_Ime, "param->work: {:p}", param->work); + LOG_DEBUG(Lib_Ime, "param->arg: {:p}", param->arg); + LOG_DEBUG(Lib_Ime, "param->handler: {:p}", reinterpret_cast(param->handler)); } if (!extended) { - LOG_INFO(Lib_Ime, "sceImeOpen: extended is null"); + LOG_INFO(Lib_Ime, "Not used extended: NULL"); } else { - // LOG_DEBUG values for debugging purposes - LOG_DEBUG(Lib_Ime, "extended: option={:032b}", static_cast(extended->option)); - LOG_DEBUG(Lib_Ime, "extended: color_base={{{},{},{},{}}}", extended->color_base.r, + LOG_DEBUG(Lib_Ime, "extended->option: {:032b}", static_cast(extended->option)); + LOG_DEBUG(Lib_Ime, "extended->color_base: {{{},{},{},{}}}", extended->color_base.r, extended->color_base.g, extended->color_base.b, extended->color_base.a); - LOG_DEBUG(Lib_Ime, "extended: color_line={{{},{},{},{}}}", extended->color_line.r, + LOG_DEBUG(Lib_Ime, "extended->color_line: {{{},{},{},{}}}", extended->color_line.r, extended->color_line.g, extended->color_line.b, extended->color_line.a); - LOG_DEBUG(Lib_Ime, "extended: color_text_field={{{},{},{},{}}}", + LOG_DEBUG(Lib_Ime, "extended->color_text_field: {{{},{},{},{}}}", extended->color_text_field.r, extended->color_text_field.g, extended->color_text_field.b, extended->color_text_field.a); - LOG_DEBUG(Lib_Ime, "extended: color_preedit={{{},{},{},{}}}", extended->color_preedit.r, + LOG_DEBUG(Lib_Ime, "extended->color_preedit: {{{},{},{},{}}}", extended->color_preedit.r, extended->color_preedit.g, extended->color_preedit.b, extended->color_preedit.a); - LOG_DEBUG(Lib_Ime, "extended: color_button_default={{{},{},{},{}}}", + LOG_DEBUG(Lib_Ime, "extended->color_button_default: {{{},{},{},{}}}", extended->color_button_default.r, extended->color_button_default.g, extended->color_button_default.b, extended->color_button_default.a); - LOG_DEBUG(Lib_Ime, "extended: color_button_function={{{},{},{},{}}}", + LOG_DEBUG(Lib_Ime, "extended->color_button_function: {{{},{},{},{}}}", extended->color_button_function.r, extended->color_button_function.g, extended->color_button_function.b, extended->color_button_function.a); - LOG_DEBUG(Lib_Ime, "extended: color_button_symbol={{{},{},{},{}}}", + LOG_DEBUG(Lib_Ime, "extended->color_button_symbol: {{{},{},{},{}}}", extended->color_button_symbol.r, extended->color_button_symbol.g, extended->color_button_symbol.b, extended->color_button_symbol.a); - LOG_DEBUG(Lib_Ime, "extended: color_text={{{},{},{},{}}}", extended->color_text.r, + LOG_DEBUG(Lib_Ime, "extended->color_text: {{{},{},{},{}}}", extended->color_text.r, extended->color_text.g, extended->color_text.b, extended->color_text.a); - LOG_DEBUG(Lib_Ime, "extended: color_special={{{},{},{},{}}}", extended->color_special.r, + LOG_DEBUG(Lib_Ime, "extended->color_special: {{{},{},{},{}}}", extended->color_special.r, extended->color_special.g, extended->color_special.b, extended->color_special.a); - LOG_DEBUG(Lib_Ime, "extended: priority={}", static_cast(extended->priority)); - LOG_DEBUG(Lib_Ime, "extended: additional_dictionary_path={:p}", + LOG_DEBUG(Lib_Ime, "extended->priority: {}", static_cast(extended->priority)); + LOG_DEBUG(Lib_Ime, "extended->additional_dictionary_path: {:p}", static_cast(extended->additional_dictionary_path)); - LOG_DEBUG(Lib_Ime, "extended: ext_keyboard_filter={:p}", + LOG_DEBUG(Lib_Ime, "extended->ext_keyboard_filter: {:p}", reinterpret_cast(extended->ext_keyboard_filter)); - LOG_DEBUG(Lib_Ime, "extended: disable_device={:032b}", + LOG_DEBUG(Lib_Ime, "extended->disable_device: {:032b}", static_cast(extended->disable_device)); - LOG_DEBUG(Lib_Ime, "extended: ext_keyboard_mode={}", extended->ext_keyboard_mode); + LOG_DEBUG(Lib_Ime, "extended->ext_keyboard_mode: {}", extended->ext_keyboard_mode); } - if (param->user_id < 1 || param->user_id > 4) { - LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid user_id ({})", static_cast(param->user_id)); + if (param->user_id < 1 || param->user_id > 4) { // Todo: check valid user IDs + LOG_ERROR(Lib_Ime, "Invalid user_id: {}", static_cast(param->user_id)); return Error::INVALID_USER_ID; } if (!magic_enum::enum_contains(param->type)) { - LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid type ({})", static_cast(param->type)); + LOG_ERROR(Lib_Ime, "Invalid type: {}", static_cast(param->type)); return Error::INVALID_TYPE; } if (static_cast(param->supported_languages) & ~kValidOrbisImeLanguageMask) { - LOG_ERROR(Lib_Ime, "sceImeOpen: supported_languages has invalid bits (0x{:016X})", - static_cast(param->supported_languages)); + LOG_ERROR(Lib_Ime, + "Invalid supported_languages\n" + "supported_languages: {:064b}\n" + "valid_mask: {:064b}", + static_cast(param->supported_languages), kValidOrbisImeLanguageMask); return Error::INVALID_SUPPORTED_LANGUAGES; } if (!magic_enum::enum_contains(param->enter_label)) { - LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid enter_label ({})", - static_cast(param->enter_label)); + LOG_ERROR(Lib_Ime, "Invalid enter_label: {}", static_cast(param->enter_label)); return Error::INVALID_ENTER_LABEL; } if (!magic_enum::enum_contains(param->input_method)) { - LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid input_method ({})", - static_cast(param->input_method)); + LOG_ERROR(Lib_Ime, "Invalid input_method: {}", static_cast(param->input_method)); return Error::INVALID_INPUT_METHOD; } if (static_cast(param->option) & ~kValidImeOptionMask) { - LOG_ERROR(Lib_Ime, "sceImeOpen: option has invalid bits set (0x{:X}), mask=(0x{:X})", + LOG_ERROR(Lib_Ime, "option has invalid bits set (0x{:X}), mask=(0x{:X})", static_cast(param->option), kValidImeOptionMask); return Error::INVALID_OPTION; } if (param->maxTextLength == 0 || param->maxTextLength > ORBIS_IME_DIALOG_MAX_TEXT_LENGTH) { - LOG_ERROR(Lib_Ime, "sceImeOpen: maxTextLength invalid ({})", param->maxTextLength); + LOG_ERROR(Lib_Ime, "Invalid maxTextLength: {}", param->maxTextLength); return Error::INVALID_MAX_TEXT_LENGTH; } if (!param->inputTextBuffer) { - LOG_ERROR(Lib_Ime, "sceImeOpen: inputTextBuffer is NULL"); + LOG_ERROR(Lib_Ime, "Invalid inputTextBuffer: NULL"); return Error::INVALID_INPUT_TEXT_BUFFER; } @@ -459,23 +514,21 @@ Error PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const OrbisImeParamExt const float maxHeight = useHighRes ? 2160.0f : 1080.0f; if (param->posx < 0.0f || param->posx >= maxWidth) { - LOG_ERROR(Lib_Ime, "sceImeOpen: posx out of range (%.2f), max allowed %.0f", param->posx, - maxWidth); + LOG_ERROR(Lib_Ime, "Invalid posx: {}, range: 0.0 - {}", param->posx, maxWidth); return Error::INVALID_POSX; } if (param->posy < 0.0f || param->posy >= maxHeight) { - LOG_ERROR(Lib_Ime, "sceImeOpen: posy out of range (%.2f), max allowed %.0f", param->posy, - maxHeight); + LOG_ERROR(Lib_Ime, "Invalid posy: {}, range: 0.0 - {}", param->posy, maxHeight); return Error::INVALID_POSY; } if (!magic_enum::enum_contains(param->horizontal_alignment)) { - LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid horizontal_alignment ({})", + LOG_ERROR(Lib_Ime, "Invalid horizontal_alignment: {}", static_cast(param->horizontal_alignment)); return Error::INVALID_HORIZONTALIGNMENT; } if (!magic_enum::enum_contains(param->vertical_alignment)) { - LOG_ERROR(Lib_Ime, "sceImeOpen: Invalid vertical_alignment ({})", + LOG_ERROR(Lib_Ime, "Invalid vertical_alignment: {}", static_cast(param->vertical_alignment)); return Error::INVALID_VERTICALALIGNMENT; } @@ -483,33 +536,51 @@ Error PS4_SYSV_ABI sceImeOpen(const OrbisImeParam* param, const OrbisImeParamExt if (extended) { u32 ext_option_value = static_cast(extended->option); if (ext_option_value & ~kValidImeExtOptionMask) { - LOG_ERROR(Lib_Ime, "sceImeOpen: extended->option has invalid bits set (0x{:X})", - ext_option_value); + LOG_ERROR(Lib_Ime, + "Invalid extended->option\n" + "option: {:032b}\n" + "valid_mask: {:032b}", + ext_option_value, kValidImeExtOptionMask); return Error::INVALID_EXTENDED; } } if (!param->work) { - LOG_ERROR(Lib_Ime, "sceImeOpen: work buffer is NULL"); + LOG_ERROR(Lib_Ime, "Invalid work: NULL"); return Error::INVALID_WORK; } - for (unsigned i = 0; i < sizeof(param->reserved); ++i) { + // Todo: validate arg + if (false) { + LOG_ERROR(Lib_Ime, "Invalid arg: NULL"); + return Error::INVALID_ARG; + } + + // Todo: validate handler + if (false) { + LOG_ERROR(Lib_Ime, "Invalid handler: NULL"); + return Error::INVALID_HANDLER; + } + + for (size_t i = 0; i < sizeof(param->reserved); ++i) { if (param->reserved[i] != 0) { - LOG_ERROR(Lib_Ime, "sceImeOpen: reserved field must be zeroed"); + LOG_ERROR(Lib_Ime, "Invalid reserved: not zeroed"); return Error::INVALID_RESERVED; } } - // Todo: validate arg and handler - if (g_ime_handler) { - LOG_ERROR(Lib_Ime, "sceImeOpen: Error BUSY"); + LOG_ERROR(Lib_Ime, "IME handler is already open"); return Error::BUSY; } g_ime_handler = std::make_unique(param); - LOG_INFO(Lib_Ime, "sceImeOpen: OK"); + if (!g_ime_handler) { + LOG_ERROR(Lib_Ime, "Failed to create IME handler"); + return Error::NO_MEMORY; // or Error::INTERNAL + } + + LOG_INFO(Lib_Ime, "IME handler created successfully"); return Error::OK; } diff --git a/src/core/libraries/ime/ime_common.h b/src/core/libraries/ime/ime_common.h index 13f2bfa8f..457748a2d 100644 --- a/src/core/libraries/ime/ime_common.h +++ b/src/core/libraries/ime/ime_common.h @@ -323,7 +323,7 @@ enum class OrbisImeEventId : u32 { ChangeInputMethodState = 18, KeyboardOpen = 256, - KeyboardKeycodeDoen = 257, + KeyboardKeycodeDown = 257, KeyboardKeycodeUp = 258, KeyboardKeycodeRepeat = 259, KeyboardConnection = 260, diff --git a/src/core/libraries/ime/ime_ui.cpp b/src/core/libraries/ime/ime_ui.cpp index c49c70ede..bf4f06507 100644 --- a/src/core/libraries/ime/ime_ui.cpp +++ b/src/core/libraries/ime/ime_ui.cpp @@ -44,7 +44,7 @@ ImeState& ImeState::operator=(ImeState&& other) noexcept { } void ImeState::SendEvent(OrbisImeEvent* event) { - std::unique_lock lock{queue_mutex}; + std::unique_lock lock{queue_mutex}; event_queue.push(*event); } @@ -108,7 +108,7 @@ ImeUi& ImeUi::operator=(ImeUi&& other) { } void ImeUi::Draw() { - std::unique_lock lock{draw_mutex}; + std::unique_lock lock{draw_mutex}; if (!state) { return; diff --git a/src/qt_gui/compatibility_info.cpp b/src/qt_gui/compatibility_info.cpp index eecd1bd47..da32f24ae 100644 --- a/src/qt_gui/compatibility_info.cpp +++ b/src/qt_gui/compatibility_info.cpp @@ -22,8 +22,8 @@ void CompatibilityInfoClass::UpdateCompatibilityDatabase(QWidget* parent, bool f if (!forced && LoadCompatibilityFile()) return; - QUrl url("https://github.com/shadps4-compatibility/shadps4-game-compatibility/releases/latest/" - "download/compatibility_data.json"); + QUrl url("https://github.com/shadps4-emu/shadps4-game-compatibility/releases/latest/download/" + "compatibility_data.json"); QNetworkRequest request(url); QNetworkReply* reply = m_network_manager->get(request); diff --git a/src/qt_gui/game_list_frame.cpp b/src/qt_gui/game_list_frame.cpp index e0995d3ef..e4c40b4f9 100644 --- a/src/qt_gui/game_list_frame.cpp +++ b/src/qt_gui/game_list_frame.cpp @@ -91,8 +91,7 @@ GameListFrame::GameListFrame(std::shared_ptr gui_settings, connect(this, &QTableWidget::cellClicked, this, [=, this](int row, int column) { if (column == 2 && m_game_info->m_games[row].compatibility.issue_number != "") { - auto url_issues = - "https://github.com/shadps4-compatibility/shadps4-game-compatibility/issues/"; + auto url_issues = "https://github.com/shadps4-emu/shadps4-game-compatibility/issues/"; QDesktopServices::openUrl( QUrl(url_issues + m_game_info->m_games[row].compatibility.issue_number)); } else if (column == 10) { diff --git a/src/qt_gui/gui_context_menus.h b/src/qt_gui/gui_context_menus.h index 110421002..6c384c4bc 100644 --- a/src/qt_gui/gui_context_menus.h +++ b/src/qt_gui/gui_context_menus.h @@ -581,7 +581,7 @@ public: if (selected == viewCompatibilityReport) { if (m_games[itemID].compatibility.issue_number != "") { auto url_issues = - "https://github.com/shadps4-compatibility/shadps4-game-compatibility/issues/"; + "https://github.com/shadps4-emu/shadps4-game-compatibility/issues/"; QDesktopServices::openUrl( QUrl(url_issues + m_games[itemID].compatibility.issue_number)); } @@ -589,8 +589,8 @@ public: if (selected == submitCompatibilityReport) { if (m_games[itemID].compatibility.issue_number == "") { - QUrl url = QUrl("https://github.com/shadps4-compatibility/" - "shadps4-game-compatibility/issues/new"); + QUrl url = + QUrl("https://github.com/shadps4-emu/shadps4-game-compatibility/issues/new"); QUrlQuery query; query.addQueryItem("template", QString("game_compatibility.yml")); query.addQueryItem( @@ -605,7 +605,7 @@ public: QDesktopServices::openUrl(url); } else { auto url_issues = - "https://github.com/shadps4-compatibility/shadps4-game-compatibility/issues/"; + "https://github.com/shadps4-emu/shadps4-game-compatibility/issues/"; QDesktopServices::openUrl( QUrl(url_issues + m_games[itemID].compatibility.issue_number)); } diff --git a/src/qt_gui/gui_settings.h b/src/qt_gui/gui_settings.h index 4d2a1b7f7..4c1eafc95 100644 --- a/src/qt_gui/gui_settings.h +++ b/src/qt_gui/gui_settings.h @@ -37,7 +37,6 @@ const gui_value gl_showBackgroundImage = gui_value(game_list, "showBackgroundIma const gui_value gl_backgroundImageOpacity = gui_value(game_list, "backgroundImageOpacity", 50); const gui_value gl_playBackgroundMusic = gui_value(game_list, "playBackgroundMusic", true); const gui_value gl_backgroundMusicVolume = gui_value(game_list, "backgroundMusicVolume", 50); -const gui_value gl_VolumeSlider = gui_value(game_list, "volumeSlider", 100); // game grid settings const gui_value gg_icon_size = gui_value(game_grid, "icon_size", 69); diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index b08bb5aee..f903562f9 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -11,7 +11,6 @@ #include "common/config.h" #include "common/scm_rev.h" -#include "core/libraries/audio/audioout.h" #include "qt_gui/compatibility_info.h" #ifdef ENABLE_DISCORD_RPC #include "common/discord_rpc_handler.h" @@ -69,7 +68,6 @@ QMap chooseHomeTabMap; int backgroundImageOpacitySlider_backup; int bgm_volume_backup; -int volume_slider_backup; static std::vector m_physical_devices; @@ -151,11 +149,9 @@ SettingsDialog::SettingsDialog(std::shared_ptr gui_settings, } else if (button == ui->buttonBox->button(QDialogButtonBox::Close)) { ui->backgroundImageOpacitySlider->setValue(backgroundImageOpacitySlider_backup); emit BackgroundOpacityChanged(backgroundImageOpacitySlider_backup); - ui->horizontalVolumeSlider->setValue(volume_slider_backup); - Config::setVolumeSlider(volume_slider_backup); ui->BGMVolumeSlider->setValue(bgm_volume_backup); BackgroundMusicPlayer::getInstance().setVolume(bgm_volume_backup); - SyncRealTimeWidgetstoConfig(); + ResetInstallFolders(); } if (Common::Log::IsActive()) { Common::Log::Filter filter; @@ -174,12 +170,6 @@ SettingsDialog::SettingsDialog(std::shared_ptr gui_settings, // GENERAL TAB { - connect(ui->horizontalVolumeSlider, &QSlider::valueChanged, this, [this](int value) { - VolumeSliderChange(value); - Config::setVolumeSlider(value); - Libraries::AudioOut::AdjustVol(); - }); - #ifdef ENABLE_UPDATER #if (QT_VERSION < QT_VERSION_CHECK(6, 7, 0)) connect(ui->updateCheckBox, &QCheckBox::stateChanged, this, [this](int state) { @@ -408,8 +398,6 @@ void SettingsDialog::closeEvent(QCloseEvent* event) { if (!is_saving) { ui->backgroundImageOpacitySlider->setValue(backgroundImageOpacitySlider_backup); emit BackgroundOpacityChanged(backgroundImageOpacitySlider_backup); - ui->horizontalVolumeSlider->setValue(volume_slider_backup); - Config::setVolumeSlider(volume_slider_backup); ui->BGMVolumeSlider->setValue(bgm_volume_backup); BackgroundMusicPlayer::getInstance().setVolume(bgm_volume_backup); } @@ -475,8 +463,6 @@ void SettingsDialog::LoadValuesFromConfig() { ui->radioButton_Bottom->setChecked(side == "bottom"); ui->BGMVolumeSlider->setValue(m_gui_settings->GetValue(gui::gl_backgroundMusicVolume).toInt()); - ui->horizontalVolumeSlider->setValue(m_gui_settings->GetValue(gui::gl_VolumeSlider).toInt()); - ui->volumeText->setText(QString::number(ui->horizontalVolumeSlider->sliderPosition()) + "%"); ui->discordRPCCheckbox->setChecked( toml::find_or(data, "General", "enableDiscordRPC", true)); QString translatedText_FullscreenMode = @@ -546,7 +532,7 @@ void SettingsDialog::LoadValuesFromConfig() { toml::find_or(data, "Input", "isMotionControlsEnabled", true)); ui->removeFolderButton->setEnabled(!ui->gameFoldersListWidget->selectedItems().isEmpty()); - SyncRealTimeWidgetstoConfig(); + ResetInstallFolders(); ui->backgroundImageOpacitySlider->setValue( m_gui_settings->GetValue(gui::gl_backgroundImageOpacity).toInt()); ui->showBackgroundImageCheckBox->setChecked( @@ -555,7 +541,6 @@ void SettingsDialog::LoadValuesFromConfig() { backgroundImageOpacitySlider_backup = m_gui_settings->GetValue(gui::gl_backgroundImageOpacity).toInt(); bgm_volume_backup = m_gui_settings->GetValue(gui::gl_backgroundMusicVolume).toInt(); - volume_slider_backup = m_gui_settings->GetValue(gui::gl_VolumeSlider).toInt(); } void SettingsDialog::InitializeEmulatorLanguages() { @@ -614,10 +599,6 @@ void SettingsDialog::OnCursorStateChanged(s16 index) { } } -void SettingsDialog::VolumeSliderChange(int value) { - ui->volumeText->setText(QString::number(ui->horizontalVolumeSlider->sliderPosition()) + "%"); -} - int SettingsDialog::exec() { return QDialog::exec(); } @@ -738,6 +719,7 @@ bool SettingsDialog::eventFilter(QObject* obj, QEvent* event) { if (qobject_cast(obj)) { bool hovered = (event->type() == QEvent::Enter); QString elementName = obj->objectName(); + if (hovered) { updateNoteTextEdit(elementName); } else { @@ -777,7 +759,6 @@ void SettingsDialog::UpdateSettings() { Config::setCursorState(ui->hideCursorComboBox->currentIndex()); Config::setCursorHideTimeout(ui->idleTimeoutSpinBox->value()); Config::setGpuId(ui->graphicsAdapterBox->currentIndex() - 1); - m_gui_settings->SetValue(gui::gl_VolumeSlider, ui->horizontalVolumeSlider->value()); m_gui_settings->SetValue(gui::gl_backgroundMusicVolume, ui->BGMVolumeSlider->value()); Config::setLanguage(languageIndexes[ui->consoleLanguageComboBox->currentIndex()]); Config::setEnableDiscordRPC(ui->discordRPCCheckbox->isChecked()); @@ -834,10 +815,9 @@ void SettingsDialog::UpdateSettings() { #endif BackgroundMusicPlayer::getInstance().setVolume(ui->BGMVolumeSlider->value()); - Config::setVolumeSlider(ui->horizontalVolumeSlider->value()); } -void SettingsDialog::SyncRealTimeWidgetstoConfig() { +void SettingsDialog::ResetInstallFolders() { ui->gameFoldersListWidget->clear(); std::filesystem::path userdir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); @@ -885,7 +865,6 @@ void SettingsDialog::setDefaultValues() { m_gui_settings->SetValue(gui::gl_backgroundImageOpacity, 50); m_gui_settings->SetValue(gui::gl_playBackgroundMusic, false); m_gui_settings->SetValue(gui::gl_backgroundMusicVolume, 50); - m_gui_settings->SetValue(gui::gl_VolumeSlider, 100); m_gui_settings->SetValue(gui::gen_checkForUpdates, false); m_gui_settings->SetValue(gui::gen_showChangeLog, false); if (Common::g_is_release) { @@ -894,4 +873,4 @@ void SettingsDialog::setDefaultValues() { m_gui_settings->SetValue(gui::gen_updateChannel, "Nightly"); } m_gui_settings->SetValue(gui::gen_guiLanguage, "en_US"); -} +} \ No newline at end of file diff --git a/src/qt_gui/settings_dialog.h b/src/qt_gui/settings_dialog.h index 13fab36a2..d9fbcb214 100644 --- a/src/qt_gui/settings_dialog.h +++ b/src/qt_gui/settings_dialog.h @@ -39,13 +39,12 @@ signals: private: void LoadValuesFromConfig(); void UpdateSettings(); - void SyncRealTimeWidgetstoConfig(); + void ResetInstallFolders(); void InitializeEmulatorLanguages(); void OnLanguageChanged(int index); void OnCursorStateChanged(s16 index); void closeEvent(QCloseEvent* event) override; void setDefaultValues(); - void VolumeSliderChange(int value); std::unique_ptr ui; diff --git a/src/qt_gui/settings_dialog.ui b/src/qt_gui/settings_dialog.ui index 9ebb1cbc1..8d239b58c 100644 --- a/src/qt_gui/settings_dialog.ui +++ b/src/qt_gui/settings_dialog.ui @@ -59,7 +59,7 @@ - 0 + 5 @@ -73,8 +73,8 @@ 0 0 - 944 - 537 + 946 + 536 @@ -86,20 +86,135 @@ 6 - - - - Qt::Orientation::Vertical + + + + 0 - - - 20 - 40 - + + 0 - + + 0 + + + + + + 0 + 0 + + + + Emulator + + + false + + + false + + + + 6 + + + 9 + + + 9 + + + 9 + + + 9 + + + + + 10 + + + + + Show Splash + + + + + + + Enable Discord Rich Presence + + + + + + + + + - + + + + 6 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + System + + + + 70 + + + + + Console Language + + + + + + + + + + + + Emulator Language + + + + + + + + + + + + + + Qt::Orientation::Vertical @@ -112,7 +227,33 @@ - + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + 6 @@ -286,228 +427,6 @@ - - - - 6 - - - 0 - - - - - - 0 - 0 - - - - - 0 - 0 - - - - System - - - - 70 - - - - - Console Language - - - - - - - - - - - - Emulator Language - - - - - - - - - - - - - - - - - Volume - - - - - - - 0 - 0 - - - - - - - true - - - - - 0 - 0 - 414 - 69 - - - - - - - - 0 - 0 - - - - - 60 - 16777215 - - - - 100% - - - Qt::AlignmentFlag::AlignCenter - - - true - - - - - - - Qt::FocusPolicy::StrongFocus - - - 500 - - - 100 - - - 100 - - - Qt::Orientation::Horizontal - - - - - - - - - - - - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - Emulator - - - false - - - false - - - - 6 - - - 9 - - - 9 - - - 9 - - - 9 - - - - - 10 - - - - - Show Splash - - - - - - - Enable Discord Rich Presence - - - - - - - - - - - - - - Qt::Orientation::Vertical - - - - 20 - 40 - - - - @@ -525,8 +444,8 @@ 0 0 - 944 - 537 + 946 + 536 @@ -781,7 +700,7 @@ - + 0 0 @@ -974,8 +893,8 @@ 0 0 - 944 - 537 + 946 + 536 @@ -1269,8 +1188,8 @@ 0 0 - 944 - 537 + 946 + 536 @@ -1511,8 +1430,8 @@ 0 0 - 944 - 537 + 946 + 536 @@ -1765,8 +1684,8 @@ 0 0 - 944 - 537 + 946 + 536 @@ -1907,8 +1826,8 @@ 0 0 - 944 - 537 + 946 + 536 diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp index fe2d64d2f..80c8b836b 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_atomic.cpp @@ -268,7 +268,6 @@ Id EmitBufferAtomicFMin32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addre const auto sign_bit_set = ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u)); - // FIXME this needs control flow because it currently executes both atomics const auto result = ctx.OpSelect( ctx.F32[1], sign_bit_set, EmitBitCastF32U32(ctx, EmitBufferAtomicUMax32(ctx, inst, handle, address, u32_value)), @@ -303,7 +302,6 @@ Id EmitBufferAtomicFMax32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addre const auto sign_bit_set = ctx.OpBitFieldUExtract(ctx.U32[1], u32_value, ctx.ConstU32(31u), ctx.ConstU32(1u)); - // FIXME this needs control flow because it currently executes both atomics const auto result = ctx.OpSelect( ctx.F32[1], sign_bit_set, EmitBitCastF32U32(ctx, EmitBufferAtomicUMin32(ctx, inst, handle, address, u32_value)), diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp index 2f4984f57..c75f43393 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_convert.cpp @@ -7,32 +7,60 @@ namespace Shader::Backend::SPIRV { namespace { Id ExtractU16(EmitContext& ctx, Id value) { - return ctx.OpUConvert(ctx.U16, value); + if (ctx.profile.support_int16) { + return ctx.OpUConvert(ctx.U16, value); + } else { + return ctx.OpBitFieldUExtract(ctx.U32[1], value, ctx.u32_zero_value, ctx.ConstU32(16u)); + } } Id ExtractS16(EmitContext& ctx, Id value) { - return ctx.OpSConvert(ctx.S16, value); + if (ctx.profile.support_int16) { + return ctx.OpSConvert(ctx.S16, value); + } else { + return ctx.OpBitFieldSExtract(ctx.U32[1], value, ctx.u32_zero_value, ctx.ConstU32(16u)); + } } Id ExtractU8(EmitContext& ctx, Id value) { - return ctx.OpUConvert(ctx.U8, value); + if (ctx.profile.support_int8) { + return ctx.OpUConvert(ctx.U8, value); + } else { + return ctx.OpBitFieldUExtract(ctx.U32[1], value, ctx.u32_zero_value, ctx.ConstU32(8u)); + } } Id ExtractS8(EmitContext& ctx, Id value) { - return ctx.OpSConvert(ctx.S8, value); + if (ctx.profile.support_int8) { + return ctx.OpSConvert(ctx.S8, value); + } else { + return ctx.OpBitFieldSExtract(ctx.U32[1], value, ctx.u32_zero_value, ctx.ConstU32(8u)); + } } } // Anonymous namespace Id EmitConvertS16F16(EmitContext& ctx, Id value) { - return ctx.OpSConvert(ctx.U32[1], ctx.OpConvertFToS(ctx.U16, value)); + if (ctx.profile.support_int16) { + return ctx.OpSConvert(ctx.U32[1], ctx.OpConvertFToS(ctx.U16, value)); + } else { + return ExtractS16(ctx, ctx.OpConvertFToS(ctx.U32[1], value)); + } } Id EmitConvertS16F32(EmitContext& ctx, Id value) { - return ctx.OpSConvert(ctx.U32[1], ctx.OpConvertFToS(ctx.U16, value)); + if (ctx.profile.support_int16) { + return ctx.OpSConvert(ctx.U32[1], ctx.OpConvertFToS(ctx.U16, value)); + } else { + return ExtractS16(ctx, ctx.OpConvertFToS(ctx.U32[1], value)); + } } Id EmitConvertS16F64(EmitContext& ctx, Id value) { - return ctx.OpSConvert(ctx.U32[1], ctx.OpConvertFToS(ctx.U16, value)); + if (ctx.profile.support_int16) { + return ctx.OpSConvert(ctx.U32[1], ctx.OpConvertFToS(ctx.U16, value)); + } else { + return ExtractS16(ctx, ctx.OpConvertFToS(ctx.U32[1], value)); + } } Id EmitConvertS32F16(EmitContext& ctx, Id value) { @@ -60,15 +88,27 @@ Id EmitConvertS64F64(EmitContext& ctx, Id value) { } Id EmitConvertU16F16(EmitContext& ctx, Id value) { - return ctx.OpUConvert(ctx.U32[1], ctx.OpConvertFToU(ctx.U16, value)); + if (ctx.profile.support_int16) { + return ctx.OpUConvert(ctx.U32[1], ctx.OpConvertFToU(ctx.U16, value)); + } else { + return ExtractU16(ctx, ctx.OpConvertFToU(ctx.U32[1], value)); + } } Id EmitConvertU16F32(EmitContext& ctx, Id value) { - return ctx.OpUConvert(ctx.U32[1], ctx.OpConvertFToU(ctx.U16, value)); + if (ctx.profile.support_int16) { + return ctx.OpUConvert(ctx.U32[1], ctx.OpConvertFToU(ctx.U16, value)); + } else { + return ExtractU16(ctx, ctx.OpConvertFToU(ctx.U32[1], value)); + } } Id EmitConvertU16F64(EmitContext& ctx, Id value) { - return ctx.OpUConvert(ctx.U32[1], ctx.OpConvertFToU(ctx.U16, value)); + if (ctx.profile.support_int16) { + return ctx.OpUConvert(ctx.U32[1], ctx.OpConvertFToU(ctx.U16, value)); + } else { + return ExtractU16(ctx, ctx.OpConvertFToU(ctx.U32[1], value)); + } } Id EmitConvertU32F16(EmitContext& ctx, Id value) { @@ -231,12 +271,4 @@ Id EmitConvertU32U8(EmitContext& ctx, Id value) { return ctx.OpUConvert(ctx.U32[1], value); } -Id EmitConvertS32S8(EmitContext& ctx, Id value) { - return ctx.OpSConvert(ctx.U32[1], value); -} - -Id EmitConvertS32S16(EmitContext& ctx, Id value) { - return ctx.OpSConvert(ctx.U32[1], value); -} - } // namespace Shader::Backend::SPIRV diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index a8c58bdba..37d5d84c9 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h @@ -488,8 +488,6 @@ Id EmitConvertU16U32(EmitContext& ctx, Id value); Id EmitConvertU32U16(EmitContext& ctx, Id value); Id EmitConvertU8U32(EmitContext& ctx, Id value); Id EmitConvertU32U8(EmitContext& ctx, Id value); -Id EmitConvertS32S8(EmitContext& ctx, Id value); -Id EmitConvertS32S16(EmitContext& ctx, Id value); Id EmitImageSampleRaw(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address1, Id address2, Id address3, Id address4); diff --git a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp index a8ffe6ae5..f373808d9 100644 --- a/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp +++ b/src/shader_recompiler/backend/spirv/spirv_emit_context.cpp @@ -117,9 +117,7 @@ void EmitContext::DefineArithmeticTypes() { void_id = Name(TypeVoid(), "void_id"); U1[1] = Name(TypeBool(), "bool_id"); U8 = Name(TypeUInt(8), "u8_id"); - S8 = Name(TypeSInt(8), "i8_id"); U16 = Name(TypeUInt(16), "u16_id"); - S16 = Name(TypeSInt(16), "i16_id"); if (info.uses_fp16) { F16[1] = Name(TypeFloat(16), "f16_id"); U16 = Name(TypeUInt(16), "u16_id"); diff --git a/src/shader_recompiler/frontend/translate/translate.h b/src/shader_recompiler/frontend/translate/translate.h index ae904b822..a29bdc993 100644 --- a/src/shader_recompiler/frontend/translate/translate.h +++ b/src/shader_recompiler/frontend/translate/translate.h @@ -281,10 +281,9 @@ public: // Buffer Memory // MUBUF / MTBUF - void BUFFER_LOAD(u32 num_dwords, bool is_inst_typed, bool is_buffer_typed, const GcnInst& inst, - u32 scalar_width = 32, bool is_signed = false); - void BUFFER_STORE(u32 num_dwords, bool is_inst_typed, bool is_buffer_typed, const GcnInst& inst, - u32 scalar_width = 32); + void BUFFER_LOAD(u32 num_dwords, bool is_inst_typed, bool is_buffer_typed, const GcnInst& inst); + void BUFFER_STORE(u32 num_dwords, bool is_inst_typed, bool is_buffer_typed, + const GcnInst& inst); template void BUFFER_ATOMIC(AtomicOp op, const GcnInst& inst); diff --git a/src/shader_recompiler/frontend/translate/vector_memory.cpp b/src/shader_recompiler/frontend/translate/vector_memory.cpp index ec9bc200d..df20f7f73 100644 --- a/src/shader_recompiler/frontend/translate/vector_memory.cpp +++ b/src/shader_recompiler/frontend/translate/vector_memory.cpp @@ -28,15 +28,6 @@ void Translator::EmitVectorMemory(const GcnInst& inst) { case Opcode::BUFFER_LOAD_FORMAT_XYZW: return BUFFER_LOAD(4, false, true, inst); - case Opcode::BUFFER_LOAD_UBYTE: - return BUFFER_LOAD(1, false, false, inst, 8, false); - case Opcode::BUFFER_LOAD_SBYTE: - return BUFFER_LOAD(1, false, false, inst, 8, true); - case Opcode::BUFFER_LOAD_USHORT: - return BUFFER_LOAD(1, false, false, inst, 16, false); - case Opcode::BUFFER_LOAD_SSHORT: - return BUFFER_LOAD(1, false, false, inst, 16, true); - case Opcode::BUFFER_LOAD_DWORD: return BUFFER_LOAD(1, false, false, inst); case Opcode::BUFFER_LOAD_DWORDX2: @@ -65,11 +56,6 @@ void Translator::EmitVectorMemory(const GcnInst& inst) { case Opcode::TBUFFER_STORE_FORMAT_XYZW: return BUFFER_STORE(4, true, false, inst); - case Opcode::BUFFER_STORE_BYTE: - return BUFFER_STORE(1, false, false, inst, 8); - case Opcode::BUFFER_STORE_SHORT: - return BUFFER_STORE(1, false, false, inst, 16); - case Opcode::BUFFER_STORE_DWORD: return BUFFER_STORE(1, false, false, inst); case Opcode::BUFFER_STORE_DWORDX2: @@ -200,7 +186,7 @@ void Translator::EmitVectorMemory(const GcnInst& inst) { } void Translator::BUFFER_LOAD(u32 num_dwords, bool is_inst_typed, bool is_buffer_typed, - const GcnInst& inst, u32 scalar_width, bool is_signed) { + const GcnInst& inst) { const auto& mubuf = inst.control.mubuf; const bool is_ring = mubuf.glc && mubuf.slc; const IR::VectorReg vaddr{inst.src[0].code}; @@ -256,26 +242,7 @@ void Translator::BUFFER_LOAD(u32 num_dwords, bool is_inst_typed, bool is_buffer_ ir.SetVectorReg(dst_reg + i, IR::F32{ir.CompositeExtract(value, i)}); } } else { - IR::Value value; - switch (scalar_width) { - case 8: { - IR::U8 byte_val = ir.LoadBufferU8(handle, address, buffer_info); - value = is_signed ? ir.SConvert(32, byte_val) : ir.UConvert(32, byte_val); - break; - } - case 16: { - IR::U16 short_val = ir.LoadBufferU16(handle, address, buffer_info); - value = is_signed ? ir.SConvert(32, short_val) : ir.UConvert(32, short_val); - break; - } - case 32: - value = ir.LoadBufferU32(num_dwords, handle, address, buffer_info); - break; - - default: - UNREACHABLE(); - } - + const IR::Value value = ir.LoadBufferU32(num_dwords, handle, address, buffer_info); if (num_dwords == 1) { ir.SetVectorReg(dst_reg, IR::U32{value}); return; @@ -287,7 +254,7 @@ void Translator::BUFFER_LOAD(u32 num_dwords, bool is_inst_typed, bool is_buffer_ } void Translator::BUFFER_STORE(u32 num_dwords, bool is_inst_typed, bool is_buffer_typed, - const GcnInst& inst, u32 scalar_width) { + const GcnInst& inst) { const auto& mubuf = inst.control.mubuf; const bool is_ring = mubuf.glc && mubuf.slc; const IR::VectorReg vaddr{inst.src[0].code}; @@ -347,23 +314,8 @@ void Translator::BUFFER_STORE(u32 num_dwords, bool is_inst_typed, bool is_buffer } ir.StoreBufferFormat(handle, address, ir.CompositeConstruct(comps), buffer_info); } else { - IR::Value value = num_dwords == 1 ? comps[0] : ir.CompositeConstruct(comps); - if (scalar_width != 32) { - value = ir.UConvert(scalar_width, IR::U32{value}); - } - switch (scalar_width) { - case 8: - ir.StoreBufferU8(handle, address, IR::U8{value}, buffer_info); - break; - case 16: - ir.StoreBufferU16(handle, address, IR::U16{value}, buffer_info); - break; - case 32: - ir.StoreBufferU32(num_dwords, handle, address, value, buffer_info); - break; - default: - UNREACHABLE(); - } + const auto value = num_dwords == 1 ? comps[0] : ir.CompositeConstruct(comps); + ir.StoreBufferU32(num_dwords, handle, address, value, buffer_info); } } diff --git a/src/shader_recompiler/ir/ir_emitter.cpp b/src/shader_recompiler/ir/ir_emitter.cpp index a6d43d102..6ca86b2c0 100644 --- a/src/shader_recompiler/ir/ir_emitter.cpp +++ b/src/shader_recompiler/ir/ir_emitter.cpp @@ -1979,24 +1979,6 @@ U8U16U32U64 IREmitter::UConvert(size_t result_bitsize, const U8U16U32U64& value) throw NotImplementedException("Conversion from {} to {} bits", value.Type(), result_bitsize); } -U8U16U32U64 IR::IREmitter::SConvert(size_t result_bitsize, const U8U16U32U64& value) { - switch (result_bitsize) { - case 32: - switch (value.Type()) { - case Type::U8: - return Inst(Opcode::ConvertS32S8, value); - case Type::U16: - return Inst(Opcode::ConvertS32S16, value); - default: - break; - } - default: - break; - } - throw NotImplementedException("Signed Conversion from {} to {} bits", value.Type(), - result_bitsize); -} - F16F32F64 IREmitter::FPConvert(size_t result_bitsize, const F16F32F64& value) { switch (result_bitsize) { case 16: diff --git a/src/shader_recompiler/ir/ir_emitter.h b/src/shader_recompiler/ir/ir_emitter.h index e4afb8739..a105b042d 100644 --- a/src/shader_recompiler/ir/ir_emitter.h +++ b/src/shader_recompiler/ir/ir_emitter.h @@ -325,7 +325,6 @@ public: const Value& value); [[nodiscard]] U8U16U32U64 UConvert(size_t result_bitsize, const U8U16U32U64& value); - [[nodiscard]] U8U16U32U64 SConvert(size_t result_bitsize, const U8U16U32U64& value); [[nodiscard]] F16F32F64 FPConvert(size_t result_bitsize, const F16F32F64& value); [[nodiscard]] Value ImageAtomicIAdd(const Value& handle, const Value& coords, diff --git a/src/shader_recompiler/ir/opcodes.inc b/src/shader_recompiler/ir/opcodes.inc index 280cd47ec..747a27e35 100644 --- a/src/shader_recompiler/ir/opcodes.inc +++ b/src/shader_recompiler/ir/opcodes.inc @@ -432,8 +432,6 @@ OPCODE(ConvertU16U32, U16, U32, OPCODE(ConvertU32U16, U32, U16, ) OPCODE(ConvertU8U32, U8, U32, ) OPCODE(ConvertU32U8, U32, U8, ) -OPCODE(ConvertS32S8, U32, U8, ) -OPCODE(ConvertS32S16, U32, U16, ) // Image operations OPCODE(ImageSampleRaw, F32x4, Opaque, F32x4, F32x4, F32x4, F32, Opaque, ) diff --git a/src/shader_recompiler/runtime_info.h b/src/shader_recompiler/runtime_info.h index 61954bec2..6cede44a8 100644 --- a/src/shader_recompiler/runtime_info.h +++ b/src/shader_recompiler/runtime_info.h @@ -171,7 +171,6 @@ enum class MrtSwizzle : u8 { static constexpr u32 MaxColorBuffers = 8; struct PsColorBuffer { - AmdGpu::DataFormat data_format : 6; AmdGpu::NumberFormat num_format : 4; AmdGpu::NumberConversion num_conversion : 3; AmdGpu::Liverpool::ShaderExportFormat export_format : 4; diff --git a/src/video_core/amdgpu/pixel_format.h b/src/video_core/amdgpu/pixel_format.h index 45c688e57..bd0f778f4 100644 --- a/src/video_core/amdgpu/pixel_format.h +++ b/src/video_core/amdgpu/pixel_format.h @@ -248,15 +248,6 @@ constexpr CompMapping RemapSwizzle(const DataFormat format, const CompMapping sw result.a = swizzle.r; return result; } - case DataFormat::Format5_6_5: { - // Remap to a more supported component order. - CompMapping result; - result.r = swizzle.b; - result.g = swizzle.g; - result.b = swizzle.r; - result.a = swizzle.a; - return result; - } default: return swizzle; } diff --git a/src/video_core/buffer_cache/buffer_cache.cpp b/src/video_core/buffer_cache/buffer_cache.cpp index c5e5d18f8..42e3c61a5 100644 --- a/src/video_core/buffer_cache/buffer_cache.cpp +++ b/src/video_core/buffer_cache/buffer_cache.cpp @@ -961,15 +961,15 @@ bool BufferCache::SynchronizeBufferFromImage(Buffer& buffer, VAddr device_addr, const u32 height = std::max(image.info.size.height >> m, 1u); const u32 depth = image.info.props.is_volume ? std::max(image.info.size.depth >> m, 1u) : 1u; - const auto [mip_size, mip_pitch, mip_height, mip_ofs] = image.info.mips_layout[m]; + const auto& [mip_size, mip_pitch, mip_height, mip_ofs] = image.info.mips_layout[m]; offset += mip_ofs; if (offset + mip_size > max_offset) { break; } copies.push_back({ .bufferOffset = offset, - .bufferRowLength = mip_pitch, - .bufferImageHeight = mip_height, + .bufferRowLength = static_cast(mip_pitch), + .bufferImageHeight = static_cast(mip_height), .imageSubresource{ .aspectMask = image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil, .mipLevel = m, diff --git a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp index 51411be7f..cd597e16c 100644 --- a/src/video_core/renderer_vulkan/liverpool_to_vk.cpp +++ b/src/video_core/renderer_vulkan/liverpool_to_vk.cpp @@ -671,7 +671,7 @@ std::span SurfaceFormats() { vk::Format::eR32G32B32A32Sfloat), // 5_6_5 CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format5_6_5, AmdGpu::NumberFormat::Unorm, - vk::Format::eR5G6B5UnormPack16), + vk::Format::eB5G6R5UnormPack16), // 1_5_5_5 CreateSurfaceFormatInfo(AmdGpu::DataFormat::Format1_5_5_5, AmdGpu::NumberFormat::Unorm, vk::Format::eA1R5G5B5UnormPack16), diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 8094bc260..4d89c83b2 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -244,24 +244,9 @@ GraphicsPipeline::GraphicsPipeline( const auto depth_format = instance.GetSupportedFormat(LiverpoolToVK::DepthFormat(key.z_format, key.stencil_format), vk::FormatFeatureFlagBits2::eDepthStencilAttachment); - std::array color_formats; - for (s32 i = 0; i < key.num_color_attachments; ++i) { - const auto& col_buf = key.color_buffers[i]; - const auto format = LiverpoolToVK::SurfaceFormat(col_buf.data_format, col_buf.num_format); - const auto color_format = - instance.GetSupportedFormat(format, vk::FormatFeatureFlagBits2::eColorAttachment); - if (!instance.IsFormatSupported(color_format, - vk::FormatFeatureFlagBits2::eColorAttachment)) { - LOG_WARNING(Render_Vulkan, - "color buffer format {} does not support COLOR_ATTACHMENT_BIT", - vk::to_string(color_format)); - } - color_formats[i] = color_format; - } - const vk::PipelineRenderingCreateInfo pipeline_rendering_ci = { .colorAttachmentCount = key.num_color_attachments, - .pColorAttachmentFormats = color_formats.data(), + .pColorAttachmentFormats = key.color_formats.data(), .depthAttachmentFormat = key.z_format != Liverpool::DepthBuffer::ZFormat::Invalid ? depth_format : vk::Format::eUndefined, diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h index aaf47ba7d..75b8c8c73 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.h +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.h @@ -36,6 +36,7 @@ struct GraphicsPipelineKey { std::array vertex_buffer_formats; u32 patch_control_points; u32 num_color_attachments; + std::array color_formats; std::array color_buffers; std::array blend_controls; std::array write_masks; diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 6e5351ddd..119c0a367 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -669,12 +669,6 @@ vk::Format Instance::GetSupportedFormat(const vk::Format format, if (IsFormatSupported(vk::Format::eD32SfloatS8Uint, flags)) { return vk::Format::eD32SfloatS8Uint; } - break; - case vk::Format::eR8Srgb: - if (IsFormatSupported(vk::Format::eR8Unorm, flags)) { - return vk::Format::eR8Unorm; - } - break; default: break; } diff --git a/src/video_core/renderer_vulkan/vk_instance.h b/src/video_core/renderer_vulkan/vk_instance.h index b21e00a71..9be2d9520 100644 --- a/src/video_core/renderer_vulkan/vk_instance.h +++ b/src/video_core/renderer_vulkan/vk_instance.h @@ -94,21 +94,6 @@ public: return features.shaderFloat64; } - /// Returns true if 64-bit ints are supported in shaders - bool IsShaderInt64Supported() const { - return features.shaderInt64; - } - - /// Returns true if 16-bit ints are supported in shaders - bool IsShaderInt16Supported() const { - return features.shaderInt16; - } - - /// Returns true if 8-bit ints are supported in shaders - bool IsShaderInt8Supported() const { - return vk12_features.shaderInt8; - } - /// Returns true when VK_EXT_custom_border_color is supported bool IsCustomBorderColorSupported() const { return custom_border_color; diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index bce16cbff..4de8fd73b 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -203,9 +203,6 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_, profile = Shader::Profile{ .supported_spirv = SpirvVersion1_6, .subgroup_size = instance.SubgroupSize(), - .support_int8 = instance.IsShaderInt8Supported(), - .support_int16 = instance.IsShaderInt16Supported(), - .support_int64 = instance.IsShaderInt64Supported(), .support_float64 = instance.IsShaderFloat64Supported(), .support_fp32_denorm_preserve = bool(vk12_props.shaderDenormPreserveFloat32), .support_fp32_denorm_flush = bool(vk12_props.shaderDenormFlushToZeroFloat32), @@ -315,6 +312,7 @@ bool PipelineCache::RefreshGraphicsKey() { // attachments. This might be not a case as HW color buffers can be bound in an arbitrary // order. We need to do some arrays compaction at this stage key.num_color_attachments = 0; + key.color_formats.fill(vk::Format::eUndefined); key.color_buffers.fill({}); key.blend_controls.fill({}); key.write_masks.fill({}); @@ -350,8 +348,16 @@ bool PipelineCache::RefreshGraphicsKey() { col_buf.GetDataFmt() == AmdGpu::DataFormat::Format8_8 || col_buf.GetDataFmt() == AmdGpu::DataFormat::Format8_8_8_8); + const auto format = + LiverpoolToVK::SurfaceFormat(col_buf.GetDataFmt(), col_buf.GetNumberFmt()); + key.color_formats[remapped_cb] = format; + if (!instance.IsFormatSupported(format, vk::FormatFeatureFlagBits2::eColorAttachment)) { + LOG_WARNING(Render_Vulkan, + "color buffer format {} does not support COLOR_ATTACHMENT_BIT", + vk::to_string(format)); + } + key.color_buffers[remapped_cb] = Shader::PsColorBuffer{ - .data_format = col_buf.GetDataFmt(), .num_format = col_buf.GetNumberFmt(), .num_conversion = col_buf.GetNumberConversion(), .export_format = regs.color_export_format.GetFormat(cb), @@ -470,7 +476,9 @@ bool PipelineCache::RefreshGraphicsKey() { // Attachment is masked out by either color_target_mask or shader mrt_mask. In the case // of the latter we need to change format to undefined, and either way we need to // increment the index for the null attachment binding. - key.color_buffers[remapped_cb++] = {}; + key.color_formats[remapped_cb] = vk::Format::eUndefined; + key.color_buffers[remapped_cb] = {}; + ++remapped_cb; continue; } diff --git a/src/video_core/texture_cache/blit_helper.cpp b/src/video_core/texture_cache/blit_helper.cpp index 4f1d17547..1ad41be00 100644 --- a/src/video_core/texture_cache/blit_helper.cpp +++ b/src/video_core/texture_cache/blit_helper.cpp @@ -126,13 +126,13 @@ void BlitHelper::BlitColorToMsDepth(Image& source, Image& dest) { .minDepth = 0.f, .maxDepth = 1.f, }; - cmdbuf.setViewportWithCount(viewport); + cmdbuf.setViewport(0, viewport); const vk::Rect2D scissor = { .offset = {0, 0}, .extent = {state.width, state.height}, }; - cmdbuf.setScissorWithCount(scissor); + cmdbuf.setScissor(0, scissor); cmdbuf.draw(3, 1, 0, 0); diff --git a/src/video_core/texture_cache/image.cpp b/src/video_core/texture_cache/image.cpp index 4ab2e991c..7b8ff4403 100644 --- a/src/video_core/texture_cache/image.cpp +++ b/src/video_core/texture_cache/image.cpp @@ -21,7 +21,7 @@ static vk::ImageUsageFlags ImageUsageFlags(const ImageInfo& info) { if (info.IsDepthStencil()) { usage |= vk::ImageUsageFlagBits::eDepthStencilAttachment; } else { - if (!info.IsBlockCoded()) { + if (!info.IsBlockCoded() && !info.IsPacked()) { usage |= vk::ImageUsageFlagBits::eColorAttachment; } // In cases where an image is created as a render/depth target and cleared with compute, diff --git a/src/video_core/texture_cache/image_info.cpp b/src/video_core/texture_cache/image_info.cpp index ed10a20bf..769c4211f 100644 --- a/src/video_core/texture_cache/image_info.cpp +++ b/src/video_core/texture_cache/image_info.cpp @@ -176,6 +176,17 @@ bool ImageInfo::IsBlockCoded() const { } } +bool ImageInfo::IsPacked() const { + switch (pixel_format) { + case vk::Format::eB5G5R5A1UnormPack16: + [[fallthrough]]; + case vk::Format::eB5G6R5UnormPack16: + return true; + default: + return false; + } +} + bool ImageInfo::IsDepthStencil() const { switch (pixel_format) { case vk::Format::eD16Unorm: diff --git a/src/video_core/texture_cache/image_info.h b/src/video_core/texture_cache/image_info.h index 9fa3b6c3d..dbd7f7cbb 100644 --- a/src/video_core/texture_cache/image_info.h +++ b/src/video_core/texture_cache/image_info.h @@ -31,6 +31,7 @@ struct ImageInfo { } bool IsBlockCoded() const; + bool IsPacked() const; bool IsDepthStencil() const; bool HasStencil() const; diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index fa24728ad..a6657d8d9 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -605,27 +605,28 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule const u32 height = std::max(image.info.size.height >> m, 1u); const u32 depth = image.info.props.is_volume ? std::max(image.info.size.depth >> m, 1u) : 1u; - const auto [mip_size, mip_pitch, mip_height, mip_offset] = image.info.mips_layout[m]; + const auto& mip = image.info.mips_layout[m]; // Protect GPU modified resources from accidental CPU reuploads. if (is_gpu_modified && !is_gpu_dirty) { const u8* addr = std::bit_cast(image.info.guest_address); - const u64 hash = XXH3_64bits(addr + mip_offset, mip_size); + const u64 hash = XXH3_64bits(addr + mip.offset, mip.size); if (image.mip_hashes[m] == hash) { continue; } image.mip_hashes[m] = hash; } - const u32 extent_width = mip_pitch ? std::min(mip_pitch, width) : width; - const u32 extent_height = mip_height ? std::min(mip_height, height) : height; - const u32 height_aligned = - mip_height && image.info.IsTiled() ? std::max(mip_height, 8U) : mip_height; + auto mip_pitch = static_cast(mip.pitch); + auto mip_height = static_cast(mip.height); + + auto image_extent_width = mip_pitch ? std::min(mip_pitch, width) : width; + auto image_extent_height = mip_height ? std::min(mip_height, height) : height; image_copy.push_back({ - .bufferOffset = mip_offset, + .bufferOffset = mip.offset, .bufferRowLength = mip_pitch, - .bufferImageHeight = height_aligned, + .bufferImageHeight = mip_height, .imageSubresource{ .aspectMask = image.aspect_mask & ~vk::ImageAspectFlagBits::eStencil, .mipLevel = m, @@ -633,7 +634,7 @@ void TextureCache::RefreshImage(Image& image, Vulkan::Scheduler* custom_schedule .layerCount = num_layers, }, .imageOffset = {0, 0, 0}, - .imageExtent = {extent_width, extent_height, depth}, + .imageExtent = {image_extent_width, image_extent_height, depth}, }); }