Merge branch 'main' into fontlib

This commit is contained in:
georgemoralis 2025-04-23 15:06:02 +03:00 committed by GitHub
commit 30e609cf4e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 378 additions and 282 deletions

View file

@ -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

2
.gitmodules vendored
View file

@ -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

View file

@ -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)

View file

@ -13,7 +13,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<h1 align="center">
<a href="https://discord.gg/bFJxfftGW6">
<img src="https://img.shields.io/discord/1080089157554155590?color=5865F2&label=shadPS4 Discord&logo=Discord&logoColor=white" width="240">
<img src="https://img.shields.io/discord/1080089157554155590?color=5865F2&label=shadPS4%20Discord&logo=Discord&logoColor=white" width="275">
<a href="https://github.com/shadps4-emu/shadPS4/releases/latest">
<img src="https://img.shields.io/github/downloads/shadps4-emu/shadPS4/total.svg" width="140">
<a href="https://shadps4.net/">

View file

@ -37,6 +37,9 @@
<category translate="no">Game</category>
</categories>
<releases>
<release version="0.8.0" date="2025-05-23">
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.8.0</url>
</release>
<release version="0.7.0" date="2025-03-23">
<url>https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.7.0</url>
</release>

@ -1 +1 @@
Subproject commit 067fc6c85b02f37dfda58eeda49d8458e093ed60
Subproject commit 4cf8f94684c53e581eb9cc694dd3305d1f7d9959

View file

@ -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
}
}

@ -1 +1 @@
Subproject commit 185833a61cbe29ce3bfb5a499ffb3dfeaee3bbe7
Subproject commit 2275d0efc4f2fa46851035d9d3c67c105bc8b99e

View file

@ -60,7 +60,7 @@ static CFURLRef UntranslocateBundlePath(const CFURLRef bundle_path) {
return nullptr;
}
static std::filesystem::path GetBundleParentDirectory() {
static std::optional<std::filesystem::path> 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.

View file

@ -112,18 +112,6 @@ void Linker::Execute(const std::vector<std::string> 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<void*>(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();

View file

@ -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<QKeyEvent*>(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<QMouseEvent*>(event);
if (event->type() == QEvent::MouseButtonPress) {
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(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<QPushButton*> AxisList = {
ui->LStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->LStickRightButton,
ui->RStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->RStickRightButton};
const QList<QPushButton*> 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<QWheelEvent*>(event);
if (event->type() == QEvent::Wheel) {
QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(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);
}

View file

@ -25,6 +25,22 @@ private:
std::unique_ptr<Ui::KBMSettings> ui;
std::shared_ptr<GameInfoClass> 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<QString> pressedKeys;
bool EnableMapping = false;
bool MappingCompleted = false;
bool HelpWindowOpen = false;

View file

@ -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
};

View file

@ -66,7 +66,7 @@
</message>
<message>
<source>You can delete the cheats you don&apos;t want after downloading them.</source>
<translation>يمكنك حذف الشفرات التي لا تريدها بعد تنزيلها.</translation>
<translation>يمكنك حذف الشفرات التي لا &apos;تريدها بعد تنزيلها.</translation>
</message>
<message>
<source>Do you want to delete the selected file?\n%1</source>
@ -74,11 +74,11 @@
</message>
<message>
<source>Select Patch File:</source>
<translation>إختر ملف الباتش:</translation>
<translation>اختر مِلَف التصحيح:</translation>
</message>
<message>
<source>Download Patches</source>
<translation>تحميل الباتشات</translation>
<translation>تحميل ملفات التصحيح</translation>
</message>
<message>
<source>Save</source>
@ -98,15 +98,15 @@
</message>
<message>
<source>No patch selected.</source>
<translation>لم يتم اختيار أي تصحيح.</translation>
<translation>لم يتم تحديد أي مِلَف تصحيح.</translation>
</message>
<message>
<source>Unable to open files.json for reading.</source>
<translation>تعذر فتح files.json للقراءة.</translation>
<translation>تعذّر فتح مِلَف files.json للقراءة.</translation>
</message>
<message>
<source>No patch file found for the current serial.</source>
<translation>لم يتم العثور على مِلَفّ باتش للسيريال الحالي.</translation>
<translation>لم يتم العثور على مِلَف تصحيح للسيريال الحالي.</translation>
</message>
<message>
<source>Unable to open the file for reading.</source>
@ -126,11 +126,11 @@
</message>
<message>
<source>Options saved successfully.</source>
<translation>تم حفظ الخيارات بنجاح.</translation>
<translation>تم حفظ الإعدادات.</translation>
</message>
<message>
<source>Invalid Source</source>
<translation>مصدر غير صالح</translation>
<translation>المصدر غير صالح</translation>
</message>
<message>
<source>The selected source is invalid.</source>
@ -138,11 +138,11 @@
</message>
<message>
<source>File Exists</source>
<translation>الملف موجود</translation>
<translation>المِلَف موجود مسبقًا</translation>
</message>
<message>
<source>File already exists. Do you want to replace it?</source>
<translation>يوجد ملف بنفس الاسم. هل ترغب في استبداله؟</translation>
<translation>المِلَف موجود مسبقًا. هل ترغب في استبداله؟</translation>
</message>
<message>
<source>Failed to save file:</source>
@ -158,7 +158,7 @@
</message>
<message>
<source>No Cheats found for this game in this version of the selected repository,try another repository or a different version of the game.</source>
<translation>لم يتم العثور على شفرات لهذه اللعبة في هذه النسخة من المستودع المحدد. حاول استخدام مستودع آخر أو نسخة مختلفة من اللعبة.</translation>
<translation>لم يتم العثور على شفرات لهذه اللعبة في هذا الإصدار من المستودع المحدد. جرّب مستودعًا آخر أو إصدارًا مختلفًا من اللعبة.</translation>
</message>
<message>
<source>Cheats Downloaded Successfully</source>
@ -182,7 +182,7 @@
</message>
<message>
<source>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.</source>
<translation>تم تنزيل التصحيحات بنجاح! تم تنزيل جميع التصحيحات لجميع الألعاب، ولا داعي لتنزيلها بشكل فردي لكل لعبة كما هو الحال مع الغش. إذا لم يظهر التحديث، قد يكون السبب أنه غير متوفر للإصدار وسيريال اللعبة المحدد.</translation>
<translation>تم تنزيل التصحيحات بنجاح! تم تنزيل جميع التصحيحات المتوفرة لجميع الألعاب، ولا حاجة إلى تنزيلها بشكل فردي لكل لعبة كما هو الحال مع الشفرات. إذا لم يظهر التصحيح، فقد لا يكون متوفرًا للسيريال أو الإصدار المحدد من اللعبة.</translation>
</message>
<message>
<source>Failed to parse JSON data from HTML.</source>
@ -190,15 +190,15 @@
</message>
<message>
<source>Failed to retrieve HTML page.</source>
<translation>.HTML فشل في استرجاع صفحة</translation>
<translation>فشل في جلب صفحة HTML.</translation>
</message>
<message>
<source>The game is in version: %1</source>
<translation>النسخة الحالية للعبة هي: %1</translation>
<translation>إصدار اللعبة الحالي: %1</translation>
</message>
<message>
<source>The downloaded patch only works on version: %1</source>
<translation>الباتش الذي تم تنزيله يعمل فقط على الإصدار: %1</translation>
<translation>التصحيح الذي تم تنزيله يعمل فقط مع الإصدار:%1</translation>
</message>
<message>
<source>You may need to update your game.</source>
@ -206,7 +206,7 @@
</message>
<message>
<source>Incompatibility Notice</source>
<translation>إشعار عدم التوافق</translation>
<translation>إشعار بعدم التوافق</translation>
</message>
<message>
<source>Failed to open file:</source>
@ -238,7 +238,7 @@
</message>
<message>
<source>Can&apos;t apply cheats before the game is started</source>
<translation>لا يمكن تطبيق الغش قبل بدء اللعبة.</translation>
<translation>لا &apos;يمكن تطبيق الشفرات قبل بَدْء اللعبة</translation>
</message>
<message>
<source>Close</source>
@ -249,7 +249,7 @@
<name>CheckUpdate</name>
<message>
<source>Auto Updater</source>
<translation>محدث تلقائي</translation>
<translation>التحديثات التلقائية</translation>
</message>
<message>
<source>Error</source>
@ -261,7 +261,7 @@
</message>
<message>
<source>The Auto Updater allows up to 60 update checks per hour.\nYou have reached this limit. Please try again later.</source>
<translation>يتيح التحديث التلقائي ما يصل إلى 60 عملية تحقق من التحديث في الساعة.\nلقد وصلت إلى هذا الحد. الرجاء المحاولة مرة أخرى لاحقًا.</translation>
<translation>تسمح التحديثات التلقائية بـ 60 عملية تحقق من التحديث في الساعة.\nلقد وصلت إلى الحد المسموح به. الرجاء المحاولة لاحقًا.</translation>
</message>
<message>
<source>Failed to parse update information.</source>

View file

@ -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);

View file

@ -4,6 +4,7 @@
#include <algorithm>
#include <unordered_map>
#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<u32> ResolveSetPcTarget(std::span<const GcnInst> list, u32 setpc_index,
std::span<const u32> 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<s32>(imm) : -static_cast<s32>(imm);
const u32 base_pc = pc_map[setpc_index - 3] + getpc.length;
const u32 result_pc = static_cast<u32>(static_cast<s32>(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>& block_pool_, std::span<const GcnInst> 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;

View file

@ -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 {

View file

@ -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:

View file

@ -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(),
};

View file

@ -122,21 +122,21 @@ GraphicsPipeline::GraphicsPipeline(
};
boost::container::static_vector<vk::DynamicState, 20> 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,

View file

@ -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<vk::PhysicalDeviceFeatures2, vk::PhysicalDeviceVulkan11Features,
vk::PhysicalDeviceVulkan12Features, vk::PhysicalDeviceVulkan13Features,
vk::PhysicalDeviceRobustness2FeaturesEXT,
vk::PhysicalDeviceExtendedDynamicState3FeaturesEXT,
vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT,
vk::PhysicalDevicePortabilitySubsetFeaturesKHR>();
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<vk::PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT>();
const auto vk11_features = feature_chain.get<vk::PhysicalDeviceVulkan11Features>();
const auto vk12_features = feature_chain.get<vk::PhysicalDeviceVulkan12Features>();
const auto vk13_features = feature_chain.get<vk::PhysicalDeviceVulkan13Features>();
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));

View file

@ -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),

View file

@ -22,6 +22,10 @@
#include "sdl_window.h"
#include "video_core/renderer_vulkan/vk_platform.h"
#ifdef __APPLE__
#include <mach-o/dyld.h>
#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";

View file

@ -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);

View file

@ -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;

View file

@ -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;
}