diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 86ca81c38..55549ab4c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -205,12 +205,12 @@ jobs: run: | mkdir upload mv ${{github.workspace}}/build/shadps4 upload - cp ${{github.workspace}}/build/externals/MoltenVK/libMoltenVK.dylib upload - tar cf shadps4-macos-sdl.tar.gz -C upload . + mv ${{github.workspace}}/build/MoltenVK_icd.json upload + mv ${{github.workspace}}/build/libMoltenVK.dylib upload - uses: actions/upload-artifact@v4 with: name: shadps4-macos-sdl-${{ needs.get-info.outputs.date }}-${{ needs.get-info.outputs.shorthash }} - path: shadps4-macos-sdl.tar.gz + path: upload/ macos-qt: runs-on: macos-15 diff --git a/.gitmodules b/.gitmodules index 9daefe305..065a4570f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -97,7 +97,7 @@ shallow = true [submodule "externals/MoltenVK/SPIRV-Cross"] path = externals/MoltenVK/SPIRV-Cross - url = https://github.com/billhollings/SPIRV-Cross + url = https://github.com/KhronosGroup/SPIRV-Cross shallow = true [submodule "externals/MoltenVK/MoltenVK"] path = externals/MoltenVK/MoltenVK diff --git a/CMakeLists.txt b/CMakeLists.txt index 6b67bc6a7..9747080e1 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,7 +202,7 @@ execute_process( # Set Version set(EMULATOR_VERSION_MAJOR "0") -set(EMULATOR_VERSION_MINOR "7") +set(EMULATOR_VERSION_MINOR "8") set(EMULATOR_VERSION_PATCH "1") set_source_files_properties(src/shadps4.rc PROPERTIES COMPILE_DEFINITIONS "EMULATOR_VERSION_MAJOR=${EMULATOR_VERSION_MAJOR};EMULATOR_VERSION_MINOR=${EMULATOR_VERSION_MINOR};EMULATOR_VERSION_PATCH=${EMULATOR_VERSION_PATCH}") @@ -1089,34 +1089,45 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND ENABLE_USERFAULTFD) endif() if (APPLE) - if (ENABLE_QT_GUI) - # Include MoltenVK in the app bundle, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers. - set(MVK_ICD ${CMAKE_CURRENT_SOURCE_DIR}/externals/MoltenVK/MoltenVK_icd.json) - target_sources(shadps4 PRIVATE ${MVK_ICD}) - set_source_files_properties(${MVK_ICD} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/vulkan/icd.d) + # Include MoltenVK, along with an ICD file so it can be found by the system Vulkan loader if used for loading layers. + set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib) - set(MVK_DYLIB_SRC ${CMAKE_CURRENT_BINARY_DIR}/externals/MoltenVK/libMoltenVK.dylib) - set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Frameworks/libMoltenVK.dylib) - add_custom_command( - OUTPUT ${MVK_DYLIB_DST} - DEPENDS ${MVK_DYLIB_SRC} - COMMAND cmake -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST}) - add_custom_target(CopyMoltenVK DEPENDS ${MVK_DYLIB_DST}) - add_dependencies(CopyMoltenVK MoltenVK) - add_dependencies(shadps4 CopyMoltenVK) - set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks") - else() - # For non-bundled SDL build, just do a normal library link. - target_link_libraries(shadps4 PRIVATE MoltenVK) - endif() + if (ENABLE_QT_GUI) + set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path/../Frameworks") + set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Resources/vulkan/icd.d/MoltenVK_icd.json) + set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/shadps4.app/Contents/Frameworks/libMoltenVK.dylib) + set(MVK_DYLIB_ICD_PATH "../../../Frameworks/libMoltenVK.dylib") + else() + set_property(TARGET shadps4 APPEND PROPERTY BUILD_RPATH "@executable_path") + set(MVK_ICD_DST ${CMAKE_CURRENT_BINARY_DIR}/MoltenVK_icd.json) + set(MVK_DYLIB_DST ${CMAKE_CURRENT_BINARY_DIR}/libMoltenVK.dylib) + set(MVK_DYLIB_ICD_PATH "./libMoltenVK.dylib") + endif() - if (ARCHITECTURE STREQUAL "x86_64") - # Reserve system-managed memory space. - target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,SYSTEM_MANAGED,0x400000,-segaddr,SYSTEM_RESERVED,0x7FFFFC000,-image_base,0x20000000000) - endif() + cmake_path(GET MVK_ICD_DST PARENT_PATH MVK_ICD_DST_PARENT) + cmake_path(GET MVK_DYLIB_DST PARENT_PATH MVK_DYLIB_DST_PARENT) - # Replacement for std::chrono::time_zone - target_link_libraries(shadps4 PRIVATE date::date-tz) + set(MVK_ICD "\\\{ \\\"file_format_version\\\": \\\"1.0.0\\\", \\\"ICD\\\": \\\{ \\\"library_path\\\": \\\"${MVK_DYLIB_ICD_PATH}\\\", \\\"api_version\\\": \\\"1.2.0\\\", \\\"is_portability_driver\\\": true \\\} \\\}") + add_custom_command( + OUTPUT ${MVK_ICD_DST} + COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_ICD_DST_PARENT} && ${CMAKE_COMMAND} -E echo ${MVK_ICD} > ${MVK_ICD_DST}) + + add_custom_command( + OUTPUT ${MVK_DYLIB_DST} + DEPENDS ${MVK_DYLIB_SRC} + COMMAND ${CMAKE_COMMAND} -E make_directory ${MVK_DYLIB_DST_PARENT} && ${CMAKE_COMMAND} -E copy ${MVK_DYLIB_SRC} ${MVK_DYLIB_DST}) + + add_custom_target(CopyMoltenVK DEPENDS ${MVK_ICD_DST} ${MVK_DYLIB_DST}) + add_dependencies(CopyMoltenVK MoltenVK) + add_dependencies(shadps4 CopyMoltenVK) + + if (ARCHITECTURE STREQUAL "x86_64") + # Reserve system-managed memory space. + target_link_options(shadps4 PRIVATE -Wl,-no_pie,-no_fixup_chains,-no_huge,-pagezero_size,0x4000,-segaddr,TCB_SPACE,0x4000,-segaddr,SYSTEM_MANAGED,0x400000,-segaddr,SYSTEM_RESERVED,0x7FFFFC000,-image_base,0x20000000000) + endif() + + # Replacement for std::chrono::time_zone + target_link_libraries(shadps4 PRIVATE date::date-tz) endif() if (NOT ENABLE_QT_GUI) diff --git a/README.md b/README.md index e24d57807..985bba586 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ SPDX-License-Identifier: GPL-2.0-or-later

- + diff --git a/dist/net.shadps4.shadPS4.metainfo.xml b/dist/net.shadps4.shadPS4.metainfo.xml index 99f9e070d..9f7b4f9c5 100644 --- a/dist/net.shadps4.shadPS4.metainfo.xml +++ b/dist/net.shadps4.shadPS4.metainfo.xml @@ -37,6 +37,9 @@ Game + + https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.8.0 + https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.7.0 diff --git a/externals/MoltenVK/MoltenVK b/externals/MoltenVK/MoltenVK index 067fc6c85..4cf8f9468 160000 --- a/externals/MoltenVK/MoltenVK +++ b/externals/MoltenVK/MoltenVK @@ -1 +1 @@ -Subproject commit 067fc6c85b02f37dfda58eeda49d8458e093ed60 +Subproject commit 4cf8f94684c53e581eb9cc694dd3305d1f7d9959 diff --git a/externals/MoltenVK/MoltenVK_icd.json b/externals/MoltenVK/MoltenVK_icd.json deleted file mode 100644 index 2c3319263..000000000 --- a/externals/MoltenVK/MoltenVK_icd.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "file_format_version": "1.0.0", - "ICD": { - "library_path": "../../../Frameworks/libMoltenVK.dylib", - "api_version": "1.2.0", - "is_portability_driver": true - } -} diff --git a/externals/MoltenVK/SPIRV-Cross b/externals/MoltenVK/SPIRV-Cross index 185833a61..2275d0efc 160000 --- a/externals/MoltenVK/SPIRV-Cross +++ b/externals/MoltenVK/SPIRV-Cross @@ -1 +1 @@ -Subproject commit 185833a61cbe29ce3bfb5a499ffb3dfeaee3bbe7 +Subproject commit 2275d0efc4f2fa46851035d9d3c67c105bc8b99e diff --git a/src/common/path_util.cpp b/src/common/path_util.cpp index 702d0fabc..1a6ff9ec8 100644 --- a/src/common/path_util.cpp +++ b/src/common/path_util.cpp @@ -60,7 +60,7 @@ static CFURLRef UntranslocateBundlePath(const CFURLRef bundle_path) { return nullptr; } -static std::filesystem::path GetBundleParentDirectory() { +static std::optional GetBundleParentDirectory() { if (CFBundleRef bundle_ref = CFBundleGetMainBundle()) { if (CFURLRef bundle_url_ref = CFBundleCopyBundleURL(bundle_ref)) { SCOPE_EXIT { @@ -83,14 +83,16 @@ static std::filesystem::path GetBundleParentDirectory() { } } } - return std::filesystem::current_path(); + return std::nullopt; } #endif static auto UserPaths = [] { -#ifdef __APPLE__ +#if defined(__APPLE__) && defined(ENABLE_QT_GUI) // Set the current path to the directory containing the app bundle. - std::filesystem::current_path(GetBundleParentDirectory()); + if (const auto bundle_dir = GetBundleParentDirectory()) { + std::filesystem::current_path(*bundle_dir); + } #endif // Try the portable user directory first. diff --git a/src/core/linker.cpp b/src/core/linker.cpp index 69deb464f..0f86376af 100644 --- a/src/core/linker.cpp +++ b/src/core/linker.cpp @@ -112,18 +112,6 @@ void Linker::Execute(const std::vector args) { 0, "SceKernelInternalMemory"); ASSERT_MSG(ret == 0, "Unable to perform sceKernelInternalMemory mapping"); - // Simulate libSceGnmDriver initialization, which maps a chunk of direct memory. - // Some games fail without accurately emulating this behavior. - s64 phys_addr{}; - ret = Libraries::Kernel::sceKernelAllocateDirectMemory( - 0, Libraries::Kernel::sceKernelGetDirectMemorySize(), 0x10000, 0x10000, 3, &phys_addr); - if (ret == 0) { - void* addr{reinterpret_cast(0xfe0000000)}; - ret = Libraries::Kernel::sceKernelMapNamedDirectMemory(&addr, 0x10000, 0x13, 0, phys_addr, - 0x10000, "SceGnmDriver"); - } - ASSERT_MSG(ret == 0, "Unable to emulate libSceGnmDriver initialization"); - main_thread.Run([this, module, args](std::stop_token) { Common::SetCurrentThreadName("GAME_MainThread"); LoadSharedLibraries(); diff --git a/src/qt_gui/kbm_gui.cpp b/src/qt_gui/kbm_gui.cpp index 2e1f6ddce..15e9008ab 100644 --- a/src/qt_gui/kbm_gui.cpp +++ b/src/qt_gui/kbm_gui.cpp @@ -608,21 +608,28 @@ void KBMSettings::CheckMapping(QPushButton*& button) { MappingTimer -= 1; button->setText(tr("Press a key") + " [" + QString::number(MappingTimer) + "]"); + if (pressedKeys.size() > 0) { + QStringList keyStrings; + + for (const QString& buttonAction : pressedKeys) { + keyStrings << buttonAction; + } + + QString combo = keyStrings.join(","); + SetMapping(combo); + MappingCompleted = true; + EnableMapping = false; + + MappingButton->setText(combo); + pressedKeys.clear(); + timer->stop(); + } if (MappingCompleted) { EnableMapping = false; EnableMappingButtons(); timer->stop(); - if (mapping == "lshift" || mapping == "lalt" || mapping == "lctrl" || mapping == "lmeta" || - mapping == "lwin") { - modifier = ""; - } - - if (modifier != "") { - button->setText(modifier + ", " + mapping); - } else { - button->setText(mapping); - } + button->setText(mapping); } if (MappingTimer <= 0) { @@ -647,322 +654,346 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) { } if (EnableMapping) { - if (Qt::ShiftModifier & QApplication::keyboardModifiers()) { - modifier = "lshift"; - } else if (Qt::AltModifier & QApplication::keyboardModifiers()) { - modifier = "lalt"; - } else if (Qt::ControlModifier & QApplication::keyboardModifiers()) { - modifier = "lctrl"; - } else if (Qt::MetaModifier & QApplication::keyboardModifiers()) { -#ifdef _WIN32 - modifier = "lwin"; -#else - modifier = "lmeta"; -#endif - } - if (event->type() == QEvent::KeyPress) { QKeyEvent* keyEvent = static_cast(event); + if (keyEvent->isAutoRepeat()) + return true; + + if (pressedKeys.size() >= 3) { + return true; + } + switch (keyEvent->key()) { case Qt::Key_Space: - SetMapping("space"); + pressedKeys.insert("space"); break; case Qt::Key_Comma: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kpcomma"); + pressedKeys.insert("kpcomma"); } else { - SetMapping("comma"); + pressedKeys.insert("comma"); } break; case Qt::Key_Period: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kpperiod"); + pressedKeys.insert("kpperiod"); } else { - SetMapping("period"); + pressedKeys.insert("period"); } break; case Qt::Key_Slash: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) - SetMapping("kpdivide"); + pressedKeys.insert("kpdivide"); break; case Qt::Key_Asterisk: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) - SetMapping("kpmultiply"); + pressedKeys.insert("kpmultiply"); break; case Qt::Key_Question: - SetMapping("question"); + pressedKeys.insert("question"); break; case Qt::Key_Semicolon: - SetMapping("semicolon"); + pressedKeys.insert("semicolon"); break; case Qt::Key_Minus: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kpminus"); + pressedKeys.insert("kpminus"); } else { - SetMapping("minus"); + pressedKeys.insert("minus"); } break; case Qt::Key_Plus: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kpplus"); + pressedKeys.insert("kpplus"); } else { - SetMapping("plus"); + pressedKeys.insert("plus"); } break; case Qt::Key_ParenLeft: - SetMapping("lparenthesis"); + pressedKeys.insert("lparenthesis"); break; case Qt::Key_ParenRight: - SetMapping("rparenthesis"); + pressedKeys.insert("rparenthesis"); break; case Qt::Key_BracketLeft: - SetMapping("lbracket"); + pressedKeys.insert("lbracket"); break; case Qt::Key_BracketRight: - SetMapping("rbracket"); + pressedKeys.insert("rbracket"); break; case Qt::Key_BraceLeft: - SetMapping("lbrace"); + pressedKeys.insert("lbrace"); break; case Qt::Key_BraceRight: - SetMapping("rbrace"); + pressedKeys.insert("rbrace"); break; case Qt::Key_Backslash: - SetMapping("backslash"); + pressedKeys.insert("backslash"); break; case Qt::Key_Tab: - SetMapping("tab"); + pressedKeys.insert("tab"); break; case Qt::Key_Backspace: - SetMapping("backspace"); + pressedKeys.insert("backspace"); break; case Qt::Key_Return: - SetMapping("enter"); + pressedKeys.insert("enter"); break; case Qt::Key_Enter: - SetMapping("kpenter"); + pressedKeys.insert("kpenter"); + break; + case Qt::Key_Home: + pressedKeys.insert("home"); + break; + case Qt::Key_End: + pressedKeys.insert("end"); + break; + case Qt::Key_PageDown: + pressedKeys.insert("pgdown"); + break; + case Qt::Key_PageUp: + pressedKeys.insert("pgup"); + break; + case Qt::Key_CapsLock: + pressedKeys.insert("capslock"); break; case Qt::Key_Escape: - SetMapping("unmapped"); + pressedKeys.insert("unmapped"); break; case Qt::Key_Shift: - SetMapping("lshift"); + if (keyEvent->nativeScanCode() == rshift) { + pressedKeys.insert("rshift"); + } else { + pressedKeys.insert("lshift"); + } break; case Qt::Key_Alt: - SetMapping("lalt"); + if (keyEvent->nativeScanCode() == ralt) { + pressedKeys.insert("ralt"); + } else { + pressedKeys.insert("lalt"); + } break; case Qt::Key_Control: - SetMapping("lctrl"); + if (keyEvent->nativeScanCode() == rctrl) { + pressedKeys.insert("rctrl"); + } else { + pressedKeys.insert("lctrl"); + } break; case Qt::Key_Meta: activateWindow(); #ifdef _WIN32 - SetMapping("lwin"); + pressedKeys.insert("lwin"); #else - SetMapping("lmeta"); + pressedKeys.insert("lmeta"); #endif case Qt::Key_1: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp1"); + pressedKeys.insert("kp1"); } else { - SetMapping("1"); + pressedKeys.insert("1"); } break; case Qt::Key_2: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp2"); + pressedKeys.insert("kp2"); } else { - SetMapping("2"); + pressedKeys.insert("2"); } break; case Qt::Key_3: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp3"); + pressedKeys.insert("kp3"); } else { - SetMapping("3"); + pressedKeys.insert("3"); } break; case Qt::Key_4: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp4"); + pressedKeys.insert("kp4"); } else { - SetMapping("4"); + pressedKeys.insert("4"); } break; case Qt::Key_5: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp5"); + pressedKeys.insert("kp5"); } else { - SetMapping("5"); + pressedKeys.insert("5"); } break; case Qt::Key_6: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp6"); + pressedKeys.insert("kp6"); } else { - SetMapping("6"); + pressedKeys.insert("6"); } break; case Qt::Key_7: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp7"); + pressedKeys.insert("kp7"); } else { - SetMapping("7"); + pressedKeys.insert("7"); } break; case Qt::Key_8: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp8"); + pressedKeys.insert("kp8"); } else { - SetMapping("8"); + pressedKeys.insert("8"); } break; case Qt::Key_9: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp9"); + pressedKeys.insert("kp9"); } else { - SetMapping("9"); + pressedKeys.insert("9"); } break; case Qt::Key_0: if (Qt::KeypadModifier & QApplication::keyboardModifiers()) { - SetMapping("kp0"); + pressedKeys.insert("kp0"); } else { - SetMapping("0"); + pressedKeys.insert("0"); } break; case Qt::Key_Up: activateWindow(); - SetMapping("up"); + pressedKeys.insert("up"); break; case Qt::Key_Down: - SetMapping("down"); + pressedKeys.insert("down"); break; case Qt::Key_Left: - SetMapping("left"); + pressedKeys.insert("left"); break; case Qt::Key_Right: - SetMapping("right"); + pressedKeys.insert("right"); break; case Qt::Key_A: - SetMapping("a"); + pressedKeys.insert("a"); break; case Qt::Key_B: - SetMapping("b"); + pressedKeys.insert("b"); break; case Qt::Key_C: - SetMapping("c"); + pressedKeys.insert("c"); break; case Qt::Key_D: - SetMapping("d"); + pressedKeys.insert("d"); break; case Qt::Key_E: - SetMapping("e"); + pressedKeys.insert("e"); break; case Qt::Key_F: - SetMapping("f"); + pressedKeys.insert("f"); break; case Qt::Key_G: - SetMapping("g"); + pressedKeys.insert("g"); break; case Qt::Key_H: - SetMapping("h"); + pressedKeys.insert("h"); break; case Qt::Key_I: - SetMapping("i"); + pressedKeys.insert("i"); break; case Qt::Key_J: - SetMapping("j"); + pressedKeys.insert("j"); break; case Qt::Key_K: - SetMapping("k"); + pressedKeys.insert("k"); break; case Qt::Key_L: - SetMapping("l"); + pressedKeys.insert("l"); break; case Qt::Key_M: - SetMapping("m"); + pressedKeys.insert("m"); break; case Qt::Key_N: - SetMapping("n"); + pressedKeys.insert("n"); break; case Qt::Key_O: - SetMapping("o"); + pressedKeys.insert("o"); break; case Qt::Key_P: - SetMapping("p"); + pressedKeys.insert("p"); break; case Qt::Key_Q: - SetMapping("q"); + pressedKeys.insert("q"); break; case Qt::Key_R: - SetMapping("r"); + pressedKeys.insert("r"); break; case Qt::Key_S: - SetMapping("s"); + pressedKeys.insert("s"); break; case Qt::Key_T: - SetMapping("t"); + pressedKeys.insert("t"); break; case Qt::Key_U: - SetMapping("u"); + pressedKeys.insert("u"); break; case Qt::Key_V: - SetMapping("v"); + pressedKeys.insert("v"); break; case Qt::Key_W: - SetMapping("w"); + pressedKeys.insert("w"); break; case Qt::Key_X: - SetMapping("x"); + pressedKeys.insert("x"); break; case Qt::Key_Y: - SetMapping("Y"); + pressedKeys.insert("Y"); break; case Qt::Key_Z: - SetMapping("z"); + pressedKeys.insert("z"); break; default: break; } return true; } + } - if (event->type() == QEvent::MouseButtonPress) { - QMouseEvent* mouseEvent = static_cast(event); + if (event->type() == QEvent::MouseButtonPress) { + QMouseEvent* mouseEvent = static_cast(event); + if (pressedKeys.size() < 3) { switch (mouseEvent->button()) { case Qt::LeftButton: - SetMapping("leftbutton"); + pressedKeys.insert("leftbutton"); break; case Qt::RightButton: - SetMapping("rightbutton"); + pressedKeys.insert("rightbutton"); break; case Qt::MiddleButton: - SetMapping("middlebutton"); + pressedKeys.insert("middlebutton"); break; default: break; } return true; } + } - const QList AxisList = { - ui->LStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->LStickRightButton, - ui->RStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->RStickRightButton}; + const QList AxisList = { + ui->LStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->LStickRightButton, + ui->RStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->RStickRightButton}; - if (event->type() == QEvent::Wheel) { - QWheelEvent* wheelEvent = static_cast(event); + if (event->type() == QEvent::Wheel) { + QWheelEvent* wheelEvent = static_cast(event); + if (pressedKeys.size() < 3) { if (wheelEvent->angleDelta().y() > 5) { if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) { - SetMapping("mousewheelup"); + pressedKeys.insert("mousewheelup"); } else { QMessageBox::information(this, tr("Cannot set mapping"), tr("Mousewheel cannot be mapped to stick outputs")); } } else if (wheelEvent->angleDelta().y() < -5) { if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) { - SetMapping("mousewheeldown"); + pressedKeys.insert("mousewheeldown"); } else { QMessageBox::information(this, tr("Cannot set mapping"), tr("Mousewheel cannot be mapped to stick outputs")); @@ -972,9 +1003,9 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) { if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) { // QT changes scrolling to horizontal for all widgets with the alt modifier if (Qt::AltModifier & QApplication::keyboardModifiers()) { - SetMapping("mousewheelup"); + pressedKeys.insert("mousewheelup"); } else { - SetMapping("mousewheelright"); + pressedKeys.insert("mousewheelright"); } } else { QMessageBox::information(this, tr("Cannot set mapping"), @@ -983,18 +1014,18 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) { } else if (wheelEvent->angleDelta().x() < -5) { if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) { if (Qt::AltModifier & QApplication::keyboardModifiers()) { - SetMapping("mousewheeldown"); + pressedKeys.insert("mousewheeldown"); } else { - SetMapping("mousewheelleft"); + pressedKeys.insert("mousewheelleft"); } } else { QMessageBox::information(this, tr("Cannot set mapping"), tr("Mousewheel cannot be mapped to stick outputs")); } } - return true; } } + return QDialog::eventFilter(obj, event); } diff --git a/src/qt_gui/kbm_gui.h b/src/qt_gui/kbm_gui.h index 06e58eef6..bfeed2b01 100644 --- a/src/qt_gui/kbm_gui.h +++ b/src/qt_gui/kbm_gui.h @@ -25,6 +25,22 @@ private: std::unique_ptr ui; std::shared_ptr m_game_info; +#ifdef _WIN32 + const int lctrl = 29; + const int rctrl = 57373; + const int lalt = 56; + const int ralt = 57400; + const int lshift = 42; + const int rshift = 54; +#else + const int lctrl = 37; + const int rctrl = 105; + const int lalt = 64; + const int ralt = 108; + const int lshift = 50; + const int rshift = 62; +#endif + bool eventFilter(QObject* obj, QEvent* event) override; void ButtonConnects(); void SetUIValuestoMappings(std::string config_id); @@ -33,6 +49,7 @@ private: void EnableMappingButtons(); void SetMapping(QString input); + QSet pressedKeys; bool EnableMapping = false; bool MappingCompleted = false; bool HelpWindowOpen = false; diff --git a/src/qt_gui/main_window_ui.h b/src/qt_gui/main_window_ui.h index 2c4d4480b..4d3481c07 100644 --- a/src/qt_gui/main_window_ui.h +++ b/src/qt_gui/main_window_ui.h @@ -106,8 +106,6 @@ public: toggleLabelsAct = new QAction(MainWindow); toggleLabelsAct->setObjectName("toggleLabelsAct"); - toggleLabelsAct->setText( - QCoreApplication::translate("MainWindow", "Show Labels Under Icons")); toggleLabelsAct->setCheckable(true); toggleLabelsAct->setChecked(Config::getShowLabelsUnderIcons()); @@ -413,6 +411,8 @@ public: setThemeTokyoNight->setText("Tokyo Night"); setThemeOled->setText("OLED"); toolBar->setWindowTitle(QCoreApplication::translate("MainWindow", "toolBar", nullptr)); + toggleLabelsAct->setText( + QCoreApplication::translate("MainWindow", "Show Labels Under Icons")); } // retranslateUi }; diff --git a/src/qt_gui/translations/ar_SA.ts b/src/qt_gui/translations/ar_SA.ts index 7ef3c6171..e434b3259 100644 --- a/src/qt_gui/translations/ar_SA.ts +++ b/src/qt_gui/translations/ar_SA.ts @@ -66,7 +66,7 @@ You can delete the cheats you don't want after downloading them. - يمكنك حذف الشفرات التي لا تريدها بعد تنزيلها. + يمكنك حذف الشفرات التي لا 'تريدها بعد تنزيلها. Do you want to delete the selected file?\n%1 @@ -74,11 +74,11 @@ Select Patch File: - إختر ملف الباتش: + اختر مِلَف التصحيح: Download Patches - تحميل الباتشات + تحميل ملفات التصحيح Save @@ -98,15 +98,15 @@ No patch selected. - لم يتم اختيار أي تصحيح. + لم يتم تحديد أي مِلَف تصحيح. Unable to open files.json for reading. - تعذر فتح files.json للقراءة. + تعذّر فتح مِلَف files.json للقراءة. No patch file found for the current serial. - لم يتم العثور على مِلَفّ باتش للسيريال الحالي. + لم يتم العثور على مِلَف تصحيح للسيريال الحالي. Unable to open the file for reading. @@ -126,11 +126,11 @@ Options saved successfully. - تم حفظ الخيارات بنجاح. + تم حفظ الإعدادات. Invalid Source - مصدر غير صالح + المصدر غير صالح The selected source is invalid. @@ -138,11 +138,11 @@ File Exists - الملف موجود + المِلَف موجود مسبقًا File already exists. Do you want to replace it? - يوجد ملف بنفس الاسم. هل ترغب في استبداله؟ + المِلَف موجود مسبقًا. هل ترغب في استبداله؟ Failed to save file: @@ -158,7 +158,7 @@ No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game. - لم يتم العثور على شفرات لهذه اللعبة في هذه النسخة من المستودع المحدد. حاول استخدام مستودع آخر أو نسخة مختلفة من اللعبة. + لم يتم العثور على شفرات لهذه اللعبة في هذا الإصدار من المستودع المحدد. جرّب مستودعًا آخر أو إصدارًا مختلفًا من اللعبة. Cheats Downloaded Successfully @@ -182,7 +182,7 @@ Patches Downloaded Successfully! All Patches available for all games have been downloaded, there is no need to download them individually for each game as happens in Cheats. If the patch does not appear, it may be that it does not exist for the specific serial and version of the game. - تم تنزيل التصحيحات بنجاح! تم تنزيل جميع التصحيحات لجميع الألعاب، ولا داعي لتنزيلها بشكل فردي لكل لعبة كما هو الحال مع الغش. إذا لم يظهر التحديث، قد يكون السبب أنه غير متوفر للإصدار وسيريال اللعبة المحدد. + تم تنزيل التصحيحات بنجاح! تم تنزيل جميع التصحيحات المتوفرة لجميع الألعاب، ولا حاجة إلى تنزيلها بشكل فردي لكل لعبة كما هو الحال مع الشفرات. إذا لم يظهر التصحيح، فقد لا يكون متوفرًا للسيريال أو الإصدار المحدد من اللعبة. Failed to parse JSON data from HTML. @@ -190,15 +190,15 @@ Failed to retrieve HTML page. - .HTML فشل في استرجاع صفحة + فشل في جلب صفحة HTML. The game is in version: %1 - النسخة الحالية للعبة هي: %1 + إصدار اللعبة الحالي: %1 The downloaded patch only works on version: %1 - الباتش الذي تم تنزيله يعمل فقط على الإصدار: %1 + التصحيح الذي تم تنزيله يعمل فقط مع الإصدار:%1 You may need to update your game. @@ -206,7 +206,7 @@ Incompatibility Notice - إشعار عدم التوافق + إشعار بعدم التوافق Failed to open file: @@ -238,7 +238,7 @@ Can't apply cheats before the game is started - لا يمكن تطبيق الغش قبل بدء اللعبة. + لا 'يمكن تطبيق الشفرات قبل بَدْء اللعبة Close @@ -249,7 +249,7 @@ CheckUpdate Auto Updater - محدث تلقائي + التحديثات التلقائية Error @@ -261,7 +261,7 @@ The Auto Updater allows up to 60 update checks per hour.\nYou have reached this limit. Please try again later. - يتيح التحديث التلقائي ما يصل إلى 60 عملية تحقق من التحديث في الساعة.\nلقد وصلت إلى هذا الحد. الرجاء المحاولة مرة أخرى لاحقًا. + تسمح التحديثات التلقائية بـ 60 عملية تحقق من التحديث في الساعة.\nلقد وصلت إلى الحد المسموح به. الرجاء المحاولة لاحقًا. Failed to parse update information. diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp index 036df24d8..936f82cd6 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp @@ -335,8 +335,7 @@ void DefineEntryPoint(const Info& info, EmitContext& ctx, Id main) { ctx.AddExecutionMode(main, spv::ExecutionMode::OriginUpperLeft); } if (info.has_discard) { - ctx.AddExtension("SPV_EXT_demote_to_helper_invocation"); - ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT); + ctx.AddCapability(spv::Capability::DemoteToHelperInvocation); } if (info.stores.GetAny(IR::Attribute::Depth)) { ctx.AddExecutionMode(main, spv::ExecutionMode::DepthReplacing); diff --git a/src/shader_recompiler/frontend/control_flow_graph.cpp b/src/shader_recompiler/frontend/control_flow_graph.cpp index cf1882b8c..b53db9e94 100644 --- a/src/shader_recompiler/frontend/control_flow_graph.cpp +++ b/src/shader_recompiler/frontend/control_flow_graph.cpp @@ -4,6 +4,7 @@ #include #include #include "common/assert.h" +#include "common/logging/log.h" #include "shader_recompiler/frontend/control_flow_graph.h" namespace Shader::Gcn { @@ -67,6 +68,39 @@ static bool IgnoresExecMask(const GcnInst& inst) { return false; } +static std::optional ResolveSetPcTarget(std::span list, u32 setpc_index, + std::span pc_map) { + if (setpc_index < 3) { + return std::nullopt; + } + + const auto& getpc = list[setpc_index - 3]; + const auto& arith = list[setpc_index - 2]; + const auto& setpc = list[setpc_index]; + + if (getpc.opcode != Opcode::S_GETPC_B64 || + !(arith.opcode == Opcode::S_ADD_U32 || arith.opcode == Opcode::S_SUB_U32) || + setpc.opcode != Opcode::S_SETPC_B64) + return std::nullopt; + + if (getpc.dst[0].code != setpc.src[0].code || arith.dst[0].code != setpc.src[0].code) + return std::nullopt; + + if (arith.src_count < 2 || arith.src[1].field != OperandField::LiteralConst) + return std::nullopt; + + const u32 imm = arith.src[1].code; + + const s32 signed_offset = + (arith.opcode == Opcode::S_ADD_U32) ? static_cast(imm) : -static_cast(imm); + + const u32 base_pc = pc_map[setpc_index - 3] + getpc.length; + + const u32 result_pc = static_cast(static_cast(base_pc) + signed_offset); + LOG_DEBUG(Render_Recompiler, "SetPC target: {} + {} = {}", base_pc, signed_offset, result_pc); + return result_pc & ~0x3u; +} + static constexpr size_t LabelReserveSize = 32; CFG::CFG(Common::ObjectPool& block_pool_, std::span inst_list_) @@ -89,9 +123,20 @@ void CFG::EmitLabels() { index_to_pc[i] = pc; const GcnInst inst = inst_list[i]; if (inst.IsUnconditionalBranch()) { - const u32 target = inst.BranchTarget(pc); + u32 target = inst.BranchTarget(pc); + if (inst.opcode == Opcode::S_SETPC_B64) { + if (auto t = ResolveSetPcTarget(inst_list, i, index_to_pc)) { + target = *t; + } else { + ASSERT_MSG( + false, + "S_SETPC_B64 without a resolvable offset at PC {:#x} (Index {}): Involved " + "instructions not recognized or invalid pattern", + pc, i); + } + } AddLabel(target); - // Emit this label so that the block ends with s_branch instruction + // Emit this label so that the block ends with the branching instruction AddLabel(pc + inst.length); } else if (inst.IsConditionalBranch()) { const u32 true_label = inst.BranchTarget(pc); @@ -102,6 +147,7 @@ void CFG::EmitLabels() { const u32 next_label = pc + inst.length; AddLabel(next_label); } + pc += inst.length; } index_to_pc[inst_list.size()] = pc; @@ -280,7 +326,18 @@ void CFG::LinkBlocks() { // Find the branch targets from the instruction and link the blocks. // Note: Block end address is one instruction after end_inst. const u32 branch_pc = block.end - end_inst.length; - const u32 target_pc = end_inst.BranchTarget(branch_pc); + u32 target_pc = 0; + if (end_inst.opcode == Opcode::S_SETPC_B64) { + auto tgt = ResolveSetPcTarget(inst_list, block.end_index, index_to_pc); + ASSERT_MSG(tgt, + "S_SETPC_B64 without a resolvable offset at PC {:#x} (Index {}): Involved " + "instructions not recognized or invalid pattern", + branch_pc, block.end_index); + target_pc = *tgt; + } else { + target_pc = end_inst.BranchTarget(branch_pc); + } + if (end_inst.IsUnconditionalBranch()) { auto* target_block = get_block(target_pc); ++target_block->num_predecessors; diff --git a/src/shader_recompiler/frontend/instruction.cpp b/src/shader_recompiler/frontend/instruction.cpp index a0c132053..246c2b85a 100644 --- a/src/shader_recompiler/frontend/instruction.cpp +++ b/src/shader_recompiler/frontend/instruction.cpp @@ -18,7 +18,7 @@ bool GcnInst::IsTerminateInstruction() const { } bool GcnInst::IsUnconditionalBranch() const { - return opcode == Opcode::S_BRANCH; + return opcode == Opcode::S_BRANCH || opcode == Opcode::S_SETPC_B64; } bool GcnInst::IsFork() const { diff --git a/src/shader_recompiler/frontend/translate/scalar_flow.cpp b/src/shader_recompiler/frontend/translate/scalar_flow.cpp index 0e02b77a2..cd1cf51f0 100644 --- a/src/shader_recompiler/frontend/translate/scalar_flow.cpp +++ b/src/shader_recompiler/frontend/translate/scalar_flow.cpp @@ -18,6 +18,7 @@ void Translator::EmitFlowControl(u32 pc, const GcnInst& inst) { return; case Opcode::S_GETPC_B64: return S_GETPC_B64(pc, inst); + case Opcode::S_SETPC_B64: case Opcode::S_WAITCNT: case Opcode::S_NOP: case Opcode::S_ENDPGM: diff --git a/src/video_core/renderer_vulkan/host_passes/pp_pass.cpp b/src/video_core/renderer_vulkan/host_passes/pp_pass.cpp index c854e124f..0c40ffd7a 100644 --- a/src/video_core/renderer_vulkan/host_passes/pp_pass.cpp +++ b/src/video_core/renderer_vulkan/host_passes/pp_pass.cpp @@ -78,7 +78,7 @@ void PostProcessingPass::Create(vk::Device device) { const std::array pp_color_formats{ vk::Format::eB8G8R8A8Unorm, // swapchain.GetSurfaceFormat().format, }; - const vk::PipelineRenderingCreateInfoKHR pipeline_rendering_ci{ + const vk::PipelineRenderingCreateInfo pipeline_rendering_ci{ .colorAttachmentCount = pp_color_formats.size(), .pColorAttachmentFormats = pp_color_formats.data(), }; diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp index 354e22331..7c020a012 100644 --- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp @@ -122,21 +122,21 @@ GraphicsPipeline::GraphicsPipeline( }; boost::container::static_vector dynamic_states = { - vk::DynamicState::eViewportWithCountEXT, vk::DynamicState::eScissorWithCountEXT, - vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnableEXT, - vk::DynamicState::eDepthWriteEnableEXT, vk::DynamicState::eDepthCompareOpEXT, - vk::DynamicState::eDepthBiasEnableEXT, vk::DynamicState::eDepthBias, - vk::DynamicState::eStencilTestEnableEXT, vk::DynamicState::eStencilReference, - vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask, - vk::DynamicState::eStencilOpEXT, vk::DynamicState::eCullModeEXT, - vk::DynamicState::eFrontFaceEXT, + vk::DynamicState::eViewportWithCount, vk::DynamicState::eScissorWithCount, + vk::DynamicState::eBlendConstants, vk::DynamicState::eDepthTestEnable, + vk::DynamicState::eDepthWriteEnable, vk::DynamicState::eDepthCompareOp, + vk::DynamicState::eDepthBiasEnable, vk::DynamicState::eDepthBias, + vk::DynamicState::eStencilTestEnable, vk::DynamicState::eStencilReference, + vk::DynamicState::eStencilCompareMask, vk::DynamicState::eStencilWriteMask, + vk::DynamicState::eStencilOp, vk::DynamicState::eCullMode, + vk::DynamicState::eFrontFace, }; if (instance.IsPrimitiveRestartDisableSupported()) { - dynamic_states.push_back(vk::DynamicState::ePrimitiveRestartEnableEXT); + dynamic_states.push_back(vk::DynamicState::ePrimitiveRestartEnable); } if (instance.IsDepthBoundsSupported()) { - dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnableEXT); + dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnable); dynamic_states.push_back(vk::DynamicState::eDepthBounds); } if (instance.IsDynamicColorWriteMaskSupported()) { @@ -145,7 +145,7 @@ GraphicsPipeline::GraphicsPipeline( if (instance.IsVertexInputDynamicState()) { dynamic_states.push_back(vk::DynamicState::eVertexInputEXT); } else if (!vertex_bindings.empty()) { - dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStrideEXT); + dynamic_states.push_back(vk::DynamicState::eVertexInputBindingStride); } const vk::PipelineDynamicStateCreateInfo dynamic_info = { @@ -212,7 +212,7 @@ GraphicsPipeline::GraphicsPipeline( }); } - const vk::PipelineRenderingCreateInfoKHR pipeline_rendering_ci = { + const vk::PipelineRenderingCreateInfo pipeline_rendering_ci = { .colorAttachmentCount = key.num_color_attachments, .pColorAttachmentFormats = key.color_formats.data(), .depthAttachmentFormat = key.depth_format, diff --git a/src/video_core/renderer_vulkan/vk_instance.cpp b/src/video_core/renderer_vulkan/vk_instance.cpp index 0df020116..089c0f00d 100644 --- a/src/video_core/renderer_vulkan/vk_instance.cpp +++ b/src/video_core/renderer_vulkan/vk_instance.cpp @@ -203,12 +203,14 @@ std::string Instance::GetDriverVersionName() { } bool Instance::CreateDevice() { - const vk::StructureChain feature_chain = physical_device.getFeatures2< - vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan11Features, - vk::PhysicalDeviceVulkan12Features, vk::PhysicalDeviceRobustness2FeaturesEXT, - vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT, - vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT, - vk::PhysicalDevicePortabilitySubsetFeaturesKHR>(); + const vk::StructureChain feature_chain = + physical_device + .getFeatures2(); features = feature_chain.get().features; const vk::StructureChain properties_chain = physical_device.getProperties2< @@ -240,18 +242,6 @@ bool Instance::CreateDevice() { return false; }; - // These extensions are promoted by Vulkan 1.3, but for greater compatibility we use Vulkan 1.2 - // with extensions. - ASSERT(add_extension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME)); - ASSERT(add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME)); - ASSERT(add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME)); - ASSERT(add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME)); - ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME)); - ASSERT(add_extension(VK_EXT_EXTENDED_DYNAMIC_STATE_2_EXTENSION_NAME)); - ASSERT(add_extension(VK_EXT_TOOLING_INFO_EXTENSION_NAME) || - driver_id == vk::DriverId::eIntelProprietaryWindows); - ASSERT(add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME)); - // Required ASSERT(add_extension(VK_KHR_SWAPCHAIN_EXTENSION_NAME)); ASSERT(add_extension(VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME)); @@ -324,6 +314,7 @@ bool Instance::CreateDevice() { feature_chain.get(); const auto vk11_features = feature_chain.get(); const auto vk12_features = feature_chain.get(); + const auto vk13_features = feature_chain.get(); vk::StructureChain device_chain = { vk::DeviceCreateInfo{ .queueCreateInfoCount = 1u, @@ -372,26 +363,14 @@ bool Instance::CreateDevice() { .hostQueryReset = vk12_features.hostQueryReset, .timelineSemaphore = vk12_features.timelineSemaphore, }, - // Vulkan 1.3 promoted extensions - vk::PhysicalDeviceDynamicRenderingFeaturesKHR{ - .dynamicRendering = true, + vk::PhysicalDeviceVulkan13Features{ + .robustImageAccess = vk13_features.robustImageAccess, + .shaderDemoteToHelperInvocation = vk13_features.shaderDemoteToHelperInvocation, + .synchronization2 = vk13_features.synchronization2, + .dynamicRendering = vk13_features.dynamicRendering, + .maintenance4 = vk13_features.maintenance4, }, - vk::PhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT{ - .shaderDemoteToHelperInvocation = true, - }, - vk::PhysicalDeviceSynchronization2Features{ - .synchronization2 = true, - }, - vk::PhysicalDeviceExtendedDynamicStateFeaturesEXT{ - .extendedDynamicState = true, - }, - vk::PhysicalDeviceExtendedDynamicState2FeaturesEXT{ - .extendedDynamicState2 = true, - }, - vk::PhysicalDeviceMaintenance4FeaturesKHR{ - .maintenance4 = true, - }, - // Other extensions + // Extensions vk::PhysicalDeviceCustomBorderColorFeaturesEXT{ .customBorderColors = true, .customBorderColorWithoutFormat = true, @@ -547,7 +526,7 @@ void Instance::CollectToolingInfo() { // Currently causes issues with Reshade on AMD proprietary, disabled until fix released. return; } - const auto [tools_result, tools] = physical_device.getToolPropertiesEXT(); + const auto [tools_result, tools] = physical_device.getToolProperties(); if (tools_result != vk::Result::eSuccess) { LOG_ERROR(Render_Vulkan, "Could not get Vulkan tool properties: {}", vk::to_string(tools_result)); diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index bad2a549c..efb1966ba 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp @@ -26,6 +26,8 @@ using Shader::LogicalStage; using Shader::Stage; using Shader::VsOutput; +constexpr static auto SpirvVersion1_6 = 0x00010600U; + constexpr static std::array DescriptorHeapSizes = { vk::DescriptorPoolSize{vk::DescriptorType::eUniformBuffer, 8192}, vk::DescriptorPoolSize{vk::DescriptorType::eStorageBuffer, 1024}, @@ -192,7 +194,7 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_, desc_heap{instance, scheduler.GetMasterSemaphore(), DescriptorHeapSizes} { const auto& vk12_props = instance.GetVk12Properties(); profile = Shader::Profile{ - .supported_spirv = instance.ApiVersion() >= VK_API_VERSION_1_3 ? 0x00010600U : 0x00010500U, + .supported_spirv = SpirvVersion1_6, .subgroup_size = instance.SubgroupSize(), .support_fp32_denorm_preserve = bool(vk12_props.shaderDenormPreserveFloat32), .support_fp32_denorm_flush = bool(vk12_props.shaderDenormFlushToZeroFloat32), diff --git a/src/video_core/renderer_vulkan/vk_platform.cpp b/src/video_core/renderer_vulkan/vk_platform.cpp index e656369b2..c49e62f4e 100644 --- a/src/video_core/renderer_vulkan/vk_platform.cpp +++ b/src/video_core/renderer_vulkan/vk_platform.cpp @@ -22,6 +22,10 @@ #include "sdl_window.h" #include "video_core/renderer_vulkan/vk_platform.h" +#ifdef __APPLE__ +#include +#endif + namespace Vulkan { static const char* const VALIDATION_LAYER_NAME = "VK_LAYER_KHRONOS_validation"; @@ -223,8 +227,19 @@ vk::UniqueInstance CreateInstance(Frontend::WindowSystemType window_type, bool e LOG_INFO(Render_Vulkan, "Creating vulkan instance"); #ifdef __APPLE__ +#ifndef ENABLE_QT_GUI + // Initialize the environment with the path to the MoltenVK ICD, so that the loader will + // find it. + static const auto icd_path = [] { + char path[PATH_MAX]; + u32 length = PATH_MAX; + _NSGetExecutablePath(path, &length); + return std::filesystem::path(path).parent_path() / "MoltenVK_icd.json"; + }(); + setenv("VK_DRIVER_FILES", icd_path.c_str(), true); +#endif // If the Vulkan loader exists in /usr/local/lib, give it priority. The Vulkan SDK - // installs it here by default but it is not in the default library search path. + // installs it here by default, but it is not in the default library search path. // The loader has a clause to check for it, but at a lower priority than the bundled // libMoltenVK.dylib, so we need to handle it ourselves to give it priority. static const std::string usr_local_path = "/usr/local/lib/libvulkan.dylib"; diff --git a/src/video_core/renderer_vulkan/vk_platform.h b/src/video_core/renderer_vulkan/vk_platform.h index 6a6ebeb15..b8f5f9f11 100644 --- a/src/video_core/renderer_vulkan/vk_platform.h +++ b/src/video_core/renderer_vulkan/vk_platform.h @@ -18,7 +18,7 @@ class WindowSDL; namespace Vulkan { -constexpr u32 TargetVulkanApiVersion = VK_API_VERSION_1_2; +constexpr u32 TargetVulkanApiVersion = VK_API_VERSION_1_3; vk::SurfaceKHR CreateSurface(vk::Instance instance, const Frontend::WindowSDL& emu_window); diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index a48d93dee..8d4188a22 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -170,29 +170,29 @@ void Scheduler::SubmitExecution(SubmitInfo& info) { void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmdbuf) { if (dirty_state.viewports) { dirty_state.viewports = false; - cmdbuf.setViewportWithCountEXT(viewports); + cmdbuf.setViewportWithCount(viewports); } if (dirty_state.scissors) { dirty_state.scissors = false; - cmdbuf.setScissorWithCountEXT(scissors); + cmdbuf.setScissorWithCount(scissors); } if (dirty_state.depth_test_enabled) { dirty_state.depth_test_enabled = false; - cmdbuf.setDepthTestEnableEXT(depth_test_enabled); + cmdbuf.setDepthTestEnable(depth_test_enabled); } if (dirty_state.depth_write_enabled) { dirty_state.depth_write_enabled = false; // Note that this must be set in a command buffer even if depth test is disabled. - cmdbuf.setDepthWriteEnableEXT(depth_write_enabled); + cmdbuf.setDepthWriteEnable(depth_write_enabled); } if (depth_test_enabled && dirty_state.depth_compare_op) { dirty_state.depth_compare_op = false; - cmdbuf.setDepthCompareOpEXT(depth_compare_op); + cmdbuf.setDepthCompareOp(depth_compare_op); } if (dirty_state.depth_bounds_test_enabled) { dirty_state.depth_bounds_test_enabled = false; if (instance.IsDepthBoundsSupported()) { - cmdbuf.setDepthBoundsTestEnableEXT(depth_bounds_test_enabled); + cmdbuf.setDepthBoundsTestEnable(depth_bounds_test_enabled); } } if (depth_bounds_test_enabled && dirty_state.depth_bounds) { @@ -203,7 +203,7 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd } if (dirty_state.depth_bias_enabled) { dirty_state.depth_bias_enabled = false; - cmdbuf.setDepthBiasEnableEXT(depth_bias_enabled); + cmdbuf.setDepthBiasEnable(depth_bias_enabled); } if (depth_bias_enabled && dirty_state.depth_bias) { dirty_state.depth_bias = false; @@ -211,28 +211,28 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd } if (dirty_state.stencil_test_enabled) { dirty_state.stencil_test_enabled = false; - cmdbuf.setStencilTestEnableEXT(stencil_test_enabled); + cmdbuf.setStencilTestEnable(stencil_test_enabled); } if (stencil_test_enabled) { if (dirty_state.stencil_front_ops && dirty_state.stencil_back_ops && stencil_front_ops == stencil_back_ops) { dirty_state.stencil_front_ops = false; dirty_state.stencil_back_ops = false; - cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFrontAndBack, - stencil_front_ops.fail_op, stencil_front_ops.pass_op, - stencil_front_ops.depth_fail_op, stencil_front_ops.compare_op); + cmdbuf.setStencilOp(vk::StencilFaceFlagBits::eFrontAndBack, stencil_front_ops.fail_op, + stencil_front_ops.pass_op, stencil_front_ops.depth_fail_op, + stencil_front_ops.compare_op); } else { if (dirty_state.stencil_front_ops) { dirty_state.stencil_front_ops = false; - cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFront, stencil_front_ops.fail_op, - stencil_front_ops.pass_op, stencil_front_ops.depth_fail_op, - stencil_front_ops.compare_op); + cmdbuf.setStencilOp(vk::StencilFaceFlagBits::eFront, stencil_front_ops.fail_op, + stencil_front_ops.pass_op, stencil_front_ops.depth_fail_op, + stencil_front_ops.compare_op); } if (dirty_state.stencil_back_ops) { dirty_state.stencil_back_ops = false; - cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eBack, stencil_back_ops.fail_op, - stencil_back_ops.pass_op, stencil_back_ops.depth_fail_op, - stencil_back_ops.compare_op); + cmdbuf.setStencilOp(vk::StencilFaceFlagBits::eBack, stencil_back_ops.fail_op, + stencil_back_ops.pass_op, stencil_back_ops.depth_fail_op, + stencil_back_ops.compare_op); } } if (dirty_state.stencil_front_reference && dirty_state.stencil_back_reference && @@ -291,16 +291,16 @@ void DynamicState::Commit(const Instance& instance, const vk::CommandBuffer& cmd if (dirty_state.primitive_restart_enable) { dirty_state.primitive_restart_enable = false; if (instance.IsPrimitiveRestartDisableSupported()) { - cmdbuf.setPrimitiveRestartEnableEXT(primitive_restart_enable); + cmdbuf.setPrimitiveRestartEnable(primitive_restart_enable); } } if (dirty_state.cull_mode) { dirty_state.cull_mode = false; - cmdbuf.setCullModeEXT(cull_mode); + cmdbuf.setCullMode(cull_mode); } if (dirty_state.front_face) { dirty_state.front_face = false; - cmdbuf.setFrontFaceEXT(front_face); + cmdbuf.setFrontFace(front_face); } if (dirty_state.blend_constants) { dirty_state.blend_constants = false; diff --git a/src/video_core/texture_cache/texture_cache.cpp b/src/video_core/texture_cache/texture_cache.cpp index d41ee57cc..047bb3dfe 100644 --- a/src/video_core/texture_cache/texture_cache.cpp +++ b/src/video_core/texture_cache/texture_cache.cpp @@ -319,15 +319,14 @@ ImageId TextureCache::FindImage(BaseDesc& desc, FindFlags flags) { continue; } if (False(flags & FindFlags::RelaxFmt) && - !IsVulkanFormatCompatible(info.pixel_format, cache_image.info.pixel_format)) { + (!IsVulkanFormatCompatible(info.pixel_format, cache_image.info.pixel_format) || + (cache_image.info.type != info.type && info.size != Extent3D{1, 1, 1}))) { continue; } if (True(flags & FindFlags::ExactFmt) && info.pixel_format != cache_image.info.pixel_format) { continue; } - ASSERT((cache_image.info.type == info.type || info.size == Extent3D{1, 1, 1} || - True(flags & FindFlags::RelaxFmt))); image_id = cache_id; }