diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 9393380e2..55549ab4c 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -205,8 +205,8 @@ jobs:
run: |
mkdir upload
mv ${{github.workspace}}/build/shadps4 upload
- cp ${{github.workspace}}/build/externals/MoltenVK/libMoltenVK.dylib upload
- install_name_tool -add_rpath "@executable_path" upload/shadps4
+ 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 }}
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 a7791dc7e..8d0e1935e 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}")
@@ -1087,34 +1087,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/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 2ff1ddaf7..1a6ff9ec8 100644
--- a/src/common/path_util.cpp
+++ b/src/common/path_util.cpp
@@ -88,7 +88,7 @@ static std::optional GetBundleParentDirectory() {
#endif
static auto UserPaths = [] {
-#ifdef __APPLE__
+#if defined(__APPLE__) && defined(ENABLE_QT_GUI)
// Set the current path to the directory containing the app bundle.
if (const auto bundle_dir = GetBundleParentDirectory()) {
std::filesystem::current_path(*bundle_dir);
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/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/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;