Merge branch 'main' into fontlib

This commit is contained in:
georgemoralis 2025-04-13 23:33:36 +03:00 committed by GitHub
commit c12319f11a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
55 changed files with 817 additions and 196 deletions

View file

@ -10,7 +10,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED True)
if(APPLE)
list(APPEND ADDITIONAL_LANGUAGES OBJC)
# Starting with 15.4, Rosetta 2 has support for all the necessary instruction sets.
set(CMAKE_OSX_DEPLOYMENT_TARGET 15.4)
set(CMAKE_OSX_DEPLOYMENT_TARGET 15.4 CACHE STRING "")
endif()
if (NOT CMAKE_BUILD_TYPE)
@ -54,9 +54,9 @@ else()
endif()
if (ARCHITECTURE STREQUAL "x86_64")
# Target Sandy Bridge as a reasonable subset of instructions supported by PS4 and host CPUs.
# Note that the native PS4 architecture 'btver2' has been attempted but causes issues with M1 CPUs.
add_compile_options(-march=sandybridge -mtune=generic)
# Target the same CPU architecture as the PS4, to maintain the same level of compatibility.
# Exclude SSE4a as it is only available on AMD CPUs.
add_compile_options(-march=btver2 -mtune=generic -mno-sse4a)
endif()
if (APPLE AND ARCHITECTURE STREQUAL "x86_64" AND CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")
@ -105,11 +105,8 @@ if (CLANG_FORMAT)
unset(CCOMMENT)
endif()
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# generate git revision information
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules/")
include(GetGitRevisionDescription)
include("${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules/GetGitRevisionDescription.cmake")
get_git_head_revision(GIT_REF_SPEC GIT_REV)
git_describe(GIT_DESC --always --long --dirty)
git_branch_name(GIT_BRANCH)
@ -209,6 +206,7 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_
message("end git things, remote: ${GIT_REMOTE_NAME}, branch: ${GIT_BRANCH}")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(Boost 1.84.0 CONFIG)
find_package(FFmpeg 5.1.2 MODULE)
find_package(fmt 10.2.0 CONFIG)
@ -229,10 +227,10 @@ find_package(ZLIB 1.3 MODULE)
find_package(Zydis 5.0.0 CONFIG)
find_package(pugixml 1.14 CONFIG)
find_package(libusb 1.0.27 MODULE)
if (APPLE)
find_package(date 3.0.1 CONFIG)
endif()
list(POP_BACK CMAKE_MODULE_PATH)
# Note: Windows always has these functions through winpthreads
include(CheckSymbolExists)
@ -1180,7 +1178,7 @@ target_include_directories(shadps4 PRIVATE ${HOST_SHADERS_INCLUDE})
# embed resources
include(CMakeRC)
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/CMakeRC.cmake")
cmrc_add_resource_library(embedded-resources
ALIAS res::embedded
NAMESPACE res

View file

@ -57,11 +57,18 @@ path = [
"src/images/utils_icon.png",
"src/images/shadPS4.icns",
"src/images/shadps4.ico",
"src/images/shadps4.png",
"src/images/net.shadps4.shadPS4.svg",
"src/images/themes_icon.png",
"src/images/update_icon.png",
"src/images/youtube.png",
"src/images/website.png",
"src/images/discord.svg",
"src/images/github.svg",
"src/images/ko-fi.svg",
"src/images/shadps4.svg",
"src/images/website.svg",
"src/images/youtube.svg",
"src/shadps4.qrc",
"src/shadps4.rc",
"src/qt_gui/translations/update_translation.sh",

View file

@ -24,7 +24,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
- A CPU supporting the following instruction sets: MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, F16C, CLMUL, AES, BMI1, MOVBE, XSAVE, ABM
- **Intel**: Haswell generation or newer
- **AMD**: Jaguar generation or newer
- **Apple**: Rosetta 2 on macOS 15 or newer
- **Apple**: Rosetta 2 on macOS 15.4 or newer
### GPU

@ -1 +1 @@
Subproject commit cb71abe3063094bf383379b15473d39cb1144120
Subproject commit 68300dc07ac3dc592dbbdb87e02d5180f984ad12

@ -1 +1 @@
Subproject commit d1fcec807b372f04e4c1041b3058e11c12853e6e
Subproject commit a56bad8bbb770ee266e930c95d37fff2a5be7fea

2
externals/date vendored

@ -1 +1 @@
Subproject commit 28b7b232521ace2c8ef3f2ad4126daec3569c14f
Subproject commit a45ea7c17b4a7f320e199b71436074bd624c9e15

@ -1 +1 @@
Subproject commit 636cd4a7d623a2bc9bf59bb3acbb4ca075befba3
Subproject commit f4d9359095eff3eb03f685921edc1cf0e37b1687

@ -1 +1 @@
Subproject commit d3b5af8827031f3bccbf8c15d5dc1bfdc9467f17
Subproject commit 19f66e6dcabb2268965f453db9e5774ede43238f

@ -1 +1 @@
Subproject commit 27de97c826b6b40c255891c37ac046a25836a575
Subproject commit b0de1dcca26c0ebfb8011b8e59dd17fc399db0ff

2
externals/fmt vendored

@ -1 +1 @@
Subproject commit 8ee89546ffcf046309d1f0d38c0393f02fde56c8
Subproject commit 64db979e38ec644b1798e41610b28c8d2c8a2739

2
externals/glslang vendored

@ -1 +1 @@
Subproject commit a0995c49ebcaca2c6d3b03efbabf74f3843decdb
Subproject commit ba1640446f3826a518721d1f083f3a8cca1120c3

2
externals/libpng vendored

@ -1 +1 @@
Subproject commit c1cc0f3f4c3d4abd11ca68c59446a29ff6f95003
Subproject commit 34005e3d3d373c0c36898cc55eae48a79c8238a1

2
externals/libusb vendored

@ -1 +1 @@
Subproject commit 8f0b4a38fc3eefa2b26a99dff89e1c12bf37afd4
Subproject commit a63a7e43e0950a595cf4b98a0eaf4051749ace5f

@ -1 +1 @@
Subproject commit 1a1824df7ac798177a521eed952720681b0bf482
Subproject commit a413fcc9c46a020a746907136a384c227f3cd095

2
externals/pugixml vendored

@ -1 +1 @@
Subproject commit 4bc14418d12d289dd9978fdce9490a45deeb653e
Subproject commit caade5a28aad86b92a4b5337a9dc70c4ba73c5eb

2
externals/robin-map vendored

@ -1 +1 @@
Subproject commit fe845fd7852ef541c5479ae23b3d36b57f8608ee
Subproject commit 4ec1bf19c6a96125ea22062f38c2cf5b958e448e

2
externals/sdl3 vendored

@ -1 +1 @@
Subproject commit a336b62d8b0b97b09214e053203e442e2b6e2be5
Subproject commit 4093e4a193971ef1d4928158e0a1832be42e4599

2
externals/toml11 vendored

@ -1 +1 @@
Subproject commit 7f6c574ff5aa1053534e7e19c0a4f22bf4c6aaca
Subproject commit a01fe3b4c14c6d7b99ee3f07c9e80058c6403097

2
externals/vma vendored

@ -1 +1 @@
Subproject commit 5a53a198945ba8260fbc58fadb788745ce6aa263
Subproject commit f378e7b3f18f6e2b06b957f6ba7b1c7207d2a536

@ -1 +1 @@
Subproject commit 952f776f6573aafbb62ea717d871cd1d6816c387
Subproject commit 5ceb9ed481e58e705d0d9b5326537daedd06b97d

@ -1 +1 @@
Subproject commit f00c973a6ab2a23573708568b8ef4acc20a9d36b
Subproject commit f35b0948d36a736e6a2d052ae295a3ffde09703f

2
externals/xbyak vendored

@ -1 +1 @@
Subproject commit 4e44f4614ddbf038f2a6296f5b906d5c72691e0f
Subproject commit 44a72f369268f7d552650891b296693e91db86bb

2
externals/xxhash vendored

@ -1 +1 @@
Subproject commit 2bf8313b934633b2a5b7e8fd239645b85e10c852
Subproject commit 953a09abc39096da9e216b6eb0002c681cdc1199

2
externals/zlib-ng vendored

@ -1 +1 @@
Subproject commit d54e3769be0c522015b784eca2af258b1c026107
Subproject commit fd0d263cedab1a136f40d65199987e3eaeecfcbd

2
externals/zydis vendored

@ -1 +1 @@
Subproject commit bffbb610cfea643b98e87658b9058382f7522807
Subproject commit 120e0e705f8e3b507dc49377ac2879979f0d545c

View file

@ -627,65 +627,56 @@ void TextEditor::HandleKeyboardInputs() {
io.WantCaptureKeyboard = true;
io.WantTextInput = true;
if (!IsReadOnly() && ctrl && !shift && !alt &&
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Z)))
if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Z))
Undo();
else if (!IsReadOnly() && !ctrl && !shift && alt &&
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace)))
else if (!IsReadOnly() && !ctrl && !shift && alt && ImGui::IsKeyPressed(ImGuiKey_Backspace))
Undo();
else if (!IsReadOnly() && ctrl && !shift && !alt &&
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Y)))
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Y))
Redo();
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_UpArrow)))
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_UpArrow))
MoveUp(1, shift);
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_DownArrow)))
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_DownArrow))
MoveDown(1, shift);
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_LeftArrow)))
else if (!alt && ImGui::IsKeyPressed(ImGuiKey_LeftArrow))
MoveLeft(1, shift, ctrl);
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_RightArrow)))
else if (!alt && ImGui::IsKeyPressed(ImGuiKey_RightArrow))
MoveRight(1, shift, ctrl);
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageUp)))
else if (!alt && ImGui::IsKeyPressed(ImGuiKey_PageUp))
MoveUp(GetPageSize() - 4, shift);
else if (!alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_PageDown)))
else if (!alt && ImGui::IsKeyPressed(ImGuiKey_PageDown))
MoveDown(GetPageSize() - 4, shift);
else if (!alt && ctrl && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
else if (!alt && ctrl && ImGui::IsKeyPressed(ImGuiKey_Home))
MoveTop(shift);
else if (ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
else if (ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_End))
MoveBottom(shift);
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Home)))
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_Home))
MoveHome(shift);
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_End))
MoveEnd(shift);
else if (!IsReadOnly() && !ctrl && !shift && !alt &&
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Delete))
Delete();
else if (!IsReadOnly() && !ctrl && !shift && !alt &&
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Backspace)))
ImGui::IsKeyPressed(ImGuiKey_Backspace))
Backspace();
else if (!ctrl && !shift && !alt &&
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
else if (!ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Insert))
mOverwrite ^= true;
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Insert))
Copy();
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C)))
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_C))
Copy();
else if (!IsReadOnly() && !ctrl && shift && !alt &&
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
else if (!IsReadOnly() && !ctrl && shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Insert))
Paste();
else if (!IsReadOnly() && ctrl && !shift && !alt &&
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_V)))
else if (!IsReadOnly() && ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_V))
Paste();
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_X)))
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_X))
Cut();
else if (!ctrl && shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Delete)))
else if (!ctrl && shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Delete))
Cut();
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_A)))
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_A))
SelectAll();
else if (!IsReadOnly() && !ctrl && !shift && !alt &&
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Enter)))
else if (!IsReadOnly() && !ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGuiKey_Enter))
EnterCharacter('\n', false);
else if (!IsReadOnly() && !ctrl && !alt &&
ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Tab)))
else if (!IsReadOnly() && !ctrl && !alt && ImGui::IsKeyPressed(ImGuiKey_Tab))
EnterCharacter('\t', shift);
if (!IsReadOnly() && !io.InputQueueCharacters.empty()) {

View file

@ -9,7 +9,7 @@
namespace Libraries::Move {
int PS4_SYSV_ABI sceMoveOpen() {
LOG_ERROR(Lib_Move, "(STUBBED) called");
LOG_TRACE(Lib_Move, "(STUBBED) called");
return ORBIS_FAIL;
}
@ -18,6 +18,11 @@ int PS4_SYSV_ABI sceMoveGetDeviceInfo() {
return ORBIS_OK;
}
int PS4_SYSV_ABI sceMoveReadStateLatest() {
LOG_TRACE(Lib_Move, "(STUBBED) called");
return ORBIS_OK;
}
int PS4_SYSV_ABI sceMoveReadStateRecent() {
LOG_TRACE(Lib_Move, "(STUBBED) called");
return ORBIS_OK;
@ -36,6 +41,7 @@ int PS4_SYSV_ABI sceMoveInit() {
void RegisterlibSceMove(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("HzC60MfjJxU", "libSceMove", 1, "libSceMove", 1, 1, sceMoveOpen);
LIB_FUNCTION("GWXTyxs4QbE", "libSceMove", 1, "libSceMove", 1, 1, sceMoveGetDeviceInfo);
LIB_FUNCTION("ttU+JOhShl4", "libSceMove", 1, "libSceMove", 1, 1, sceMoveReadStateLatest);
LIB_FUNCTION("f2bcpK6kJfg", "libSceMove", 1, "libSceMove", 1, 1, sceMoveReadStateRecent);
LIB_FUNCTION("tsZi60H4ypY", "libSceMove", 1, "libSceMove", 1, 1, sceMoveTerm);
LIB_FUNCTION("j1ITE-EoJmE", "libSceMove", 1, "libSceMove", 1, 1, sceMoveInit);

View file

@ -250,7 +250,6 @@ int PS4_SYSV_ABI scePadMbusTerm() {
}
int PS4_SYSV_ABI scePadOpen(s32 userId, s32 type, s32 index, const OrbisPadOpenParam* pParam) {
LOG_INFO(Lib_Pad, "(DUMMY) called user_id = {} type = {} index = {}", userId, type, index);
if (userId == -1) {
return ORBIS_PAD_ERROR_DEVICE_NO_HANDLE;
}
@ -261,6 +260,7 @@ int PS4_SYSV_ABI scePadOpen(s32 userId, s32 type, s32 index, const OrbisPadOpenP
if (type != ORBIS_PAD_PORT_TYPE_STANDARD && type != ORBIS_PAD_PORT_TYPE_REMOTE_CONTROL)
return ORBIS_PAD_ERROR_DEVICE_NOT_CONNECTED;
}
LOG_INFO(Lib_Pad, "(DUMMY) called user_id = {} type = {} index = {}", userId, type, index);
scePadResetLightBar(1);
return 1; // dummy
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 43 KiB

24
src/images/discord.svg Normal file
View file

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="270.93332mm"
height="270.93332mm"
viewBox="0 0 270.93332 270.93332"
version="1.1"
id="svg1"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" /><g
id="layer1"><circle
style="fill:#000000;stroke-width:0.333618;fill-opacity:1"
id="path1"
cx="135.46666"
cy="135.46666"
r="135.46666" /><path
d="m 194.12363,81.01373 c -10.93928,-5.11822 -22.63609,-8.83793 -34.86478,-10.95597 -1.50182,2.71524 -3.2564,6.36731 -4.46607,9.27253 -12.99943,-1.95495 -25.87929,-1.95495 -38.63961,0 -1.20947,-2.90522 -3.00389,-6.55729 -4.51915,-9.27253 -12.241889,2.11804 -23.952119,5.85142 -34.891409,10.98307 -22.06463,33.34254 -28.045983,65.85691 -25.055298,97.90961 14.634418,10.92863 28.816948,17.56744 42.760118,21.91169 3.44265,-4.73808 6.513019,-9.77474 9.158059,-15.08293 -5.037579,-1.91418 -9.862539,-4.27637 -14.421539,-7.01873 1.20947,-0.89604 2.39255,-1.83288 3.53556,-2.79678 27.806639,13.00588 58.019289,13.00588 85.493719,0 1.15643,0.9639 2.33926,1.90074 3.53556,2.79678 -4.57246,2.75579 -9.41061,5.11798 -14.4482,7.03241 2.64504,5.29451 5.70223,10.34483 9.15805,15.08268 13.95665,-4.34425 28.1523,-10.98282 42.78675,-21.92512 3.50912,-37.15724 -5.99459,-69.37299 -25.12176,-97.93671 z m -86.72985,78.22459 c -8.347289,0 -15.192739,-7.79268 -15.192739,-17.28227 0,-9.48958 6.69928,-17.29569 15.192739,-17.29569 8.49367,0 15.33891,7.79244 15.19272,17.29569 0.0124,9.48959 -6.69905,17.28227 -15.19272,17.28227 z m 56.14517,0 c -8.34727,0 -15.19272,-7.79268 -15.19272,-17.28227 0,-9.48958 6.69904,-17.29569 15.19272,-17.29569 8.49344,0 15.3389,7.79244 15.19272,17.29569 0,9.48959 -6.69928,17.28227 -15.19272,17.28227 z"
fill="#5865F2"
fill-rule="nonzero"
id="path1-1"
style="fill:#ffffff;stroke-width:0.660131" /></g></svg>

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 42 KiB

22
src/images/github.svg Normal file
View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="270.93332mm"
height="270.93332mm"
viewBox="0 0 270.93332 270.93332"
version="1.1"
id="svg1"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" /><g
id="layer1"><circle
style="fill:#000000;fill-opacity:1;stroke-width:0.638749"
id="path6"
cx="135.46666"
cy="135.46666"
r="135.46666" /><path
d="m 169.16642,266.41733 0.03,-25.82065 c 0.0275,-14.56818 0.019,-22.82654 -0.0238,-23.70553 -0.45287,-9.28878 -3.18131,-16.59646 -8.00675,-21.44417 -0.51833,-0.52073 -0.93407,-0.95373 -0.92397,-0.96273 0.0101,-0.009 0.44777,-0.0663 0.97255,-0.12764 37.08454,-4.33929 55.61974,-20.97235 59.5452,-53.43395 2.47353,-20.45482 -1.25492,-35.28308 -11.991,-47.687007 -0.441,-0.50949 -0.85644,-0.996495 -0.92294,-1.082105 -0.11924,-0.153612 -0.11632,-0.168083 0.21291,-1.092956 3.48926,-9.801891 3.08146,-21.84476 -1.12293,-33.147331 -0.65397,-1.758042 -0.47565,-1.634201 -2.5709,-1.78077 -7.91812,-0.553905 -20.35359,4.335862 -33.80673,13.293762 l -1.15135,0.766879 -0.52658,-0.150896 c -12.92077,-3.704851 -29.09272,-5.157035 -43.79112,-3.932576 -7.21573,0.601112 -14.83438,1.91638 -21.45193,3.70365 l -1.41438,0.381889 -0.95446,-0.635621 C 86.99336,60.049959 72.837429,54.806634 65.589795,56.343848 l -0.309542,0.06563 -0.326595,0.837675 c -4.332806,11.118399 -4.907871,23.48198 -1.547192,33.270837 0.236072,0.687637 0.444934,1.31371 0.464054,1.39113 0.02704,0.109638 -0.130307,0.328834 -0.711584,0.990637 -9.160582,10.429614 -13.392033,22.887494 -12.958383,38.152714 1.106869,38.96344 19.486075,58.39373 59.852157,63.27469 0.65144,0.0787 1.19093,0.14903 1.19993,0.15503 0.008,0.007 -0.42227,0.45425 -0.95705,0.99477 -3.85869,3.90015 -6.54793,9.80164 -7.46414,16.38039 l -0.0827,0.59221 -0.36174,0.17829 c -1.57996,0.77769 -4.999926,1.92702 -7.319448,2.4598 -12.017875,2.76038 -22.054909,-0.77155 -29.200801,-10.27535 -0.611821,-0.81369 -1.002109,-1.39605 -2.631881,-3.92379 -6.342866,-9.8377 -15.85558,-14.92007 -24.055896,-12.85296 -4.140227,1.04365 -2.520489,4.818 3.538802,8.24704 4.584375,2.59434 11.458806,12.02482 14.328324,19.65565 5.313949,14.13125 20.872615,19.63362 43.89345,15.52308 0.48859,-0.0872 0.93963,-0.15902 1.00303,-0.15916 0.10915,-2.5e-4 0.11524,0.79731 0.11524,15.82539 v 19.35334 a 135.46666,135.46666 0 0 0 33.40882,4.45244 135.46666,135.46666 0 0 0 33.69975,-4.516 z"
style="fill:#ffffff;stroke-width:0.777192"
id="path5" /></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

22
src/images/ko-fi.svg Normal file
View file

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="270.93332mm"
height="270.93332mm"
viewBox="0 0 270.93332 270.93332"
version="1.1"
id="svg1"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" /><g
id="layer1"><circle
style="fill:#000000;fill-opacity:1;stroke-width:0.638749"
id="path6"
cx="135.46666"
cy="135.46666"
r="135.46666" /><path
d="M 245.29662,112.91788 C 238.59944,77.525962 203.19888,73.124713 203.19888,73.124713 H 44.658761 c -5.232973,0 -5.882763,6.913782 -5.882763,6.913782 0,0 -0.710438,63.454165 -0.190612,102.424225 1.420874,21.00124 22.404764,23.14987 22.404764,23.14987 0,0 71.62419,-0.19923 103.67183,-0.42453 21.12252,-3.69082 23.24517,-22.23147 23.02856,-32.35089 37.70517,2.07933 64.30326,-24.52739 57.60608,-59.91929 z m -95.83971,30.41882 c -10.79518,12.58861 -34.75078,34.44754 -34.75078,34.44754 0,0 -1.04833,1.031 -2.6858,0.19924 -0.65845,-0.49382 -0.93569,-0.77972 -0.93569,-0.77972 -3.83809,-3.82079 -29.179908,-26.41616 -34.950046,-34.25694 -6.14268,-8.36065 -9.019085,-23.39244 -0.788412,-32.14296 8.239342,-8.75052 26.034928,-9.40895 37.800448,3.5262 0,0 13.55896,-15.439026 30.0463,-8.34332 16.49601,7.1044 15.8722,26.0869 6.26398,37.34992 z m 53.48205,4.14135 c -8.04007,1.00499 -14.57263,0.24252 -14.57263,0.24252 V 98.501153 h 15.33506 c 0,0 17.07647,4.773777 17.07647,22.855257 0,16.57399 -8.53391,23.10655 -17.8389,26.12157 z"
id="path1"
style="fill:#ffffff;stroke-width:8.66388" /></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 401 KiB

BIN
src/images/shadps4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

105
src/images/shadps4.svg Normal file
View file

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
version="1.1"
viewBox="0 0 256 256"
xml:space="preserve"
id="svg10"
width="256"
height="256"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs3"><linearGradient
id="linearGradient1"><stop
stop-color="#0b034f"
offset="0"
id="stop1" /><stop
stop-color="#4461f2"
offset="1"
id="stop2" /></linearGradient><linearGradient
id="linearGradient2"
x1="100"
x2="100"
y1="185.84"
y2="14.157"
gradientUnits="userSpaceOnUse"
xlink:href="#linearGradient1"
gradientTransform="matrix(1.4489308,0,0,1.4489308,-16.890188,-16.890188)" /><mask
id="mask9"
maskUnits="userSpaceOnUse"><path
d="m -4.1597,120.43 65.304,22.774 -20.899,59.926 -65.304,-22.774 z"
fill="none"
stroke="#149ffb"
stroke-linecap="square"
stroke-width="11"
style="paint-order:markers fill stroke"
id="path2" /></mask><mask
id="mask10"
maskUnits="userSpaceOnUse"><path
d="M 178.79,52.448 133.386,71.834 139.2995,22.82 Z"
fill="none"
stroke="#149ffb"
stroke-linecap="square"
stroke-width="6.75"
style="paint-order:markers fill stroke"
id="path3" /></mask><linearGradient
xlink:href="#linearGradient1"
id="linearGradient10"
gradientUnits="userSpaceOnUse"
x1="100"
y1="185.84"
x2="100"
y2="14.157"
gradientTransform="matrix(1.4489308,0,0,1.4489308,-16.890188,-16.890188)" /></defs><path
d="M 53.640867,3.6223249 H 202.35913 c 27.70935,0 50.01854,22.3077391 50.01854,50.0185421 V 202.35913 c 0,27.70935 -22.30774,50.01854 -50.01854,50.01854 H 53.640867 c -27.709354,0 -50.0185421,-22.30774 -50.0185421,-50.01854 V 53.640867 c 0,-27.709354 22.3077391,-50.0185421 50.0185421,-50.0185421 z"
fill="url(#linearGradient2)"
stroke="#ffffff"
stroke-linecap="square"
stroke-linejoin="round"
stroke-width="7.24465"
style="fill:url(#linearGradient10);paint-order:markers fill stroke"
id="path4" /><path
d="M 53.640867,3.6223249 H 202.35913 c 27.70935,0 50.01854,22.3077391 50.01854,50.0185421 V 202.35913 c 0,27.70935 -22.30774,50.01854 -50.01854,50.01854 H 53.640867 c -27.709354,0 -50.0185421,-22.30774 -50.0185421,-50.01854 V 53.640867 c 0,-27.709354 22.3077391,-50.0185421 50.0185421,-50.0185421 z"
fill="url(#linearGradient2)"
stroke="#ffffff"
stroke-linecap="square"
stroke-linejoin="round"
stroke-width="7.24465"
style="fill:url(#linearGradient2);paint-order:markers fill stroke"
id="path5" /><path
d="m 50.17,16.403 h 99.848 c 18.603,0 33.58,14.977 33.58,33.58 v 99.848 c 0,18.603 -14.977,33.58 -33.58,33.58 H 50.17 c -18.603,0 -33.58,-14.977 -33.58,-33.58 V 49.983 c 0,-18.603 14.977,-33.58 33.58,-33.58 z"
fill="#00ffff"
mask="url(#mask9)"
style="paint-order:markers fill stroke"
id="path6"
transform="matrix(1.4489308,0,0,1.4489308,-16.890189,-16.890189)" /><path
d="m 50.076,16.496 h 99.848 c 18.603,0 33.58,14.977 33.58,33.58 v 99.848 c 0,18.603 -14.977,33.58 -33.58,33.58 H 50.076 c -18.603,0 -33.58,-14.977 -33.58,-33.58 V 50.076 c 0,-18.603 14.977,-33.58 33.58,-33.58 z"
fill="#00ffff"
mask="url(#mask10)"
style="paint-order:markers fill stroke"
id="path7"
transform="matrix(1.4489308,0,0,1.4489308,-16.890189,-16.890189)" /><g
fill="none"
id="g10"
transform="matrix(1.4489308,0,0,1.4489308,-16.890189,-16.890189)"><path
transform="matrix(0.91041,0.0063593,-0.0063593,0.91041,28.548,42.178)"
d="m 166.13,88.68 -23.677,14.288 13.949,23.879 -14.288,-23.677 -23.879,13.949 23.677,-14.288 -13.949,-23.879 14.288,23.677 z"
stroke="#139ffb"
stroke-linecap="square"
stroke-width="12.43"
style="paint-order:markers fill stroke"
id="path8" /><path
d="M 117.98,135.88 V 47.598 l -65.093,69.568 h 83.807"
stroke="#ffffff"
stroke-linecap="square"
stroke-linejoin="round"
stroke-width="10"
style="font-variation-settings:normal;paint-order:markers fill stroke"
id="path9" /><path
d="M 69.923,56.468 A 20.994,21.009 0 0 1 49.012,77.477 20.994,21.009 0 0 1 27.936,56.634 20.994,21.009 0 0 1 48.68,35.46 20.994,21.009 0 0 1 69.92,56.135"
stop-color="#000000"
stroke="#139ffb"
stroke-linecap="round"
stroke-width="9.4488"
style="paint-order:markers fill stroke"
id="path10" /></g></svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 72 KiB

22
src/images/website.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 32 KiB

28
src/images/youtube.svg Normal file
View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="270.93332mm"
height="270.93332mm"
viewBox="0 0 270.93332 270.93332"
version="1.1"
id="svg1"
xml:space="preserve"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1" /><g
id="layer1"><circle
style="fill:#000000;fill-opacity:1;stroke-width:0.638749"
id="path6"
cx="135.46666"
cy="135.46666"
r="135.46666" /><g
style="fill:#ffffff;fill-rule:nonzero;stroke:none;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none"
transform="matrix(1.8837557,0,0,1.8837557,50.69765,50.69765)"
id="g1">
<path
d="M 88.119,23.338 C 87.084,19.466 84.034,16.416 80.162,15.381 73.144,13.5 45,13.5 45,13.5 c 0,0 -28.144,0 -35.162,1.881 C 5.966,16.416 2.916,19.466 1.881,23.338 0,30.356 0,45 0,45 0,45 0,59.644 1.881,66.662 2.916,70.534 5.966,73.584 9.838,74.619 16.856,76.5 45,76.5 45,76.5 c 0,0 28.144,0 35.162,-1.881 3.872,-1.035 6.922,-4.085 7.957,-7.957 C 90,59.644 90,45 90,45 90,45 90,30.356 88.119,23.338 Z M 36,58.5 v -27 L 59.382,45 Z"
style="opacity:1;fill:#ffffff;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none"
stroke-linecap="round"
id="path1" />
</g></g></svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -50,14 +50,14 @@ inline void KeepWindowInside(ImVec2 display_size = GetIO().DisplaySize) {
}
inline void KeepNavHighlight() {
GetCurrentContext()->NavDisableHighlight = false;
GetCurrentContext()->NavCursorVisible = true;
}
inline void SetItemCurrentNavFocus(const ImGuiID id = -1) {
const auto ctx = GetCurrentContext();
SetFocusID(id == -1 ? ctx->LastItemData.ID : id, ctx->CurrentWindow);
ctx->NavInitResult.Clear();
ctx->NavDisableHighlight = false;
ctx->NavCursorVisible = true;
}
inline void DrawPrettyBackground() {

View file

@ -35,7 +35,7 @@
<string/>
</property>
<property name="pixmap">
<pixmap>:/images/shadps4.ico</pixmap>
<pixmap>:/images/shadps4.png</pixmap>
</property>
<property name="scaledContents">
<bool>true</bool>

View file

@ -188,7 +188,7 @@ void CheckUpdate::setupUI(const QString& downloadUrl, const QString& latestDate,
QHBoxLayout* titleLayout = new QHBoxLayout();
QLabel* imageLabel = new QLabel(this);
QPixmap pixmap(":/images/shadps4.ico");
QPixmap pixmap(":/images/shadps4.png");
imageLabel->setPixmap(pixmap);
imageLabel->setScaledContents(true);
imageLabel->setFixedSize(50, 50);

View file

@ -1,6 +1,7 @@
<RCC>
<qresource prefix="/">
<file>images/shadps4.ico</file>
<file>images/shadps4.png</file>
<file>images/about_icon.png</file>
<file>images/dump_icon.png</file>
<file>images/play_icon.png</file>

View file

@ -156,6 +156,18 @@ vk::CullModeFlags CullMode(Liverpool::CullMode mode) {
}
}
vk::FrontFace FrontFace(Liverpool::FrontFace face) {
switch (face) {
case Liverpool::FrontFace::Clockwise:
return vk::FrontFace::eClockwise;
case Liverpool::FrontFace::CounterClockwise:
return vk::FrontFace::eCounterClockwise;
default:
UNREACHABLE();
return vk::FrontFace::eClockwise;
}
}
vk::BlendFactor BlendFactor(Liverpool::BlendControl::BlendFactor factor) {
using BlendFactor = Liverpool::BlendControl::BlendFactor;
switch (factor) {

View file

@ -26,6 +26,8 @@ vk::PolygonMode PolygonMode(Liverpool::PolygonMode mode);
vk::CullModeFlags CullMode(Liverpool::CullMode mode);
vk::FrontFace FrontFace(Liverpool::FrontFace mode);
vk::BlendFactor BlendFactor(Liverpool::BlendControl::BlendFactor factor);
vk::BlendOp BlendOp(Liverpool::BlendControl::BlendFunc func);

View file

@ -28,6 +28,15 @@ static constexpr std::array LogicalStageToStageBit = {
vk::ShaderStageFlagBits::eCompute,
};
static bool IsPrimitiveTopologyList(const vk::PrimitiveTopology topology) {
return topology == vk::PrimitiveTopology::ePointList ||
topology == vk::PrimitiveTopology::eLineList ||
topology == vk::PrimitiveTopology::eTriangleList ||
topology == vk::PrimitiveTopology::eLineListWithAdjacency ||
topology == vk::PrimitiveTopology::eTriangleListWithAdjacency ||
topology == vk::PrimitiveTopology::ePatchList;
}
GraphicsPipeline::GraphicsPipeline(
const Instance& instance, Scheduler& scheduler, DescriptorHeap& desc_heap,
const Shader::Profile& profile, const GraphicsPipelineKey& key_,
@ -75,19 +84,15 @@ GraphicsPipeline::GraphicsPipeline(
.pVertexAttributeDescriptions = vertex_attributes.data(),
};
auto prim_restart = key.enable_primitive_restart != 0;
if (prim_restart && IsPrimitiveListTopology() && !instance.IsListRestartSupported()) {
LOG_DEBUG(Render_Vulkan,
"Primitive restart is enabled for list topology but not supported by driver.");
prim_restart = false;
}
const auto topology = LiverpoolToVK::PrimitiveType(key.prim_type);
const vk::PipelineInputAssemblyStateCreateInfo input_assembly = {
.topology = LiverpoolToVK::PrimitiveType(key.prim_type),
.primitiveRestartEnable = prim_restart,
.topology = topology,
// Avoid warning spam on all pipelines about unsupported restart disable, if not supported.
// However, must be false for list topologies to avoid validation errors.
.primitiveRestartEnable =
!instance.IsPrimitiveRestartDisableSupported() && !IsPrimitiveTopologyList(topology),
};
ASSERT_MSG(!prim_restart || key.primitive_restart_index == 0xFFFF ||
key.primitive_restart_index == 0xFFFFFFFF,
"Primitive restart index other than -1 is not supported yet");
const bool is_rect_list = key.prim_type == AmdGpu::PrimitiveType::RectList;
const bool is_quad_list = key.prim_type == AmdGpu::PrimitiveType::QuadList;
const auto& fs_info = runtime_infos[u32(Shader::LogicalStage::Fragment)].fs_info;
@ -99,12 +104,6 @@ GraphicsPipeline::GraphicsPipeline(
.depthClampEnable = false,
.rasterizerDiscardEnable = false,
.polygonMode = LiverpoolToVK::PolygonMode(key.polygon_mode),
.cullMode = LiverpoolToVK::IsPrimitiveCulled(key.prim_type)
? LiverpoolToVK::CullMode(key.cull_mode)
: vk::CullModeFlagBits::eNone,
.frontFace = key.front_face == Liverpool::FrontFace::Clockwise
? vk::FrontFace::eClockwise
: vk::FrontFace::eCounterClockwise,
.lineWidth = 1.0f,
};
@ -122,16 +121,20 @@ GraphicsPipeline::GraphicsPipeline(
.pNext = instance.IsDepthClipControlSupported() ? &clip_control : nullptr,
};
boost::container::static_vector<vk::DynamicState, 17> dynamic_states = {
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::eStencilOpEXT, vk::DynamicState::eCullModeEXT,
vk::DynamicState::eFrontFaceEXT,
};
if (instance.IsPrimitiveRestartDisableSupported()) {
dynamic_states.push_back(vk::DynamicState::ePrimitiveRestartEnableEXT);
}
if (instance.IsDepthBoundsSupported()) {
dynamic_states.push_back(vk::DynamicState::eDepthBoundsTestEnableEXT);
dynamic_states.push_back(vk::DynamicState::eDepthBounds);

View file

@ -42,11 +42,7 @@ struct GraphicsPipelineKey {
u32 num_samples;
u32 mrt_mask;
AmdGpu::PrimitiveType prim_type;
u32 enable_primitive_restart;
u32 primitive_restart_index;
Liverpool::PolygonMode polygon_mode;
Liverpool::CullMode cull_mode;
Liverpool::FrontFace front_face;
Liverpool::ClipSpace clip_space;
Liverpool::ColorBufferMask cb_shader_mask;
std::array<Liverpool::BlendControl, Liverpool::NumColorBuffers> blend_controls;
@ -82,16 +78,6 @@ public:
return key.mrt_mask;
}
[[nodiscard]] bool IsPrimitiveListTopology() const {
return key.prim_type == AmdGpu::PrimitiveType::PointList ||
key.prim_type == AmdGpu::PrimitiveType::LineList ||
key.prim_type == AmdGpu::PrimitiveType::TriangleList ||
key.prim_type == AmdGpu::PrimitiveType::AdjLineList ||
key.prim_type == AmdGpu::PrimitiveType::AdjTriangleList ||
key.prim_type == AmdGpu::PrimitiveType::RectList ||
key.prim_type == AmdGpu::PrimitiveType::QuadList;
}
/// Gets the attributes and bindings for vertex inputs.
template <typename Attribute, typename Binding>
void GetVertexInputs(VertexInputs<Attribute>& attributes, VertexInputs<Binding>& bindings,

View file

@ -292,6 +292,11 @@ public:
properties.limits.framebufferStencilSampleCounts;
}
/// Returns whether disabling primitive restart is supported.
bool IsPrimitiveRestartDisableSupported() const {
return driver_id != vk::DriverId::eMoltenvk;
}
private:
/// Creates the logical device opportunistically enabling extensions
bool CreateDevice();

View file

@ -283,12 +283,8 @@ bool PipelineCache::RefreshGraphicsKey() {
}
key.prim_type = regs.primitive_type;
key.enable_primitive_restart = regs.enable_primitive_restart & 1;
key.primitive_restart_index = regs.primitive_restart_index;
key.polygon_mode = regs.polygon_control.PolyMode();
key.cull_mode = regs.polygon_control.CullingMode();
key.clip_space = regs.clipper_control.clip_space;
key.front_face = regs.polygon_control.front_face;
key.num_samples = regs.NumSamples();
const bool skip_cb_binding =

View file

@ -946,19 +946,20 @@ void Rasterizer::UnmapMemory(VAddr addr, u64 size) {
mapped_ranges -= boost::icl::interval<VAddr>::right_open(addr, addr + size);
}
void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) {
void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) const {
UpdateViewportScissorState();
UpdateDepthStencilState();
UpdatePrimitiveState();
const auto& regs = liverpool->regs;
const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.setBlendConstants(&regs.blend_constants.red);
if (instance.IsDynamicColorWriteMaskSupported()) {
cmdbuf.setColorWriteMaskEXT(0, pipeline.GetWriteMasks());
}
auto& dynamic_state = scheduler.GetDynamicState();
dynamic_state.SetBlendConstants(&liverpool->regs.blend_constants.red);
dynamic_state.SetColorWriteMasks(pipeline.GetWriteMasks());
// Commit new dynamic state to the command buffer.
dynamic_state.Commit(instance, scheduler.CommandBuffer());
}
void Rasterizer::UpdateViewportScissorState() {
void Rasterizer::UpdateViewportScissorState() const {
const auto& regs = liverpool->regs;
const auto combined_scissor_value_tl = [](s16 scr, s16 win, s16 gen, s16 win_offset) {
@ -1071,95 +1072,86 @@ void Rasterizer::UpdateViewportScissorState() {
scissors.push_back(empty_scissor);
}
const auto cmdbuf = scheduler.CommandBuffer();
cmdbuf.setViewportWithCountEXT(viewports);
cmdbuf.setScissorWithCountEXT(scissors);
auto& dynamic_state = scheduler.GetDynamicState();
dynamic_state.SetViewports(viewports);
dynamic_state.SetScissors(scissors);
}
void Rasterizer::UpdateDepthStencilState() {
auto& regs = liverpool->regs;
const auto cmdbuf = scheduler.CommandBuffer();
void Rasterizer::UpdateDepthStencilState() const {
const auto& regs = liverpool->regs;
auto& dynamic_state = scheduler.GetDynamicState();
bool depth_test = regs.depth_control.depth_enable && regs.depth_buffer.DepthValid();
cmdbuf.setDepthTestEnableEXT(depth_test);
cmdbuf.setDepthWriteEnableEXT(regs.depth_control.depth_write_enable &&
!regs.depth_render_control.depth_clear_enable);
if (depth_test) {
cmdbuf.setDepthCompareOpEXT(LiverpoolToVK::CompareOp(regs.depth_control.depth_func));
const auto depth_test_enabled =
regs.depth_control.depth_enable && regs.depth_buffer.DepthValid();
dynamic_state.SetDepthTestEnabled(depth_test_enabled);
if (depth_test_enabled) {
dynamic_state.SetDepthWriteEnabled(regs.depth_control.depth_write_enable &&
!regs.depth_render_control.depth_clear_enable);
dynamic_state.SetDepthCompareOp(LiverpoolToVK::CompareOp(regs.depth_control.depth_func));
}
if (instance.IsDepthBoundsSupported()) {
cmdbuf.setDepthBoundsTestEnableEXT(regs.depth_control.depth_bounds_enable);
if (regs.depth_control.depth_bounds_enable) {
cmdbuf.setDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max);
}
const auto depth_bounds_test_enabled = regs.depth_control.depth_bounds_enable;
dynamic_state.SetDepthBoundsTestEnabled(depth_bounds_test_enabled);
if (depth_bounds_test_enabled) {
dynamic_state.SetDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max);
}
cmdbuf.setDepthBiasEnableEXT(regs.polygon_control.NeedsBias());
if (regs.polygon_control.enable_polygon_offset_front) {
cmdbuf.setDepthBias(regs.poly_offset.front_offset, regs.poly_offset.depth_bias,
regs.poly_offset.front_scale / 16.f);
} else if (regs.polygon_control.enable_polygon_offset_back) {
cmdbuf.setDepthBias(regs.poly_offset.back_offset, regs.poly_offset.depth_bias,
regs.poly_offset.back_scale / 16.f);
const auto depth_bias_enabled = regs.polygon_control.NeedsBias();
dynamic_state.SetDepthBiasEnabled(depth_bias_enabled);
if (depth_bias_enabled) {
const bool front = regs.polygon_control.enable_polygon_offset_front;
dynamic_state.SetDepthBias(
front ? regs.poly_offset.front_offset : regs.poly_offset.back_offset,
regs.poly_offset.depth_bias,
(front ? regs.poly_offset.front_scale : regs.poly_offset.back_scale) / 16.f);
}
cmdbuf.setStencilTestEnableEXT(regs.depth_control.stencil_enable &&
regs.depth_buffer.StencilValid());
if (regs.depth_control.stencil_enable) {
const auto front_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_front);
const auto front_pass_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_front);
const auto front_depth_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_front);
const auto front_compare_op = LiverpoolToVK::CompareOp(regs.depth_control.stencil_ref_func);
if (regs.depth_control.backface_enable) {
const auto back_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_back);
const auto back_pass_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_back);
const auto back_depth_fail_op =
LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_back);
const auto back_compare_op =
LiverpoolToVK::CompareOp(regs.depth_control.stencil_bf_func);
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFront, front_fail_op, front_pass_op,
front_depth_fail_op, front_compare_op);
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eBack, back_fail_op, back_pass_op,
back_depth_fail_op, back_compare_op);
} else {
cmdbuf.setStencilOpEXT(vk::StencilFaceFlagBits::eFrontAndBack, front_fail_op,
front_pass_op, front_depth_fail_op, front_compare_op);
}
const auto stencil_test_enabled =
regs.depth_control.stencil_enable && regs.depth_buffer.StencilValid();
dynamic_state.SetStencilTestEnabled(stencil_test_enabled);
if (stencil_test_enabled) {
const StencilOps front_ops{
.fail_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_front),
.pass_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_front),
.depth_fail_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_front),
.compare_op = LiverpoolToVK::CompareOp(regs.depth_control.stencil_ref_func),
};
const StencilOps back_ops = regs.depth_control.backface_enable ? StencilOps{
.fail_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_fail_back),
.pass_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zpass_back),
.depth_fail_op = LiverpoolToVK::StencilOp(regs.stencil_control.stencil_zfail_back),
.compare_op = LiverpoolToVK::CompareOp(regs.depth_control.stencil_bf_func),
} : front_ops;
dynamic_state.SetStencilOps(front_ops, back_ops);
const auto front = regs.stencil_ref_front;
const auto back = regs.stencil_ref_back;
if (front.stencil_test_val == back.stencil_test_val) {
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
front.stencil_test_val);
} else {
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFront, front.stencil_test_val);
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eBack, back.stencil_test_val);
}
if (front.stencil_write_mask == back.stencil_write_mask) {
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack,
front.stencil_write_mask);
} else {
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFront, front.stencil_write_mask);
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eBack, back.stencil_write_mask);
}
if (front.stencil_mask == back.stencil_mask) {
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack,
front.stencil_mask);
} else {
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFront, front.stencil_mask);
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eBack, back.stencil_mask);
}
const auto back =
regs.depth_control.backface_enable ? regs.stencil_ref_back : regs.stencil_ref_front;
dynamic_state.SetStencilReferences(front.stencil_test_val, back.stencil_test_val);
dynamic_state.SetStencilWriteMasks(front.stencil_write_mask, back.stencil_write_mask);
dynamic_state.SetStencilCompareMasks(front.stencil_mask, back.stencil_mask);
}
}
void Rasterizer::UpdatePrimitiveState() const {
const auto& regs = liverpool->regs;
auto& dynamic_state = scheduler.GetDynamicState();
const auto prim_restart = (regs.enable_primitive_restart & 1) != 0;
ASSERT_MSG(!prim_restart || regs.primitive_restart_index == 0xFFFF ||
regs.primitive_restart_index == 0xFFFFFFFF,
"Primitive restart index other than -1 is not supported yet");
const auto cull_mode = LiverpoolToVK::IsPrimitiveCulled(regs.primitive_type)
? LiverpoolToVK::CullMode(regs.polygon_control.CullingMode())
: vk::CullModeFlagBits::eNone;
const auto front_face = LiverpoolToVK::FrontFace(regs.polygon_control.front_face);
dynamic_state.SetPrimitiveRestartEnabled(prim_restart);
dynamic_state.SetCullMode(cull_mode);
dynamic_state.SetFrontFace(front_face);
}
void Rasterizer::ScopeMarkerBegin(const std::string_view& str, bool from_guest) {
if ((from_guest && !Config::getVkGuestMarkersEnabled()) ||
(!from_guest && !Config::getVkHostMarkersEnabled())) {

View file

@ -75,9 +75,10 @@ private:
void DepthStencilCopy(bool is_depth, bool is_stencil);
void EliminateFastClear();
void UpdateDynamicState(const GraphicsPipeline& pipeline);
void UpdateViewportScissorState();
void UpdateDepthStencilState();
void UpdateDynamicState(const GraphicsPipeline& pipeline) const;
void UpdateViewportScissorState() const;
void UpdateDepthStencilState() const;
void UpdatePrimitiveState() const;
bool FilterDraw();

View file

@ -97,6 +97,9 @@ void Scheduler::AllocateWorkerCommandBuffers() {
ASSERT_MSG(begin_result == vk::Result::eSuccess, "Failed to begin command buffer: {}",
vk::to_string(begin_result));
// Invalidate dynamic state so it gets applied to the new command buffer.
dynamic_state.Invalidate();
#if TRACY_GPU_ENABLED
auto* profiler_ctx = instance.GetProfilerContext();
if (profiler_ctx) {
@ -164,4 +167,151 @@ 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);
}
if (dirty_state.scissors) {
dirty_state.scissors = false;
cmdbuf.setScissorWithCountEXT(scissors);
}
if (dirty_state.depth_test_enabled) {
dirty_state.depth_test_enabled = false;
cmdbuf.setDepthTestEnableEXT(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);
}
if (depth_test_enabled && dirty_state.depth_compare_op) {
dirty_state.depth_compare_op = false;
cmdbuf.setDepthCompareOpEXT(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);
}
}
if (depth_bounds_test_enabled && dirty_state.depth_bounds) {
dirty_state.depth_bounds = false;
if (instance.IsDepthBoundsSupported()) {
cmdbuf.setDepthBounds(depth_bounds_min, depth_bounds_max);
}
}
if (dirty_state.depth_bias_enabled) {
dirty_state.depth_bias_enabled = false;
cmdbuf.setDepthBiasEnableEXT(depth_bias_enabled);
}
if (depth_bias_enabled && dirty_state.depth_bias) {
dirty_state.depth_bias = false;
cmdbuf.setDepthBias(depth_bias_constant, depth_bias_clamp, depth_bias_slope);
}
if (dirty_state.stencil_test_enabled) {
dirty_state.stencil_test_enabled = false;
cmdbuf.setStencilTestEnableEXT(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);
} 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);
}
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);
}
}
if (dirty_state.stencil_front_reference && dirty_state.stencil_back_reference &&
stencil_front_reference == stencil_back_reference) {
dirty_state.stencil_front_reference = false;
dirty_state.stencil_back_reference = false;
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFrontAndBack,
stencil_front_reference);
} else {
if (dirty_state.stencil_front_reference) {
dirty_state.stencil_front_reference = false;
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eFront,
stencil_front_reference);
}
if (dirty_state.stencil_back_reference) {
dirty_state.stencil_back_reference = false;
cmdbuf.setStencilReference(vk::StencilFaceFlagBits::eBack, stencil_back_reference);
}
}
if (dirty_state.stencil_front_write_mask && dirty_state.stencil_back_write_mask &&
stencil_front_write_mask == stencil_back_write_mask) {
dirty_state.stencil_front_write_mask = false;
dirty_state.stencil_back_write_mask = false;
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFrontAndBack,
stencil_front_write_mask);
} else {
if (dirty_state.stencil_front_write_mask) {
dirty_state.stencil_front_write_mask = false;
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eFront,
stencil_front_write_mask);
}
if (dirty_state.stencil_back_write_mask) {
dirty_state.stencil_back_write_mask = false;
cmdbuf.setStencilWriteMask(vk::StencilFaceFlagBits::eBack, stencil_back_write_mask);
}
}
if (dirty_state.stencil_front_compare_mask && dirty_state.stencil_back_compare_mask &&
stencil_front_compare_mask == stencil_back_compare_mask) {
dirty_state.stencil_front_compare_mask = false;
dirty_state.stencil_back_compare_mask = false;
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFrontAndBack,
stencil_front_compare_mask);
} else {
if (dirty_state.stencil_front_compare_mask) {
dirty_state.stencil_front_compare_mask = false;
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eFront,
stencil_front_compare_mask);
}
if (dirty_state.stencil_back_compare_mask) {
dirty_state.stencil_back_compare_mask = false;
cmdbuf.setStencilCompareMask(vk::StencilFaceFlagBits::eBack,
stencil_back_compare_mask);
}
}
}
if (dirty_state.primitive_restart_enable) {
dirty_state.primitive_restart_enable = false;
if (instance.IsPrimitiveRestartDisableSupported()) {
cmdbuf.setPrimitiveRestartEnableEXT(primitive_restart_enable);
}
}
if (dirty_state.cull_mode) {
dirty_state.cull_mode = false;
cmdbuf.setCullModeEXT(cull_mode);
}
if (dirty_state.front_face) {
dirty_state.front_face = false;
cmdbuf.setFrontFaceEXT(front_face);
}
if (dirty_state.blend_constants) {
dirty_state.blend_constants = false;
cmdbuf.setBlendConstants(blend_constants);
}
if (dirty_state.color_write_masks) {
dirty_state.color_write_masks = false;
if (instance.IsDynamicColorWriteMaskSupported()) {
cmdbuf.setColorWriteMaskEXT(0, color_write_masks);
}
}
}
} // namespace Vulkan

View file

@ -7,6 +7,7 @@
#include <boost/container/static_vector.hpp>
#include "common/types.h"
#include "common/unique_function.h"
#include "video_core/amdgpu/liverpool.h"
#include "video_core/renderer_vulkan/vk_master_semaphore.h"
#include "video_core/renderer_vulkan/vk_resource_pool.h"
@ -55,6 +56,248 @@ struct SubmitInfo {
}
};
using Viewports = boost::container::static_vector<vk::Viewport, AmdGpu::Liverpool::NumViewports>;
using Scissors = boost::container::static_vector<vk::Rect2D, AmdGpu::Liverpool::NumViewports>;
using ColorWriteMasks = std::array<vk::ColorComponentFlags, AmdGpu::Liverpool::NumColorBuffers>;
struct StencilOps {
vk::StencilOp fail_op{};
vk::StencilOp pass_op{};
vk::StencilOp depth_fail_op{};
vk::CompareOp compare_op{};
bool operator==(const StencilOps& other) const {
return fail_op == other.fail_op && pass_op == other.pass_op &&
depth_fail_op == other.depth_fail_op && compare_op == other.compare_op;
}
};
struct DynamicState {
struct {
bool viewports : 1;
bool scissors : 1;
bool depth_test_enabled : 1;
bool depth_write_enabled : 1;
bool depth_compare_op : 1;
bool depth_bounds_test_enabled : 1;
bool depth_bounds : 1;
bool depth_bias_enabled : 1;
bool depth_bias : 1;
bool stencil_test_enabled : 1;
bool stencil_front_ops : 1;
bool stencil_front_reference : 1;
bool stencil_front_write_mask : 1;
bool stencil_front_compare_mask : 1;
bool stencil_back_ops : 1;
bool stencil_back_reference : 1;
bool stencil_back_write_mask : 1;
bool stencil_back_compare_mask : 1;
bool primitive_restart_enable : 1;
bool cull_mode : 1;
bool front_face : 1;
bool blend_constants : 1;
bool color_write_masks : 1;
} dirty_state{};
Viewports viewports{};
Scissors scissors{};
bool depth_test_enabled{};
bool depth_write_enabled{};
vk::CompareOp depth_compare_op{};
bool depth_bounds_test_enabled{};
float depth_bounds_min{};
float depth_bounds_max{};
bool depth_bias_enabled{};
float depth_bias_constant{};
float depth_bias_clamp{};
float depth_bias_slope{};
bool stencil_test_enabled{};
StencilOps stencil_front_ops{};
u32 stencil_front_reference{};
u32 stencil_front_write_mask{};
u32 stencil_front_compare_mask{};
StencilOps stencil_back_ops{};
u32 stencil_back_reference{};
u32 stencil_back_write_mask{};
u32 stencil_back_compare_mask{};
bool primitive_restart_enable{};
vk::CullModeFlags cull_mode{};
vk::FrontFace front_face{};
float blend_constants[4]{};
ColorWriteMasks color_write_masks{};
/// Commits the dynamic state to the provided command buffer.
void Commit(const Instance& instance, const vk::CommandBuffer& cmdbuf);
/// Invalidates all dynamic state to be flushed into the next command buffer.
void Invalidate() {
std::memset(&dirty_state, 0xFF, sizeof(dirty_state));
}
void SetViewports(const Viewports& viewports_) {
if (!std::ranges::equal(viewports, viewports_)) {
viewports = viewports_;
dirty_state.viewports = true;
}
}
void SetScissors(const Scissors& scissors_) {
if (!std::ranges::equal(scissors, scissors_)) {
scissors = scissors_;
dirty_state.scissors = true;
}
}
void SetDepthTestEnabled(const bool enabled) {
if (depth_test_enabled != enabled) {
depth_test_enabled = enabled;
dirty_state.depth_test_enabled = true;
}
}
void SetDepthWriteEnabled(const bool enabled) {
if (depth_write_enabled != enabled) {
depth_write_enabled = enabled;
dirty_state.depth_write_enabled = true;
}
}
void SetDepthCompareOp(const vk::CompareOp compare_op) {
if (depth_compare_op != compare_op) {
depth_compare_op = compare_op;
dirty_state.depth_compare_op = true;
}
}
void SetDepthBoundsTestEnabled(const bool enabled) {
if (depth_bounds_test_enabled != enabled) {
depth_bounds_test_enabled = enabled;
dirty_state.depth_bounds_test_enabled = true;
}
}
void SetDepthBounds(const float min, const float max) {
if (depth_bounds_min != min || depth_bounds_max != max) {
depth_bounds_min = min;
depth_bounds_max = max;
dirty_state.depth_bounds = true;
}
}
void SetDepthBiasEnabled(const bool enabled) {
if (depth_bias_enabled != enabled) {
depth_bias_enabled = enabled;
dirty_state.depth_bias_enabled = true;
}
}
void SetDepthBias(const float constant, const float clamp, const float slope) {
if (depth_bias_constant != constant || depth_bias_clamp != clamp ||
depth_bias_slope != slope) {
depth_bias_constant = constant;
depth_bias_clamp = clamp;
depth_bias_slope = slope;
dirty_state.depth_bias = true;
}
}
void SetStencilTestEnabled(const bool enabled) {
if (stencil_test_enabled != enabled) {
stencil_test_enabled = enabled;
dirty_state.stencil_test_enabled = true;
}
}
void SetStencilOps(const StencilOps& front_ops, const StencilOps& back_ops) {
if (stencil_front_ops != front_ops) {
stencil_front_ops = front_ops;
dirty_state.stencil_front_ops = true;
}
if (stencil_back_ops != back_ops) {
stencil_back_ops = back_ops;
dirty_state.stencil_back_ops = true;
}
}
void SetStencilReferences(const u32 front_reference, const u32 back_reference) {
if (stencil_front_reference != front_reference) {
stencil_front_reference = front_reference;
dirty_state.stencil_front_reference = true;
}
if (stencil_back_reference != back_reference) {
stencil_back_reference = back_reference;
dirty_state.stencil_back_reference = true;
}
}
void SetStencilWriteMasks(const u32 front_write_mask, const u32 back_write_mask) {
if (stencil_front_write_mask != front_write_mask) {
stencil_front_write_mask = front_write_mask;
dirty_state.stencil_front_write_mask = true;
}
if (stencil_back_write_mask != back_write_mask) {
stencil_back_write_mask = back_write_mask;
dirty_state.stencil_back_write_mask = true;
}
}
void SetStencilCompareMasks(const u32 front_compare_mask, const u32 back_compare_mask) {
if (stencil_front_compare_mask != front_compare_mask) {
stencil_front_compare_mask = front_compare_mask;
dirty_state.stencil_front_compare_mask = true;
}
if (stencil_back_compare_mask != back_compare_mask) {
stencil_back_compare_mask = back_compare_mask;
dirty_state.stencil_back_compare_mask = true;
}
}
void SetPrimitiveRestartEnabled(const bool enabled) {
if (primitive_restart_enable != enabled) {
primitive_restart_enable = enabled;
dirty_state.primitive_restart_enable = true;
}
}
void SetCullMode(const vk::CullModeFlags cull_mode_) {
if (cull_mode != cull_mode_) {
cull_mode = cull_mode_;
dirty_state.cull_mode = true;
}
}
void SetFrontFace(const vk::FrontFace front_face_) {
if (front_face != front_face_) {
front_face = front_face_;
dirty_state.front_face = true;
}
}
void SetBlendConstants(const float blend_constants_[4]) {
if (!std::equal(blend_constants, std::end(blend_constants), blend_constants_)) {
std::memcpy(blend_constants, blend_constants_, sizeof(blend_constants));
dirty_state.blend_constants = true;
}
}
void SetColorWriteMasks(const ColorWriteMasks& color_write_masks_) {
if (!std::ranges::equal(color_write_masks, color_write_masks_)) {
color_write_masks = color_write_masks_;
dirty_state.color_write_masks = true;
}
}
};
class Scheduler {
public:
explicit Scheduler(const Instance& instance);
@ -81,6 +324,10 @@ public:
return render_state;
}
DynamicState& GetDynamicState() {
return dynamic_state;
}
/// Returns the current command buffer.
vk::CommandBuffer CommandBuffer() const {
return current_cmdbuf;
@ -125,6 +372,7 @@ private:
};
std::queue<PendingOp> pending_ops;
RenderState render_state;
DynamicState dynamic_state;
bool is_rendering = false;
tracy::VkCtxScope* profiler_scope{};
};