mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63ee30cbb3 | ||
|
|
20241f301b | ||
|
|
61c653c49c | ||
|
|
a7f4f992e1 | ||
|
|
daa9953d40 | ||
|
|
4771198c30 | ||
|
|
d8f3717119 | ||
|
|
33ab6fd09b | ||
|
|
1391e1339e | ||
|
|
2f2614737a | ||
|
|
85a62427f9 | ||
|
|
8fd91cb7df | ||
|
|
c5820a4f54 | ||
|
|
572eae596c | ||
|
|
6f3c189129 | ||
|
|
7a0017bd40 | ||
|
|
74f840f66b | ||
|
|
4a7c194157 | ||
|
|
116eb6dc5b | ||
|
|
0bab3c74ea | ||
|
|
6328de43e3 | ||
|
|
5becdc9ab5 | ||
|
|
26b6394b67 | ||
|
|
1b6086ab62 | ||
|
|
87a4536a2e | ||
|
|
d20b897ac8 | ||
|
|
6f26b064b9 | ||
|
|
3a2c78d17c | ||
|
|
19d375b4bd | ||
|
|
8162461618 | ||
|
|
0cadc3189c | ||
|
|
e971a9ebf5 | ||
|
|
19f85713ce |
@@ -86,5 +86,5 @@ SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Cpp11
|
||||
TabWidth: 4
|
||||
UseTab: ForContinuationAndIndentation
|
||||
UseTab: AlignWithSpaces
|
||||
...
|
||||
|
||||
30
.github/workflows/scripts/linux/appimage-qt.sh
vendored
30
.github/workflows/scripts/linux/appimage-qt.sh
vendored
@@ -41,8 +41,13 @@ BINARY=pcsx2-qt
|
||||
APPDIRNAME=PCSX2.AppDir
|
||||
STRIP=strip
|
||||
|
||||
# Need both libharfbuzz.so and libharfbuzz.so.0 for bundled libs
|
||||
|
||||
declare -a MANUAL_LIBS=(
|
||||
"libshaderc_shared.so.1"
|
||||
"libharfbuzz.so.0"
|
||||
"libharfbuzz.so"
|
||||
"libfreetype.so.6"
|
||||
)
|
||||
|
||||
declare -a REMOVE_LIBS=(
|
||||
@@ -75,22 +80,29 @@ fi
|
||||
OUTDIR=$(realpath "./$APPDIRNAME")
|
||||
rm -fr "$OUTDIR"
|
||||
|
||||
# Our deps build dosn't create libharfbuzz.so.0, so we have to symlink it here
|
||||
hbpath=$(find "$DEPSDIR" -name "libharfbuzz.so")
|
||||
if [ ! -f "$hbpath" ]; then
|
||||
echo "Missing harfbuzz. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$hbpath.0" ]; then
|
||||
echo "Symlinking libharfbuzz.so.0"
|
||||
ln -s "$hbpath" "$hbpath.0"
|
||||
fi
|
||||
|
||||
echo "Locating extra libraries..."
|
||||
EXTRA_LIBS_ARGS=""
|
||||
EXTRA_LIBS_ARGS=()
|
||||
for lib in "${MANUAL_LIBS[@]}"; do
|
||||
srcpath=$(find "$DEPSDIR" -name "$lib")
|
||||
if [ ! -f "$srcpath" ]; then
|
||||
echo "Missinge extra library $lib. Exiting."
|
||||
echo "Missing extra library $lib. Exiting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Found $lib at $srcpath."
|
||||
|
||||
if [ "$EXTRA_LIBS_ARGS" == "" ]; then
|
||||
EXTRA_LIBS_ARGS="--library=$srcpath"
|
||||
else
|
||||
EXTRA_LIBS_ARGS="$EXTRA_LIBS_ARGS,$srcpath"
|
||||
fi
|
||||
EXTRA_LIBS_ARGS+=( "--library=$srcpath" )
|
||||
done
|
||||
|
||||
# Why the nastyness? linuxdeploy strips our main binary, and there's no option to turn it off.
|
||||
@@ -122,7 +134,7 @@ EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so" \
|
||||
DEPLOY_PLATFORM_THEMES="1" \
|
||||
QMAKE="$DEPSDIR/bin/qmake" \
|
||||
NO_STRIP="1" \
|
||||
$LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/pcsx2-qt" $EXTRA_LIBS_ARGS \
|
||||
$LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/pcsx2-qt" ${EXTRA_LIBS_ARGS[@]} \
|
||||
--desktop-file="net.pcsx2.PCSX2.desktop" --icon-file="PCSX2.png"
|
||||
|
||||
echo "Copying resources into AppDir..."
|
||||
|
||||
@@ -14,16 +14,18 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
|
||||
INSTALLDIR="$PWD/$INSTALLDIR"
|
||||
fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=11.2.0
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.1
|
||||
LIBPNG=1.6.50
|
||||
LIBWEBP=1.5.0
|
||||
SDL=SDL3-3.2.18
|
||||
LIBWEBP=1.6.0
|
||||
SDL=SDL3-3.2.20
|
||||
QT=6.9.1
|
||||
LZ4=1.10.0
|
||||
ZSTD=1.5.7
|
||||
KDDOCKWIDGETS=2.2.3
|
||||
PLUTOVG=1.1.0
|
||||
PLUTOVG=1.3.0
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
SHADERC=2025.3
|
||||
@@ -35,11 +37,13 @@ mkdir -p deps-build
|
||||
cd deps-build
|
||||
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
|
||||
aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
1a775bde924397a8e0c08bfda198926c17be859d0288ad0dec1dea1b2ee04f8f $SDL.tar.gz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67 $SDL.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
40caedbf83cc9a1959610830563565889878bc95f115868bbf545d1914acf28e qtbase-everywhere-src-$QT.tar.xz
|
||||
@@ -53,11 +57,13 @@ a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADE
|
||||
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
8aa9860519c407890668c29998e8bb88896ef6a2e6d7ce5ac1e57f18d79e1525 plutovg-$PLUTOVG.tar.gz
|
||||
4b08587d782f6858e6cb815b455fd7238f45190a57094857a3123883ecb595eb plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
-o "freetype-$FREETYPE.tar.xz" "https://sourceforge.net/projects/freetype/files/freetype2/$FREETYPE/freetype-$FREETYPE.tar.xz/download" \
|
||||
-o "harfbuzz-$HARFBUZZ.tar.gz" "https://github.com/harfbuzz/harfbuzz/archive/refs/tags/$HARFBUZZ.tar.gz" \
|
||||
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.zip" \
|
||||
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$LIBPNG/libpng-$LIBPNG.tar.xz" \
|
||||
@@ -137,6 +143,33 @@ cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building FreeType without HarfBuzz..."
|
||||
rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_DISABLE_HARFBUZZ=TRUE -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building HarfBuzz..."
|
||||
rm -fr "harfbuzz-$HARFBUZZ"
|
||||
tar xf "harfbuzz-$HARFBUZZ.tar.gz"
|
||||
cd "harfbuzz-$HARFBUZZ"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DHB_BUILD_UTILS=OFF -DHB_HAVE_FREETYPE=ON -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building FreeType with HarfBuzz..."
|
||||
rm -fr "freetype-$FREETYPE"
|
||||
tar xf "freetype-$FREETYPE.tar.xz"
|
||||
cd "freetype-$FREETYPE"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DFT_REQUIRE_ZLIB=ON -DFT_REQUIRE_PNG=ON -DFT_DISABLE_BZIP2=TRUE -DFT_DISABLE_BROTLI=TRUE -DFT_REQUIRE_HARFBUZZ=TRUE -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
echo "Building SDL..."
|
||||
rm -fr "$SDL"
|
||||
tar xf "$SDL.tar.gz"
|
||||
@@ -240,7 +273,7 @@ echo "Building PlutoSVG..."
|
||||
rm -fr "plutosvg-$PLUTOSVG"
|
||||
tar xf "plutosvg-$PLUTOSVG.tar.gz"
|
||||
cd "plutosvg-$PLUTOSVG"
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=OFF -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build -G Ninja
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DBUILD_SHARED_LIBS=ON -DPLUTOSVG_ENABLE_FREETYPE=ON -DPLUTOSVG_BUILD_EXAMPLES=OFF -B build -G Ninja
|
||||
cmake --build build --parallel
|
||||
ninja -C build install
|
||||
cd ..
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.18.tar.gz",
|
||||
"sha256": "1a775bde924397a8e0c08bfda198926c17be859d0288ad0dec1dea1b2ee04f8f"
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.20.tar.gz",
|
||||
"sha256": "467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/sammycage/plutovg.git",
|
||||
"tag": "v1.1.0",
|
||||
"commit": "1a8412d0574c4345dd7ef8a91ce7b58c7dcfe253"
|
||||
"tag": "v1.3.0",
|
||||
"commit": "1596f459d6796b37f3f6d610ce598de2403350b5"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"app-id": "net.pcsx2.PCSX2",
|
||||
"runtime": "org.kde.Platform",
|
||||
"runtime-version": "6.8",
|
||||
"runtime-version": "6.9",
|
||||
"sdk": "org.kde.Sdk",
|
||||
"sdk-extensions": [
|
||||
"org.freedesktop.Sdk.Extension.llvm18"
|
||||
|
||||
@@ -40,17 +40,17 @@ fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=11.2.0
|
||||
SDL=SDL3-3.2.18
|
||||
SDL=SDL3-3.2.20
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.50
|
||||
LIBJPEGTURBO=3.1.1
|
||||
LIBWEBP=1.5.0
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=6.0
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.7.3
|
||||
KDDOCKWIDGETS=2.2.3
|
||||
PLUTOVG=1.1.0
|
||||
PLUTOVG=1.3.0
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
SHADERC=2025.3
|
||||
@@ -79,11 +79,11 @@ CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
1a775bde924397a8e0c08bfda198926c17be859d0288ad0dec1dea1b2ee04f8f $SDL.tar.gz
|
||||
467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67 $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
@@ -97,7 +97,7 @@ a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADE
|
||||
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
8aa9860519c407890668c29998e8bb88896ef6a2e6d7ce5ac1e57f18d79e1525 plutovg-$PLUTOVG.tar.gz
|
||||
4b08587d782f6858e6cb815b455fd7238f45190a57094857a3123883ecb595eb plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
EOF
|
||||
|
||||
|
||||
@@ -22,17 +22,17 @@ fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=11.2.0
|
||||
SDL=SDL3-3.2.18
|
||||
SDL=SDL3-3.2.20
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.50
|
||||
LIBJPEGTURBO=3.1.1
|
||||
LIBWEBP=1.5.0
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=6.0
|
||||
MOLTENVK=1.2.9
|
||||
QT=6.7.3
|
||||
KDDOCKWIDGETS=2.2.3
|
||||
PLUTOVG=1.1.0
|
||||
PLUTOVG=1.3.0
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
SHADERC=2025.3
|
||||
@@ -59,11 +59,11 @@ CMAKE_COMMON=(
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
1a775bde924397a8e0c08bfda198926c17be859d0288ad0dec1dea1b2ee04f8f $SDL.tar.gz
|
||||
467600ae090dd28616fa37369faf4e3143198ff1da37729b552137e47f751a67 $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
4df396518620a7aa3651443e87d1b2862e4e88cad135a8b93423e01706232307 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
f415a09385030c6510a936155ce211f617c31506db5fbc563e804345f1ecf56e v$MOLTENVK.tar.gz
|
||||
@@ -77,7 +77,7 @@ a8e4a25e5c2686fd36981e527ed05e451fcfc226bddf350f4e76181371190937 shaderc-$SHADE
|
||||
c2225a49c3d7efa5c4f4ce4a6b42081e6ea3daca376f3353d9d7c2722d77a28a shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
44d1005880c583fc00a0fb41c839214c68214b000ea8dcb54d352732fee600ff shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
8aa9860519c407890668c29998e8bb88896ef6a2e6d7ce5ac1e57f18d79e1525 plutovg-$PLUTOVG.tar.gz
|
||||
4b08587d782f6858e6cb815b455fd7238f45190a57094857a3123883ecb595eb plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
EOF
|
||||
|
||||
|
||||
@@ -46,16 +46,16 @@ set FREETYPE=2.13.3
|
||||
set HARFBUZZ=11.2.0
|
||||
set LIBJPEGTURBO=3.1.1
|
||||
set LIBPNG=1650
|
||||
set SDL=SDL3-3.2.18
|
||||
set SDL=SDL3-3.2.20
|
||||
set QT=6.9.1
|
||||
set QTMINOR=6.9
|
||||
set LZ4=1.10.0
|
||||
set WEBP=1.5.0
|
||||
set WEBP=1.6.0
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.2.3
|
||||
set PLUTOVG=1.1.0
|
||||
set PLUTOVG=1.3.0
|
||||
set PLUTOSVG=0.0.7
|
||||
|
||||
set SHADERC=2025.3
|
||||
@@ -67,8 +67,8 @@ call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 850cb5e38e21106c0abba86c5b73f8f74b9a32d7725505901d081080b0d3f0b3 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1650.zip 4be6938313b08d5921f9dede13f2789b653c96f4f8595d92ff3f09c9320e51c7 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 208028b3b6225b3c9eae3942e50ed243d8798b4b3a56b98a59b3f7e37baa55fd || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" d76454913ea6f5f38856fbf00578d8e39daf842887f3396c95608414680250f7 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" efa6d8ef9f7ae0fd9f7d280fbff574d71882b60a357ae639e516dc173cf26986 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 8439d3394bc380fd17a920ee96df1d2272bf8d3490871d948ef750f95e0ded06 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" a8f90c768b54e28d61e02c1229b74a2b834e9852af523e5c70bcd2ae4c34a772 || goto error
|
||||
@@ -78,7 +78,7 @@ call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 1ba8e5b48f3b4d47d2de7121529d448532200fa36d9ed21f93909f6eb03f61cb || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 83b2cd6230909a8d586518f49e79e4a1b1e9fab3847db6a678ec9d2dacab052a || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 5153e6b3603a253e6f86dc0b1eb5b80d1dce849ceef628369942587e86582cbb || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
|
||||
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 77d2425458bca62c16b1ed49ed02de4c4114a113781bd94c1961b273bdca00fb || goto error
|
||||
|
||||
@@ -44,16 +44,16 @@ set FREETYPE=2.13.3
|
||||
set HARFBUZZ=11.2.0
|
||||
set LIBJPEGTURBO=3.1.1
|
||||
set LIBPNG=1650
|
||||
set SDL=SDL3-3.2.18
|
||||
set SDL=SDL3-3.2.20
|
||||
set QT=6.9.1
|
||||
set QTMINOR=6.9
|
||||
set LZ4=1.10.0
|
||||
set WEBP=1.5.0
|
||||
set WEBP=1.6.0
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.2.3
|
||||
set PLUTOVG=1.1.0
|
||||
set PLUTOVG=1.3.0
|
||||
set PLUTOSVG=0.0.7
|
||||
|
||||
set SHADERC=2025.3
|
||||
@@ -65,8 +65,8 @@ call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 850cb5e38e21106c0abba86c5b73f8f74b9a32d7725505901d081080b0d3f0b3 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1650.zip 4be6938313b08d5921f9dede13f2789b653c96f4f8595d92ff3f09c9320e51c7 || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" aadc97ea91f6ef078b0ae3a62bba69e008d9a7db19b34e4ac973b19b71b4217c || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" 7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 208028b3b6225b3c9eae3942e50ed243d8798b4b3a56b98a59b3f7e37baa55fd || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" d76454913ea6f5f38856fbf00578d8e39daf842887f3396c95608414680250f7 || goto error
|
||||
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" efa6d8ef9f7ae0fd9f7d280fbff574d71882b60a357ae639e516dc173cf26986 || goto error
|
||||
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 8439d3394bc380fd17a920ee96df1d2272bf8d3490871d948ef750f95e0ded06 || goto error
|
||||
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" a8f90c768b54e28d61e02c1229b74a2b834e9852af523e5c70bcd2ae4c34a772 || goto error
|
||||
@@ -76,7 +76,7 @@ call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://zlib.net/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 1ba8e5b48f3b4d47d2de7121529d448532200fa36d9ed21f93909f6eb03f61cb || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 83b2cd6230909a8d586518f49e79e4a1b1e9fab3847db6a678ec9d2dacab052a || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 5153e6b3603a253e6f86dc0b1eb5b80d1dce849ceef628369942587e86582cbb || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
|
||||
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 77d2425458bca62c16b1ed49ed02de4c4114a113781bd94c1961b273bdca00fb || goto error
|
||||
|
||||
4
3rdparty/imgui/include/imconfig.h
vendored
4
3rdparty/imgui/include/imconfig.h
vendored
@@ -66,7 +66,7 @@
|
||||
//#define IMGUI_USE_LEGACY_CRC32_ADLER
|
||||
|
||||
//---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...)
|
||||
//#define IMGUI_USE_WCHAR32
|
||||
#define IMGUI_USE_WCHAR32
|
||||
|
||||
//---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version
|
||||
// By default the embedded implementations are declared static and not available outside of Dear ImGui sources files.
|
||||
@@ -91,7 +91,7 @@
|
||||
// - plutosvg is currently easier to install, as e.g. it is part of vcpkg. It will support more fonts and may load them faster. See misc/freetype/README for instructions.
|
||||
// - Both require headers to be available in the include path + program to be linked with the library code (not provided).
|
||||
// - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement)
|
||||
//#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
|
||||
#define IMGUI_ENABLE_FREETYPE_PLUTOSVG
|
||||
//#define IMGUI_ENABLE_FREETYPE_LUNASVG
|
||||
|
||||
//---- Use stb_truetype to build and rasterize the font atlas (default)
|
||||
|
||||
@@ -2402,6 +2402,7 @@ SCAJ-20177:
|
||||
textureInsideRT: 1 # Required for swirl battle transition.
|
||||
nativeScaling: 2 # Fixes depth of field effects and bloom.
|
||||
roundSprite: 1 # Fixes lines in transitions.
|
||||
autoFlush: 2 # Fixes shadow rendering in certain scenarios when using DirectX.
|
||||
SCAJ-20178:
|
||||
name: "Ape Escape - Million Monkeys"
|
||||
region: "NTSC-Unk"
|
||||
@@ -2521,6 +2522,7 @@ SCAJ-20197:
|
||||
textureInsideRT: 1 # Required for swirl battle transition.
|
||||
nativeScaling: 2 # Fixes depth of field effects and bloom.
|
||||
roundSprite: 1 # Fixes lines in transitions.
|
||||
autoFlush: 2 # Fixes shadow rendering in certain scenarios when using DirectX.
|
||||
SCAJ-20198:
|
||||
name: "Everybody's Tennis [PlayStation2 the Best]"
|
||||
region: "NTSC-Unk"
|
||||
@@ -3798,8 +3800,11 @@ SCED-52461:
|
||||
SCED-52491:
|
||||
name: "Athens 2004"
|
||||
region: "PAL-M6"
|
||||
SCED-52496:
|
||||
name: "This Is Football 2004 [Demo]"
|
||||
region: "PAL-M4"
|
||||
SCED-52497:
|
||||
name: "This is Football 2004"
|
||||
name: "This Is Football 2004 [Demo]"
|
||||
region: "PAL-M4"
|
||||
SCED-52549:
|
||||
name: "Official PlayStation 2 Magazine Demo 47"
|
||||
@@ -7639,6 +7644,7 @@ SCKA-20079:
|
||||
textureInsideRT: 1 # Required for swirl battle transition.
|
||||
nativeScaling: 2 # Fixes depth of field effects and bloom.
|
||||
roundSprite: 1 # Fixes lines in transitions.
|
||||
autoFlush: 2 # Fixes shadow rendering in certain scenarios when using DirectX.
|
||||
SCKA-20081:
|
||||
name: "Tekken 5 [PlayStation 2 Big Hit Series]"
|
||||
region: "NTSC-K"
|
||||
@@ -26209,7 +26215,7 @@ SLES-54434:
|
||||
name: "Babe"
|
||||
region: "PAL-A"
|
||||
SLES-54435:
|
||||
name: "Babe"
|
||||
name: "Casper and the Ghostly Trio"
|
||||
region: "PAL-A"
|
||||
SLES-54436:
|
||||
name: "Jumanji"
|
||||
@@ -26876,6 +26882,7 @@ SLES-54644:
|
||||
textureInsideRT: 1 # Required for swirl battle transition.
|
||||
nativeScaling: 2 # Fixes depth of field effects and bloom.
|
||||
roundSprite: 1 # Fixes lines in transitions.
|
||||
autoFlush: 2 # Fixes shadow rendering in certain scenarios when using DirectX.
|
||||
SLES-54645:
|
||||
name: "Valkyrie Profile 2 - Silmeria"
|
||||
region: "PAL-F"
|
||||
@@ -26886,6 +26893,7 @@ SLES-54645:
|
||||
textureInsideRT: 1 # Required for swirl battle transition.
|
||||
nativeScaling: 2 # Fixes depth of field effects and bloom.
|
||||
roundSprite: 1 # Fixes lines in transitions.
|
||||
autoFlush: 2 # Fixes shadow rendering in certain scenarios when using DirectX.
|
||||
SLES-54646:
|
||||
name: "Valkyrie Profile 2 - Silmeria"
|
||||
region: "PAL-G"
|
||||
@@ -26897,6 +26905,7 @@ SLES-54646:
|
||||
textureInsideRT: 1 # Required for swirl battle transition.
|
||||
nativeScaling: 2 # Fixes depth of field effects and bloom.
|
||||
roundSprite: 1 # Fixes lines in transitions.
|
||||
autoFlush: 2 # Fixes shadow rendering in certain scenarios when using DirectX.
|
||||
SLES-54647:
|
||||
name: "Valkyrie Profile 2 - Silmeria"
|
||||
region: "PAL-I"
|
||||
@@ -26908,6 +26917,7 @@ SLES-54647:
|
||||
textureInsideRT: 1 # Required for swirl battle transition.
|
||||
nativeScaling: 2 # Fixes depth of field effects and bloom.
|
||||
roundSprite: 1 # Fixes lines in transitions.
|
||||
autoFlush: 2 # Fixes shadow rendering in certain scenarios when using DirectX.
|
||||
SLES-54648:
|
||||
name: "Valkyrie Profile 2 - Silmeria"
|
||||
region: "PAL-S"
|
||||
@@ -26918,6 +26928,7 @@ SLES-54648:
|
||||
textureInsideRT: 1 # Required for swirl battle transition.
|
||||
nativeScaling: 2 # Fixes depth of field effects and bloom.
|
||||
roundSprite: 1 # Fixes lines in transitions.
|
||||
autoFlush: 2 # Fixes shadow rendering in certain scenarios when using DirectX.
|
||||
SLES-54653:
|
||||
name: "Freak Out - Extreme Freeride"
|
||||
region: "PAL-M5"
|
||||
@@ -48427,6 +48438,7 @@ SLPM-66419:
|
||||
textureInsideRT: 1 # Required for swirl battle transition.
|
||||
nativeScaling: 2 # Fixes depth of field effects and bloom.
|
||||
roundSprite: 1 # Fixes lines in transitions.
|
||||
autoFlush: 2 # Fixes shadow rendering in certain scenarios when using DirectX.
|
||||
SLPM-66420:
|
||||
name: "フロントミッション4 [Ultimate Hits]"
|
||||
name-sort: "ふろんとみっしょん4 [Ultimate Hits]"
|
||||
@@ -50742,6 +50754,7 @@ SLPM-66782:
|
||||
textureInsideRT: 1 # Required for swirl battle transition.
|
||||
nativeScaling: 2 # Fixes depth of field effects and bloom.
|
||||
roundSprite: 1 # Fixes lines in transitions.
|
||||
autoFlush: 2 # Fixes shadow rendering in certain scenarios when using DirectX.
|
||||
SLPM-66783:
|
||||
name: "アイドル雀士 スーチーパイⅣ 「完全限定版・コレクターズエディション」"
|
||||
name-sort: "あいどるじゃんし すーちーぱい4 [かんぜんげんていばん・これくたーずえでぃしょん]"
|
||||
@@ -70909,6 +70922,7 @@ SLUS-21452:
|
||||
textureInsideRT: 1 # Required for swirl battle transition.
|
||||
nativeScaling: 2 # Fixes depth of field effects and bloom.
|
||||
roundSprite: 1 # Fixes lines in transitions.
|
||||
autoFlush: 2 # Fixes shadow rendering in certain scenarios when using DirectX.
|
||||
SLUS-21453:
|
||||
name: "Meet the Robinsons"
|
||||
region: "NTSC-U"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
93
bin/resources/fonts/NotoColorEmoji-Regular-license
Normal file
93
bin/resources/fonts/NotoColorEmoji-Regular-license
Normal file
@@ -0,0 +1,93 @@
|
||||
Copyright 2021 Google Inc. All Rights Reserved.
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
https://openfontlicense.org
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
BIN
bin/resources/fonts/NotoColorEmoji-Regular.ttf
Normal file
BIN
bin/resources/fonts/NotoColorEmoji-Regular.ttf
Normal file
Binary file not shown.
@@ -822,7 +822,7 @@
|
||||
030000005e040000e302000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000005e040000ea02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000005e040000fd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000005e040000ff02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000005e040000ff02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000006f0e0000a802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
030000006f0e0000c802000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
03000000c62400003a54000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
|
||||
@@ -1824,6 +1824,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
060000005e040000120b00000b050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000120b00000d050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000120b00000f050000,Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
060000005e040000120b000011050000,Xbox Series X Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
050000005e040000130b000022050000,Xbox Series X Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000200b000013050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
050000005e040000200b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
|
||||
@@ -21,6 +21,7 @@ float4 ContrastSaturationBrightness(float4 color) // Ported to HLSL
|
||||
float brt = params.x;
|
||||
float con = params.y;
|
||||
float sat = params.z;
|
||||
float gam = params.w;
|
||||
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
@@ -34,8 +35,10 @@ float4 ContrastSaturationBrightness(float4 color) // Ported to HLSL
|
||||
float3 intensity = dot(brtColor, LumCoeff);
|
||||
float3 satColor = lerp(intensity, brtColor, sat);
|
||||
float3 conColor = lerp(AvgLumin, satColor, con);
|
||||
|
||||
color.rgb = conColor;
|
||||
|
||||
float3 csb = conColor;
|
||||
csb = pow(csb, 1.0 / gam);
|
||||
color.rgb = csb;
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ vec4 ContrastSaturationBrightness(vec4 color)
|
||||
float brt = params.x;
|
||||
float con = params.y;
|
||||
float sat = params.z;
|
||||
float gam = params.w;
|
||||
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
@@ -45,7 +46,10 @@ vec4 ContrastSaturationBrightness(vec4 color)
|
||||
vec3 satColor = mix(intensity, brtColor, sat);
|
||||
vec3 conColor = mix(AvgLumin, satColor, con);
|
||||
|
||||
color.rgb = conColor;
|
||||
vec3 csb = conColor;
|
||||
csb = pow(csb, vec3(1.0 / gam));
|
||||
color.rgb = csb;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ vec4 ContrastSaturationBrightness(vec4 color)
|
||||
float brt = params.x;
|
||||
float con = params.y;
|
||||
float sat = params.z;
|
||||
float gam = params.w;
|
||||
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
@@ -59,7 +60,9 @@ vec4 ContrastSaturationBrightness(vec4 color)
|
||||
vec3 satColor = mix(intensity, brtColor, sat);
|
||||
vec3 conColor = mix(AvgLumin, satColor, con);
|
||||
|
||||
color.rgb = conColor;
|
||||
vec3 csb = conColor;
|
||||
csb = pow(csb, vec3(1.0 / gam));
|
||||
color.rgb = csb;
|
||||
return color;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ find_package(Zstd 1.5.5 REQUIRED)
|
||||
find_package(LZ4 REQUIRED)
|
||||
find_package(WebP REQUIRED) # v1.3.2, spews an error on Linux because no pkg-config.
|
||||
find_package(SDL3 3.2.6 REQUIRED)
|
||||
find_package(Freetype 2.11.1 REQUIRED)
|
||||
find_package(Freetype 2.12 REQUIRED)
|
||||
find_package(plutovg 1.1.0 REQUIRED)
|
||||
find_package(plutosvg 0.0.7 REQUIRED)
|
||||
|
||||
|
||||
@@ -174,9 +174,6 @@ else()
|
||||
target_compile_definitions(common PRIVATE "HAS_LIBBACKTRACE=1")
|
||||
target_link_libraries(common PRIVATE libbacktrace::libbacktrace)
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
target_link_libraries(common PRIVATE cpuinfo)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_source_files_properties(PrecompiledHeader.cpp PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
@@ -206,6 +203,7 @@ target_link_libraries(common PRIVATE
|
||||
JPEG::JPEG
|
||||
PNG::PNG
|
||||
WebP::libwebp
|
||||
cpuinfo
|
||||
)
|
||||
|
||||
target_link_libraries(common PUBLIC
|
||||
|
||||
@@ -335,7 +335,7 @@ bool Log::SetFileOutputLevel(LOGLEVEL level, std::string path)
|
||||
|
||||
const bool was_enabled = (s_file_level > LOGLEVEL_NONE);
|
||||
const bool new_enabled = (level > LOGLEVEL_NONE && !path.empty());
|
||||
if (was_enabled != new_enabled || (new_enabled && path == s_file_path))
|
||||
if (was_enabled != new_enabled || (new_enabled && path != s_file_path))
|
||||
{
|
||||
if (new_enabled)
|
||||
{
|
||||
|
||||
@@ -271,7 +271,7 @@ std::vector<DarwinMisc::CPUClass> DarwinMisc::GetCPUClasses()
|
||||
}
|
||||
else if (std::optional<u32> physcpu = sysctlbyname_T<u32>("hw.physicalcpu"))
|
||||
{
|
||||
out.push_back({"Default", *physcpu, sysctlbyname_T<u32>("hw.logicalcpu").value_or(0)});
|
||||
out.push_back({"Default", *physcpu, sysctlbyname_T<u32>("hw.logicalcpu").value_or(*physcpu)});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -281,6 +281,35 @@ std::vector<DarwinMisc::CPUClass> DarwinMisc::GetCPUClasses()
|
||||
return out;
|
||||
}
|
||||
|
||||
static CPUInfo CalcCPUInfo()
|
||||
{
|
||||
CPUInfo out;
|
||||
char name[256];
|
||||
size_t name_size = sizeof(name);
|
||||
if (0 != sysctlbyname("machdep.cpu.brand_string", name, &name_size, nullptr, 0))
|
||||
strcpy(name, "Unknown");
|
||||
out.name = name;
|
||||
if (sysctlbyname_T<u32>("sysctl.proc_translated").value_or(0))
|
||||
out.name += " (Rosetta)";
|
||||
std::vector<DarwinMisc::CPUClass> classes = DarwinMisc::GetCPUClasses();
|
||||
out.num_clusters = static_cast<u32>(classes.size());
|
||||
out.num_big_cores = classes.empty() ? 0 : classes[0].num_physical;
|
||||
out.num_threads = classes.empty() ? 0 : classes[0].num_logical;
|
||||
out.num_small_cores = 0;
|
||||
for (std::size_t i = 1; i < classes.size(); i++)
|
||||
{
|
||||
out.num_small_cores += classes[i].num_physical;
|
||||
out.num_threads += classes[i].num_logical;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
const CPUInfo& GetCPUInfo()
|
||||
{
|
||||
static const CPUInfo info = CalcCPUInfo();
|
||||
return info;
|
||||
}
|
||||
|
||||
size_t HostSys::GetRuntimePageSize()
|
||||
{
|
||||
return sysctlbyname_T<u32>("hw.pagesize").value_or(0);
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
#include "Console.h"
|
||||
#include "VectorIntrin.h"
|
||||
|
||||
#ifndef __APPLE__
|
||||
#include "cpuinfo.h"
|
||||
#endif
|
||||
|
||||
static u32 PAUSE_TIME = 0;
|
||||
|
||||
static void MultiPause()
|
||||
@@ -135,3 +139,43 @@ void AbortWithMessage(const char* msg)
|
||||
#endif
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
// MacOS version is in DarwinMisc
|
||||
static CPUInfo CalcCPUInfo()
|
||||
{
|
||||
CPUInfo out;
|
||||
out.name = cpuinfo_get_package(0)->name;
|
||||
out.num_threads = cpuinfo_get_processors_count();
|
||||
out.num_clusters = cpuinfo_get_clusters_count();
|
||||
out.num_big_cores = 0;
|
||||
out.num_small_cores = 0;
|
||||
const cpuinfo_cluster* clusters = cpuinfo_get_clusters();
|
||||
uint64_t big_freq = 0;
|
||||
for (uint32_t i = 0; i < out.num_clusters; i++)
|
||||
{
|
||||
const cpuinfo_cluster& cluster = clusters[i];
|
||||
if (cluster.frequency > big_freq)
|
||||
{
|
||||
out.num_small_cores += out.num_big_cores;
|
||||
out.num_big_cores = cluster.core_count;
|
||||
big_freq = cluster.frequency;
|
||||
}
|
||||
else if (cluster.frequency == big_freq)
|
||||
{
|
||||
out.num_big_cores += cluster.core_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
out.num_small_cores += cluster.core_count;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
const CPUInfo& GetCPUInfo()
|
||||
{
|
||||
static const CPUInfo info = CalcCPUInfo();
|
||||
return info;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -192,6 +192,16 @@ extern const u32 SPIN_TIME_NS;
|
||||
|
||||
extern std::string GetOSVersionString();
|
||||
|
||||
struct CPUInfo {
|
||||
std::string name;
|
||||
u32 num_big_cores;
|
||||
u32 num_small_cores;
|
||||
u32 num_threads;
|
||||
u32 num_clusters;
|
||||
};
|
||||
|
||||
const CPUInfo& GetCPUInfo();
|
||||
|
||||
namespace Common
|
||||
{
|
||||
/// Enables or disables the screen saver from starting.
|
||||
|
||||
@@ -600,7 +600,7 @@ bool SmallStringBase::starts_with(const char* str, bool case_sensitive) const
|
||||
return false;
|
||||
|
||||
return (case_sensitive) ? (std::strncmp(str, m_buffer, other_length) == 0) :
|
||||
(CASE_N_COMPARE(str, m_buffer, other_length) == 0);
|
||||
(CASE_N_COMPARE(str, m_buffer, other_length) == 0);
|
||||
}
|
||||
|
||||
bool SmallStringBase::starts_with(const SmallStringBase& str, bool case_sensitive) const
|
||||
@@ -610,7 +610,7 @@ bool SmallStringBase::starts_with(const SmallStringBase& str, bool case_sensitiv
|
||||
return false;
|
||||
|
||||
return (case_sensitive) ? (std::strncmp(str.m_buffer, m_buffer, other_length) == 0) :
|
||||
(CASE_N_COMPARE(str.m_buffer, m_buffer, other_length) == 0);
|
||||
(CASE_N_COMPARE(str.m_buffer, m_buffer, other_length) == 0);
|
||||
}
|
||||
|
||||
bool SmallStringBase::starts_with(const std::string_view str, bool case_sensitive) const
|
||||
@@ -620,7 +620,7 @@ bool SmallStringBase::starts_with(const std::string_view str, bool case_sensitiv
|
||||
return false;
|
||||
|
||||
return (case_sensitive) ? (std::strncmp(str.data(), m_buffer, other_length) == 0) :
|
||||
(CASE_N_COMPARE(str.data(), m_buffer, other_length) == 0);
|
||||
(CASE_N_COMPARE(str.data(), m_buffer, other_length) == 0);
|
||||
}
|
||||
|
||||
bool SmallStringBase::starts_with(const std::string& str, bool case_sensitive) const
|
||||
@@ -630,7 +630,7 @@ bool SmallStringBase::starts_with(const std::string& str, bool case_sensitive) c
|
||||
return false;
|
||||
|
||||
return (case_sensitive) ? (std::strncmp(str.data(), m_buffer, other_length) == 0) :
|
||||
(CASE_N_COMPARE(str.data(), m_buffer, other_length) == 0);
|
||||
(CASE_N_COMPARE(str.data(), m_buffer, other_length) == 0);
|
||||
}
|
||||
|
||||
bool SmallStringBase::ends_with(const char* str, bool case_sensitive) const
|
||||
@@ -641,7 +641,7 @@ bool SmallStringBase::ends_with(const char* str, bool case_sensitive) const
|
||||
|
||||
u32 start_offset = m_length - other_length;
|
||||
return (case_sensitive) ? (std::strncmp(str, m_buffer + start_offset, other_length) == 0) :
|
||||
(CASE_N_COMPARE(str, m_buffer + start_offset, other_length) == 0);
|
||||
(CASE_N_COMPARE(str, m_buffer + start_offset, other_length) == 0);
|
||||
}
|
||||
|
||||
bool SmallStringBase::ends_with(const SmallStringBase& str, bool case_sensitive) const
|
||||
@@ -652,7 +652,7 @@ bool SmallStringBase::ends_with(const SmallStringBase& str, bool case_sensitive)
|
||||
|
||||
const u32 start_offset = m_length - other_length;
|
||||
return (case_sensitive) ? (std::strncmp(str.m_buffer, m_buffer + start_offset, other_length) == 0) :
|
||||
(CASE_N_COMPARE(str.m_buffer, m_buffer + start_offset, other_length) == 0);
|
||||
(CASE_N_COMPARE(str.m_buffer, m_buffer + start_offset, other_length) == 0);
|
||||
}
|
||||
|
||||
bool SmallStringBase::ends_with(const std::string_view str, bool case_sensitive) const
|
||||
@@ -663,7 +663,7 @@ bool SmallStringBase::ends_with(const std::string_view str, bool case_sensitive)
|
||||
|
||||
const u32 start_offset = m_length - other_length;
|
||||
return (case_sensitive) ? (std::strncmp(str.data(), m_buffer + start_offset, other_length) == 0) :
|
||||
(CASE_N_COMPARE(str.data(), m_buffer + start_offset, other_length) == 0);
|
||||
(CASE_N_COMPARE(str.data(), m_buffer + start_offset, other_length) == 0);
|
||||
}
|
||||
|
||||
bool SmallStringBase::ends_with(const std::string& str, bool case_sensitive) const
|
||||
@@ -674,7 +674,7 @@ bool SmallStringBase::ends_with(const std::string& str, bool case_sensitive) con
|
||||
|
||||
const u32 start_offset = m_length - other_length;
|
||||
return (case_sensitive) ? (std::strncmp(str.data(), m_buffer + start_offset, other_length) == 0) :
|
||||
(CASE_N_COMPARE(str.data(), m_buffer + start_offset, other_length) == 0);
|
||||
(CASE_N_COMPARE(str.data(), m_buffer + start_offset, other_length) == 0);
|
||||
}
|
||||
|
||||
void SmallStringBase::clear()
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\cpuinfo\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\fast_float\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\fmt\include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(SolutionDir)3rdparty\jpgd</AdditionalIncludeDirectories>
|
||||
@@ -191,4 +192,4 @@
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -47,16 +47,16 @@ AboutDialog::AboutDialog(QWidget* parent)
|
||||
m_ui.links->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||
m_ui.links->setText(QStringLiteral(
|
||||
R"(<a href="%1">%2</a> | <a href="%3">%4</a> | <a href="%5">%6</a> | <a href="%7">%8</a> | <a href="%9">%10</a>)")
|
||||
.arg(getWebsiteUrl())
|
||||
.arg(tr("Website"))
|
||||
.arg(getSupportForumsUrl())
|
||||
.arg(tr("Support Forums"))
|
||||
.arg(getGitHubRepositoryUrl())
|
||||
.arg(tr("GitHub Repository"))
|
||||
.arg(getLicenseUrl())
|
||||
.arg(tr("License"))
|
||||
.arg(getThirdPartyLicensesUrl())
|
||||
.arg(tr("Third-Party Licenses")));
|
||||
.arg(getWebsiteUrl())
|
||||
.arg(tr("Website"))
|
||||
.arg(getSupportForumsUrl())
|
||||
.arg(tr("Support Forums"))
|
||||
.arg(getGitHubRepositoryUrl())
|
||||
.arg(tr("GitHub Repository"))
|
||||
.arg(getLicenseUrl())
|
||||
.arg(tr("License"))
|
||||
.arg(getThirdPartyLicensesUrl())
|
||||
.arg(tr("Third-Party Licenses")));
|
||||
|
||||
connect(m_ui.links, &QLabel::linkActivated, this, &AboutDialog::linksLinkActivated);
|
||||
connect(m_ui.buttonBox, &QDialogButtonBox::rejected, this, &QDialog::close);
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>580</width>
|
||||
<height>300</height>
|
||||
<height>320</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
||||
@@ -874,10 +874,10 @@ inline QString DisassemblyView::DisassemblyStringFromAddress(u32 address, QFont
|
||||
}
|
||||
|
||||
lineString = lineString.leftJustified(4, ' ') // Address / symbol
|
||||
.arg(line.name.c_str())
|
||||
.arg(line.params.c_str()) // opcode + arguments
|
||||
.arg(isConditional ? (isConditionalMet ? "# true" : "# false") : "")
|
||||
.arg(isCurrentPC ? "<--" : "");
|
||||
.arg(line.name.c_str())
|
||||
.arg(line.params.c_str()) // opcode + arguments
|
||||
.arg(isConditional ? (isConditionalMet ? "# true" : "# false") : "")
|
||||
.arg(isCurrentPC ? "<--" : "");
|
||||
|
||||
return lineString;
|
||||
}
|
||||
|
||||
@@ -34,10 +34,12 @@
|
||||
#include "pcsx2/Recording/InputRecording.h"
|
||||
#include "pcsx2/Recording/InputRecordingControls.h"
|
||||
#include "pcsx2/SIO/Sio.h"
|
||||
#include "pcsx2/GS/GSExtra.h"
|
||||
|
||||
#include "common/Assertions.h"
|
||||
#include "common/CocoaTools.h"
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/Path.h"
|
||||
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QDir>
|
||||
@@ -217,6 +219,9 @@ void MainWindow::setupAdditionalUi()
|
||||
m_ui.actionViewStatusBar->setChecked(status_bar_visible);
|
||||
m_ui.statusBar->setVisible(status_bar_visible);
|
||||
|
||||
const bool show_game_grid = Host::GetBaseBoolSettingValue("UI", "GameListGridView", false);
|
||||
updateGameGridActions(show_game_grid);
|
||||
|
||||
m_game_list_widget = new GameListWidget(getContentParent());
|
||||
m_game_list_widget->initialize();
|
||||
m_ui.actionGridViewShowTitles->setChecked(m_game_list_widget->getShowGridCoverTitles());
|
||||
@@ -388,6 +393,7 @@ void MainWindow::connectSignals()
|
||||
connect(m_game_list_widget, &GameListWidget::layoutChange, this, [this]() {
|
||||
QSignalBlocker sb(m_ui.actionGridViewShowTitles);
|
||||
m_ui.actionGridViewShowTitles->setChecked(m_game_list_widget->getShowGridCoverTitles());
|
||||
updateGameGridActions(m_game_list_widget->isShowingGameGrid());
|
||||
});
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(nullptr, m_ui.actionViewStatusBarVerbose, "UI", "VerboseStatusBar", false);
|
||||
@@ -502,10 +508,13 @@ void MainWindow::createRendererSwitchMenu()
|
||||
};
|
||||
const GSRendererType current_renderer = static_cast<GSRendererType>(
|
||||
Host::GetBaseIntSettingValue("EmuCore/GS", "Renderer", static_cast<int>(GSRendererType::Auto)));
|
||||
|
||||
QActionGroup* switch_renderer_group = new QActionGroup(m_ui.menuDebugSwitchRenderer);
|
||||
|
||||
for (const GSRendererType renderer : renderers)
|
||||
{
|
||||
QAction* action = m_ui.menuDebugSwitchRenderer->addAction(
|
||||
QString::fromUtf8(Pcsx2Config::GSOptions::GetRendererName(renderer)));
|
||||
QAction* action = new QAction(
|
||||
QString::fromUtf8(Pcsx2Config::GSOptions::GetRendererName(renderer)), switch_renderer_group);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(current_renderer == renderer);
|
||||
connect(action,
|
||||
@@ -513,15 +522,10 @@ void MainWindow::createRendererSwitchMenu()
|
||||
Host::SetBaseIntSettingValue("EmuCore/GS", "Renderer", static_cast<int>(renderer));
|
||||
Host::CommitBaseSettingChanges();
|
||||
g_emu_thread->applySettings();
|
||||
|
||||
// clear all others
|
||||
for (QObject* obj : m_ui.menuDebugSwitchRenderer->children())
|
||||
{
|
||||
if (QAction* act = qobject_cast<QAction*>(obj); act && act != action)
|
||||
act->setChecked(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
m_ui.menuDebugSwitchRenderer->addActions(switch_renderer_group->actions());
|
||||
}
|
||||
|
||||
void MainWindow::recreate()
|
||||
@@ -1129,8 +1133,8 @@ bool MainWindow::shouldHideMainWindow() const
|
||||
{
|
||||
// NOTE: We can't use isRenderingToMain() here, because this happens post-fullscreen-switch.
|
||||
return (Host::GetBoolSettingValue("UI", "HideMainWindowWhenRunning", false) && !g_emu_thread->shouldRenderToMain()) ||
|
||||
(g_emu_thread->shouldRenderToMain() && (isRenderingFullscreen() || m_is_temporarily_windowed)) ||
|
||||
Host::InNoGUIMode();
|
||||
(g_emu_thread->shouldRenderToMain() && (isRenderingFullscreen() || m_is_temporarily_windowed)) ||
|
||||
Host::InNoGUIMode();
|
||||
}
|
||||
|
||||
bool MainWindow::shouldMouseLock() const
|
||||
@@ -1142,8 +1146,8 @@ bool MainWindow::shouldMouseLock() const
|
||||
return false;
|
||||
|
||||
bool windowsHidden = (!g_debugger_window || g_debugger_window->isHidden()) &&
|
||||
(!m_controller_settings_window || m_controller_settings_window->isHidden()) &&
|
||||
(!m_settings_window || m_settings_window->isHidden());
|
||||
(!m_controller_settings_window || m_controller_settings_window->isHidden()) &&
|
||||
(!m_settings_window || m_settings_window->isHidden());
|
||||
|
||||
return windowsHidden && (isActiveWindow() || isRenderingFullscreen());
|
||||
}
|
||||
@@ -1454,6 +1458,8 @@ void MainWindow::onGameListEntryContextMenuRequested(const QPoint& point)
|
||||
connect(menu.addAction(tr("Check Wiki Page")), &QAction::triggered, [this, entry]() { goToWikiPage(entry); });
|
||||
}
|
||||
|
||||
action = menu.addAction(tr("Open Screenshots Folder"));
|
||||
connect(action, &QAction::triggered, [this, entry]() { openScreenshotsFolderForGame(entry); });
|
||||
menu.addSeparator();
|
||||
|
||||
if (!s_vm_valid)
|
||||
@@ -2905,6 +2911,39 @@ void MainWindow::goToWikiPage(const GameList::Entry* entry)
|
||||
QtUtils::OpenURL(this, fmt::format("https://wiki.pcsx2.net/{}", entry->serial).c_str());
|
||||
}
|
||||
|
||||
void MainWindow::openScreenshotsFolderForGame(const GameList::Entry* entry)
|
||||
{
|
||||
if (!entry || entry->title.empty())
|
||||
return;
|
||||
|
||||
// if disabled open the snapshots folder
|
||||
if (!EmuConfig.GS.OrganizeScreenshotsByGame)
|
||||
{
|
||||
QtUtils::OpenURL(this, QUrl::fromLocalFile(QString::fromStdString(EmuFolders::Snapshots)));
|
||||
return;
|
||||
}
|
||||
|
||||
std::string game_name = entry->title;
|
||||
Path::SanitizeFileName(&game_name);
|
||||
if (game_name.length() > 219)
|
||||
{
|
||||
game_name.resize(219);
|
||||
}
|
||||
const std::string game_dir = Path::Combine(EmuFolders::Snapshots, game_name);
|
||||
|
||||
if (!FileSystem::DirectoryExists(game_dir.c_str()))
|
||||
{
|
||||
if (!FileSystem::CreateDirectoryPath(game_dir.c_str(), false))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to create screenshots directory '%1'.").arg(QString::fromStdString(game_dir)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const QFileInfo fi(QString::fromStdString(game_dir));
|
||||
QtUtils::OpenURL(this, QUrl::fromLocalFile(fi.absoluteFilePath()));
|
||||
}
|
||||
|
||||
std::optional<bool> MainWindow::promptForResumeState(const QString& save_state_path)
|
||||
{
|
||||
if (save_state_path.isEmpty())
|
||||
@@ -3110,6 +3149,14 @@ void MainWindow::updateGameDependentActions()
|
||||
m_ui.actionReloadPatches->setEnabled(s_vm_valid);
|
||||
}
|
||||
|
||||
void MainWindow::updateGameGridActions(const bool show_game_grid)
|
||||
{
|
||||
m_ui.actionGridViewShowTitles->setEnabled(show_game_grid);
|
||||
m_ui.actionGridViewZoomIn->setEnabled(show_game_grid);
|
||||
m_ui.actionGridViewZoomOut->setEnabled(show_game_grid);
|
||||
m_ui.actionGridViewRefreshCovers->setEnabled(show_game_grid);
|
||||
}
|
||||
|
||||
void MainWindow::doStartFile(std::optional<CDVD_SourceType> source, const QString& path)
|
||||
{
|
||||
if (s_vm_valid)
|
||||
|
||||
@@ -234,6 +234,7 @@ private:
|
||||
void updateEmulationActions(bool starting, bool running, bool stopping);
|
||||
void updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen);
|
||||
void updateGameDependentActions();
|
||||
void updateGameGridActions(const bool show_game_grid);
|
||||
void updateStatusBarWidgetVisibility();
|
||||
void updateAdvancedSettingsVisibility();
|
||||
void updateWindowTitle();
|
||||
@@ -274,6 +275,7 @@ private:
|
||||
void setGameListEntryCoverImage(const GameList::Entry* entry);
|
||||
void clearGameListEntryPlayTime(const GameList::Entry* entry);
|
||||
void goToWikiPage(const GameList::Entry* entry);
|
||||
void openScreenshotsFolderForGame(const GameList::Entry* entry);
|
||||
|
||||
std::optional<bool> promptForResumeState(const QString& save_state_path);
|
||||
void loadSaveStateSlot(s32 slot, bool load_backup = false);
|
||||
|
||||
@@ -1000,21 +1000,21 @@ void EmuThread::updatePerformanceMetrics(bool force)
|
||||
if (THREAD_VU1)
|
||||
{
|
||||
gs_stat = tr("Slot: %1 | Volume: %2% | %3 | EE: %4% | VU: %5% | GS: %6%")
|
||||
.arg(SaveStateSelectorUI::GetCurrentSlot())
|
||||
.arg(SPU2::GetOutputVolume())
|
||||
.arg(gs_stat_str.c_str())
|
||||
.arg(PerformanceMetrics::GetCPUThreadUsage(), 0, 'f', 0)
|
||||
.arg(PerformanceMetrics::GetVUThreadUsage(), 0, 'f', 0)
|
||||
.arg(PerformanceMetrics::GetGSThreadUsage(), 0, 'f', 0);
|
||||
.arg(SaveStateSelectorUI::GetCurrentSlot())
|
||||
.arg(SPU2::GetOutputVolume())
|
||||
.arg(gs_stat_str.c_str())
|
||||
.arg(PerformanceMetrics::GetCPUThreadUsage(), 0, 'f', 0)
|
||||
.arg(PerformanceMetrics::GetVUThreadUsage(), 0, 'f', 0)
|
||||
.arg(PerformanceMetrics::GetGSThreadUsage(), 0, 'f', 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
gs_stat = tr("Slot: %1 | Volume: %2% | %3 | EE: %4% | GS: %5%")
|
||||
.arg(SaveStateSelectorUI::GetCurrentSlot())
|
||||
.arg(SPU2::GetOutputVolume())
|
||||
.arg(gs_stat_str.c_str())
|
||||
.arg(PerformanceMetrics::GetCPUThreadUsage(), 0, 'f', 0)
|
||||
.arg(PerformanceMetrics::GetGSThreadUsage(), 0, 'f', 0);
|
||||
.arg(SaveStateSelectorUI::GetCurrentSlot())
|
||||
.arg(SPU2::GetOutputVolume())
|
||||
.arg(gs_stat_str.c_str())
|
||||
.arg(PerformanceMetrics::GetCPUThreadUsage(), 0, 'f', 0)
|
||||
.arg(PerformanceMetrics::GetGSThreadUsage(), 0, 'f', 0);
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(g_main_window->getStatusVerboseWidget(), "setText", Qt::QueuedConnection, Q_ARG(const QString&, gs_stat));
|
||||
@@ -1129,9 +1129,9 @@ void Host::OnAchievementsRefreshed()
|
||||
game_id = Achievements::GetGameID();
|
||||
|
||||
game_info = qApp
|
||||
->translate("EmuThread", "Game: %1 (%2)\n")
|
||||
.arg(QString::fromStdString(Achievements::GetGameTitle()))
|
||||
.arg(game_id);
|
||||
->translate("EmuThread", "Game: %1 (%2)\n")
|
||||
.arg(QString::fromStdString(Achievements::GetGameTitle()))
|
||||
.arg(game_id);
|
||||
|
||||
const std::string& rich_presence_string = Achievements::GetRichPresenceString();
|
||||
if (!rich_presence_string.empty())
|
||||
@@ -1181,7 +1181,7 @@ void Host::OpenHostFileSelectorAsync(std::string_view title, bool select_directo
|
||||
if (!filters.empty())
|
||||
{
|
||||
filters_str.append(QStringLiteral("All File Types (%1)")
|
||||
.arg(QString::fromStdString(StringUtil::JoinString(filters.begin(), filters.end(), " "))));
|
||||
.arg(QString::fromStdString(StringUtil::JoinString(filters.begin(), filters.end(), " "))));
|
||||
for (const std::string& filter : filters)
|
||||
{
|
||||
filters_str.append(
|
||||
|
||||
@@ -90,9 +90,7 @@ namespace QtUtils
|
||||
|
||||
const int min_column_width = header->minimumSectionSize();
|
||||
const int scrollbar_width = ((view->verticalScrollBar() && view->verticalScrollBar()->isVisible()) ||
|
||||
view->verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOn) ?
|
||||
view->verticalScrollBar()->width() :
|
||||
0;
|
||||
view->verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOn) ? view->verticalScrollBar()->width() : 0;
|
||||
int num_flex_items = 0;
|
||||
int total_width = 0;
|
||||
int column_index = 0;
|
||||
|
||||
@@ -242,8 +242,8 @@ namespace SettingWidgetBinder
|
||||
static std::optional<QString> getNullableStringValue(const QCheckBox* widget)
|
||||
{
|
||||
return (widget->checkState() == Qt::PartiallyChecked) ?
|
||||
std::nullopt :
|
||||
std::optional<QString>(widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0"));
|
||||
std::nullopt :
|
||||
std::optional<QString>(widget->isChecked() ? QStringLiteral("1") : QStringLiteral("0"));
|
||||
}
|
||||
static void setNullableStringValue(QCheckBox* widget, std::optional<QString> value)
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ AchievementSettingsWidget::AchievementSettingsWidget(SettingsWindow* dialog, QWi
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.notificationPosition, "Achievements", "NotificationPosition", static_cast<int>(OsdOverlayPos::TopLeft));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.encoreMode, "Achievements", "EncoreMode", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.spectatorMode, "Achievements", "SpectatorMode", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.unofficialAchievements, "Achievements", "UnofficialTestMode",false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.unofficialAchievements, "Achievements", "UnofficialTestMode", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.achievementNotificationsDuration, "Achievements", "NotificationsDuration", Pcsx2Config::AchievementsOptions::DEFAULT_NOTIFICATION_DURATION);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.leaderboardNotificationsDuration, "Achievements", "LeaderboardsDuration", Pcsx2Config::AchievementsOptions::DEFAULT_LEADERBOARD_DURATION);
|
||||
|
||||
@@ -57,7 +57,7 @@ AchievementSettingsWidget::AchievementSettingsWidget(SettingsWindow* dialog, QWi
|
||||
dialog->registerWidgetHelp(m_ui.overlays, tr("Enable In-Game Overlays"), tr("Checked"), tr("Shows icons in the lower-right corner of the screen when a challenge/primed achievement is active."));
|
||||
dialog->registerWidgetHelp(m_ui.overlayPosition, tr("Overlay Position"), tr("Bottom Right"), tr("Determines where achievement overlays are positioned on the screen."));
|
||||
dialog->registerWidgetHelp(m_ui.notificationPosition, tr("Notification Position"), tr("Top Left"), tr("Determines where achievement notification popups are positioned on the screen."));
|
||||
dialog->registerWidgetHelp(m_ui.encoreMode, tr("Enable Encore Mode"), tr("Unchecked"),tr("When enabled, each session will behave as if no achievements have been unlocked."));
|
||||
dialog->registerWidgetHelp(m_ui.encoreMode, tr("Enable Encore Mode"), tr("Unchecked"), tr("When enabled, each session will behave as if no achievements have been unlocked."));
|
||||
dialog->registerWidgetHelp(m_ui.spectatorMode, tr("Enable Spectator Mode"), tr("Unchecked"), tr("When enabled, PCSX2 will assume all achievements are locked and not send any unlock notifications to the server."));
|
||||
dialog->registerWidgetHelp(m_ui.unofficialAchievements, tr("Test Unofficial Achievements"), tr("Unchecked"), tr("When enabled, PCSX2 will list achievements from unofficial sets. Please note that these achievements are not tracked by RetroAchievements, so they unlock every time."));
|
||||
|
||||
@@ -211,8 +211,8 @@ void AchievementSettingsWidget::updateLoginState()
|
||||
StringUtil::FromChars<u64>(Host::GetBaseStringSettingValue("Achievements", "LoginTimestamp", "0")).value_or(0);
|
||||
const QDateTime login_timestamp(QDateTime::fromSecsSinceEpoch(static_cast<qint64>(login_unix_timestamp)));
|
||||
m_ui.loginStatus->setText(tr("Username: %1\nLogin token generated on %2.")
|
||||
.arg(QString::fromStdString(username))
|
||||
.arg(login_timestamp.toString(Qt::TextDate)));
|
||||
.arg(QString::fromStdString(username))
|
||||
.arg(login_timestamp.toString(Qt::TextDate)));
|
||||
m_ui.loginButton->setText(tr("Logout"));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -53,11 +53,8 @@ AdvancedSettingsWidget::AdvancedSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.gameFixes, "EmuCore", "EnableGameFixes", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.patches, "EmuCore", "EnablePatches", true);
|
||||
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.ntscFrameRate, "EmuCore/GS", "FramerateNTSC", 59.94f);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.palFrameRate, "EmuCore/GS", "FrameratePAL", 50.00f);
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.savestateSelector, tr("Use Save State Selector"), tr("Checked"),
|
||||
tr("Show a save state selector UI when switching slots instead of showing a notification bubble."));
|
||||
tr("Show a save state selector UI when switching slots instead of showing a notification bubble."));
|
||||
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.savestateCompressionMethod, "EmuCore", "SavestateCompressionType", static_cast<int>(SavestateCompressionMethod::Zstandard));
|
||||
@@ -223,6 +220,6 @@ void AdvancedSettingsWidget::setClampingMode(int vunum, int index)
|
||||
void AdvancedSettingsWidget::onSavestateCompressionTypeChanged()
|
||||
{
|
||||
const bool uncompressed = (m_dialog->getEffectiveIntValue("EmuCore", "SavestateCompressionType", static_cast<int>(SavestateCompressionMethod::Zstandard)) ==
|
||||
static_cast<int>(SavestateCompressionMethod::Uncompressed));
|
||||
static_cast<int>(SavestateCompressionMethod::Uncompressed));
|
||||
m_ui.savestateCompressionLevel->setDisabled(uncompressed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -508,61 +508,6 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="framerateControlSettings">
|
||||
<property name="title">
|
||||
<string>Frame Rate Control</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="framerateControlLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="palFrameRate">
|
||||
<property name="suffix">
|
||||
<string extracomment="hz=Hertz, as in the measuring unit. Shown after the corresponding number. Those languages who'd need to remove the space or do something in between should do so."> hz</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>300.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="ntscFrameRate">
|
||||
<property name="suffix">
|
||||
<string> hz</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>300.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="palLabel">
|
||||
<property name="text">
|
||||
<string>PAL Frame Rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="ntscLabel">
|
||||
<property name="text">
|
||||
<string>NTSC Frame Rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="pineSettings">
|
||||
<property name="title">
|
||||
|
||||
@@ -160,20 +160,20 @@ void AudioSettingsWidget::onSyncModeChanged()
|
||||
{
|
||||
const Pcsx2Config::SPU2Options::SPU2SyncMode sync_mode =
|
||||
Pcsx2Config::SPU2Options::ParseSyncMode(
|
||||
m_dialog
|
||||
->getEffectiveStringValue("SPU2/Output", "SyncMode",
|
||||
Pcsx2Config::SPU2Options::GetSyncModeName(Pcsx2Config::SPU2Options::DEFAULT_SYNC_MODE))
|
||||
.c_str())
|
||||
.value_or(Pcsx2Config::SPU2Options::DEFAULT_SYNC_MODE);
|
||||
m_dialog->getEffectiveStringValue("SPU2/Output", "SyncMode",
|
||||
Pcsx2Config::SPU2Options::GetSyncModeName(Pcsx2Config::SPU2Options::DEFAULT_SYNC_MODE)
|
||||
).c_str()
|
||||
).value_or(Pcsx2Config::SPU2Options::DEFAULT_SYNC_MODE);
|
||||
m_ui.stretchSettings->setEnabled(sync_mode == Pcsx2Config::SPU2Options::SPU2SyncMode::TimeStretch);
|
||||
}
|
||||
|
||||
AudioBackend AudioSettingsWidget::getEffectiveBackend() const
|
||||
{
|
||||
return AudioStream::ParseBackendName(m_dialog->getEffectiveStringValue("SPU2/Output", "Backend",
|
||||
AudioStream::GetBackendName(Pcsx2Config::SPU2Options::DEFAULT_BACKEND))
|
||||
.c_str())
|
||||
.value_or(Pcsx2Config::SPU2Options::DEFAULT_BACKEND);
|
||||
return AudioStream::ParseBackendName(
|
||||
m_dialog->getEffectiveStringValue("SPU2/Output", "Backend",
|
||||
AudioStream::GetBackendName(Pcsx2Config::SPU2Options::DEFAULT_BACKEND)
|
||||
).c_str()
|
||||
).value_or(Pcsx2Config::SPU2Options::DEFAULT_BACKEND);
|
||||
}
|
||||
|
||||
void AudioSettingsWidget::updateDriverNames()
|
||||
@@ -263,17 +263,17 @@ void AudioSettingsWidget::updateLatencyLabel()
|
||||
if (expand_buffer_ms > 0)
|
||||
{
|
||||
m_ui.bufferingLabel->setText(tr("Maximum Latency: %1 ms (%2 ms buffer + %3 ms expand + %4 ms output)")
|
||||
.arg(config_buffer_ms + expand_buffer_ms + output_latency_ms)
|
||||
.arg(config_buffer_ms)
|
||||
.arg(expand_buffer_ms)
|
||||
.arg(output_latency_ms));
|
||||
.arg(config_buffer_ms + expand_buffer_ms + output_latency_ms)
|
||||
.arg(config_buffer_ms)
|
||||
.arg(expand_buffer_ms)
|
||||
.arg(output_latency_ms));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ui.bufferingLabel->setText(tr("Maximum Latency: %1 ms (%2 ms buffer + %3 ms output)")
|
||||
.arg(config_buffer_ms + output_latency_ms)
|
||||
.arg(config_buffer_ms)
|
||||
.arg(output_latency_ms));
|
||||
.arg(config_buffer_ms + output_latency_ms)
|
||||
.arg(config_buffer_ms)
|
||||
.arg(output_latency_ms));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -281,8 +281,8 @@ void AudioSettingsWidget::updateLatencyLabel()
|
||||
if (expand_buffer_ms > 0)
|
||||
{
|
||||
m_ui.bufferingLabel->setText(tr("Maximum Latency: %1 ms (%2 ms expand, minimum output latency unknown)")
|
||||
.arg(expand_buffer_ms + config_buffer_ms)
|
||||
.arg(expand_buffer_ms));
|
||||
.arg(expand_buffer_ms + config_buffer_ms)
|
||||
.arg(expand_buffer_ms));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -206,7 +206,7 @@ void ControllerSettingsWindow::onRenameProfileClicked()
|
||||
{
|
||||
std::string game_settings_path(game_settings.FileName.c_str());
|
||||
std::unique_ptr<INISettingsInterface> update_sif(std::make_unique<INISettingsInterface>(std::move(game_settings_path)));
|
||||
|
||||
|
||||
update_sif->Load();
|
||||
|
||||
if (!old_profile_name.compare(update_sif->GetStringValue("EmuCore", "InputProfileName")))
|
||||
@@ -458,9 +458,9 @@ void ControllerSettingsWindow::createWidgets()
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem();
|
||||
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
|
||||
item->setText(mtap_enabled[port] ? (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name)) :
|
||||
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
|
||||
tr("Controller Port %1\n%2").arg(port + 1).arg(display_name));
|
||||
item->setText(mtap_enabled[port] ? (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name))
|
||||
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
|
||||
: tr("Controller Port %1\n%2").arg(port + 1).arg(display_name));
|
||||
item->setIcon(m_port_bindings[global_slot]->getIcon());
|
||||
item->setData(Qt::UserRole, QVariant(global_slot));
|
||||
m_ui.settingsCategory->addItem(item);
|
||||
@@ -514,9 +514,9 @@ void ControllerSettingsWindow::updateListDescription(u32 global_slot, Controller
|
||||
const QString display_name = QString::fromUtf8(ci ? ci->GetLocalizedName() : "Unknown");
|
||||
|
||||
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
|
||||
item->setText(mtap_enabled ? (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name)) :
|
||||
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
|
||||
tr("Controller Port %1\n%2").arg(port + 1).arg(display_name));
|
||||
item->setText(mtap_enabled ? (tr("Controller Port %1%2\n%3").arg(port + 1).arg(s_mtap_slot_names[slot]).arg(display_name))
|
||||
//: Controller Port is an official term from Sony. Find the official translation for your language inside the console's manual.
|
||||
: tr("Controller Port %1\n%2").arg(port + 1).arg(display_name));
|
||||
item->setIcon(widget->getIcon());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ void DEV9SettingsWidget::onEthDeviceChanged(int index)
|
||||
void DEV9SettingsWidget::onEthDHCPInterceptChanged(Qt::CheckState state)
|
||||
{
|
||||
const bool enabled = (state == Qt::CheckState::PartiallyChecked ? Host::GetBaseBoolSettingValue("DEV9/Eth", "InterceptDHCP", false) : state) ||
|
||||
((m_adapter_options & AdapterOptions::DHCP_ForcedOn) == AdapterOptions::DHCP_ForcedOn);
|
||||
((m_adapter_options & AdapterOptions::DHCP_ForcedOn) == AdapterOptions::DHCP_ForcedOn);
|
||||
|
||||
// clang-format off
|
||||
const bool ipOverride = (m_adapter_options & AdapterOptions::DHCP_OverrideIP) == AdapterOptions::DHCP_OverrideIP;
|
||||
|
||||
@@ -55,11 +55,11 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
|
||||
connect(m_ui.manuallySetRealTimeClock, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::onManuallySetRealTimeClockChanged);
|
||||
EmulationSettingsWidget::onManuallySetRealTimeClockChanged();
|
||||
|
||||
m_ui.eeCycleRate->insertItem(
|
||||
0, tr("Use Global Setting [%1]")
|
||||
.arg(m_ui.eeCycleRate->itemText(
|
||||
std::clamp(Host::GetBaseIntSettingValue("EmuCore/Speedhacks", "EECycleRate", DEFAULT_EE_CYCLE_RATE) - MINIMUM_EE_CYCLE_RATE,
|
||||
0, MAXIMUM_EE_CYCLE_RATE - MINIMUM_EE_CYCLE_RATE))));
|
||||
m_ui.eeCycleRate->insertItem(0,
|
||||
tr("Use Global Setting [%1]")
|
||||
.arg(m_ui.eeCycleRate->itemText(
|
||||
std::clamp(Host::GetBaseIntSettingValue("EmuCore/Speedhacks", "EECycleRate", DEFAULT_EE_CYCLE_RATE) - MINIMUM_EE_CYCLE_RATE,
|
||||
0, MAXIMUM_EE_CYCLE_RATE - MINIMUM_EE_CYCLE_RATE))));
|
||||
|
||||
// Disable cheats, use the cheats panel instead (move fastcvd up in its spot).
|
||||
const int count = m_ui.systemSettingsLayout->count();
|
||||
@@ -92,9 +92,9 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
|
||||
|
||||
const std::optional<int> cycle_rate =
|
||||
m_dialog->getIntValue("EmuCore/Speedhacks", "EECycleRate", sif ? std::nullopt : std::optional<int>(DEFAULT_EE_CYCLE_RATE));
|
||||
m_ui.eeCycleRate->setCurrentIndex(cycle_rate.has_value() ? (std::clamp(cycle_rate.value(), MINIMUM_EE_CYCLE_RATE, MAXIMUM_EE_CYCLE_RATE) +
|
||||
(0 - MINIMUM_EE_CYCLE_RATE) + static_cast<int>(m_dialog->isPerGameSettings())) :
|
||||
0);
|
||||
m_ui.eeCycleRate->setCurrentIndex(cycle_rate.has_value() ? (std::clamp(cycle_rate.value(), MINIMUM_EE_CYCLE_RATE, MAXIMUM_EE_CYCLE_RATE)
|
||||
+ (0 - MINIMUM_EE_CYCLE_RATE) + static_cast<int>(m_dialog->isPerGameSettings()))
|
||||
: 0);
|
||||
connect(m_ui.eeCycleRate, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this](int index) {
|
||||
std::optional<int> value;
|
||||
if (!m_dialog->isPerGameSettings() || index > 0)
|
||||
@@ -164,9 +164,9 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* dialog, QWidget
|
||||
tr("Manually set a real-time clock to use for the virtual PlayStation 2 instead of using your OS' system clock."));
|
||||
dialog->registerWidgetHelp(m_ui.rtcDateTime, tr("Real-Time Clock"), tr("Current date and time"),
|
||||
tr("Real-time clock (RTC) used by the virtual PlayStation 2. Date format is the same as the one used by your OS. "
|
||||
"This time is only applied upon booting the PS2; changing it while in-game will have no effect. "
|
||||
"NOTE: This assumes you have your PS2 set to the default timezone of GMT+0 and default DST of Summer Time. "
|
||||
"Some games require an RTC date/time set after their release date."));
|
||||
"This time is only applied upon booting the PS2; changing it while in-game will have no effect. "
|
||||
"NOTE: This assumes you have your PS2 set to the default timezone of GMT+0 and default DST of Summer Time. "
|
||||
"Some games require an RTC date/time set after their release date."));
|
||||
|
||||
updateOptimalFramePacing();
|
||||
updateUseVSyncForTimingEnabled();
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include <QtWidgets/QMessageBox>
|
||||
#include <algorithm>
|
||||
|
||||
#include "FolderSettingsWidget.h"
|
||||
#include "pcsx2/GS/GS.h"
|
||||
#include "SettingWidgetBinder.h"
|
||||
#include "SettingsWindow.h"
|
||||
|
||||
@@ -18,8 +20,14 @@ FolderSettingsWidget::FolderSettingsWidget(SettingsWindow* dialog, QWidget* pare
|
||||
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.cheats, m_ui.cheatsBrowse, m_ui.cheatsOpen, m_ui.cheatsReset, "Folders", "Cheats", Path::Combine(EmuFolders::DataRoot, "cheats"));
|
||||
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.covers, m_ui.coversBrowse, m_ui.coversOpen, m_ui.coversReset, "Folders", "Covers", Path::Combine(EmuFolders::DataRoot, "covers"));
|
||||
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.snapshots, m_ui.snapshotsBrowse, m_ui.snapshotsOpen, m_ui.snapshotsReset, "Folders", "Snapshots", Path::Combine(EmuFolders::DataRoot, "snaps"));
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.organizeScreenshotsByGame, "EmuCore/GS", "OrganizeScreenshotsByGame", false);
|
||||
connect(m_ui.organizeScreenshotsByGame, &QCheckBox::checkStateChanged, this, [](int state) {
|
||||
GSConfig.OrganizeScreenshotsByGame = (state == Qt::Checked);
|
||||
});
|
||||
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.saveStates, m_ui.saveStatesBrowse, m_ui.saveStatesOpen, m_ui.saveStatesReset, "Folders", "SaveStates", Path::Combine(EmuFolders::DataRoot, "sstates"));
|
||||
SettingWidgetBinder::BindWidgetToFolderSetting(sif, m_ui.videoDumpingDirectory, m_ui.videoDumpingDirectoryBrowse, m_ui.videoDumpingDirectoryOpen, m_ui.videoDumpingDirectoryReset, "Folders", "Videos", Path::Combine(EmuFolders::DataRoot, "videos"));
|
||||
dialog->registerWidgetHelp(m_ui.organizeScreenshotsByGame, tr("Organize Screenshots by Game"), tr("Unchecked"),
|
||||
tr("When enabled, screenshots will be saved in a folder with the game's name, instead of all being saved in the Snapshots folder"));
|
||||
}
|
||||
|
||||
FolderSettingsWidget::~FolderSettingsWidget() = default;
|
||||
|
||||
@@ -175,12 +175,19 @@
|
||||
</item>
|
||||
<item row="0" column="0" colspan="4">
|
||||
<widget class="QLabel" name="snaphotsLabel">
|
||||
<property name="text">
|
||||
<string>Used for screenshots and saving GS dumps.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
<property name="text">
|
||||
<string>Used for screenshots and saving GS dumps.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="4">
|
||||
<widget class="QCheckBox" name="organizeScreenshotsByGame">
|
||||
<property name="text">
|
||||
<string>Save Screenshots in Game-Specific Folders</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
|
||||
@@ -205,7 +205,7 @@ void GameCheatSettingsWidget::reloadList()
|
||||
{
|
||||
u32 num_unlabelled_codes = 0;
|
||||
bool showAllCRCS = m_ui.allCRCsCheckbox->isChecked();
|
||||
m_patches = Patch::GetPatchInfo(m_dialog->getSerial(), m_dialog->getDiscCRC(), true, showAllCRCS, & num_unlabelled_codes);
|
||||
m_patches = Patch::GetPatchInfo(m_dialog->getSerial(), m_dialog->getDiscCRC(), true, showAllCRCS, &num_unlabelled_codes);
|
||||
m_enabled_patches =
|
||||
m_dialog->getSettingsInterface()->GetStringList(Patch::CHEATS_CONFIG_SECTION, Patch::PATCH_ENABLE_CONFIG_KEY);
|
||||
|
||||
|
||||
@@ -340,15 +340,15 @@ void GameSummaryWidget::onVerifyClicked()
|
||||
if (!hentry->version.empty())
|
||||
{
|
||||
setVerifyResult(tr("Verified as %1 [%2] (Version %3).")
|
||||
.arg(QString::fromStdString(hentry->name))
|
||||
.arg(QString::fromStdString(hentry->serial))
|
||||
.arg(QString::fromStdString(hentry->version)));
|
||||
.arg(QString::fromStdString(hentry->name))
|
||||
.arg(QString::fromStdString(hentry->serial))
|
||||
.arg(QString::fromStdString(hentry->version)));
|
||||
}
|
||||
else
|
||||
{
|
||||
setVerifyResult(tr("Verified as %1 [%2].")
|
||||
.arg(QString::fromStdString(hentry->name))
|
||||
.arg(QString::fromStdString(hentry->serial)));
|
||||
.arg(QString::fromStdString(hentry->name))
|
||||
.arg(QString::fromStdString(hentry->serial)));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -130,12 +130,17 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowHardwareInfo, "EmuCore/GS", "OsdShowHardwareInfo", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowVideoCapture, "EmuCore/GS", "OsdShowVideoCapture", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowInputRec, "EmuCore/GS", "OsdShowInputRec", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdWarnAboutUnsafeSettings, "EmuCore", "osdWarnAboutUnsafeSettings", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdWarnAboutUnsafeSettings, "EmuCore", "OsdWarnAboutUnsafeSettings", true);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Post-Processing Settings
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fxaa, "EmuCore/GS", "fxaa", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.shadeBoost, "EmuCore/GS", "ShadeBoost", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.shadeBoostBrightness, "EmuCore/GS", "ShadeBoost_Brightness", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.shadeBoostContrast, "EmuCore/GS", "ShadeBoost_Contrast", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.shadeBoostSaturation, "EmuCore/GS", "ShadeBoost_Saturation", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.shadeBoostBrightness, "EmuCore/GS", "ShadeBoost_Brightness", Pcsx2Config::GSOptions::DEFAULT_SHADEBOOST_BRIGHTNESS);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.shadeBoostContrast, "EmuCore/GS", "ShadeBoost_Contrast", Pcsx2Config::GSOptions::DEFAULT_SHADEBOOST_CONTRAST);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.shadeBoostGamma, "EmuCore/GS", "ShadeBoost_Gamma", Pcsx2Config::GSOptions::DEFAULT_SHADEBOOST_GAMMA);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.shadeBoostSaturation, "EmuCore/GS", "ShadeBoost_Saturation", Pcsx2Config::GSOptions::DEFAULT_SHADEBOOST_SATURATION);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.tvShader, "EmuCore/GS", "TVShader", DEFAULT_TV_SHADER_MODE);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.casMode, "EmuCore/GS", "CASMode", static_cast<int>(GSCASMode::Disabled));
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_ui.casSharpness, "EmuCore/GS", "CASSharpness", DEFAULT_CAS_SHARPNESS);
|
||||
@@ -254,6 +259,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.disableVertexShaderExpand, "EmuCore/GS", "DisableVertexShaderExpand", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(
|
||||
sif, m_ui.gsDownloadMode, "EmuCore/GS", "HWDownloadMode", static_cast<int>(GSHardwareDownloadMode::Enabled));
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.ntscFrameRate, "EmuCore/GS", "FrameRateNTSC", 59.94f);
|
||||
SettingWidgetBinder::BindWidgetToFloatSetting(sif, m_ui.palFrameRate, "EmuCore/GS", "FrameRatePAL", 50.00f);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// SW Settings
|
||||
@@ -392,6 +399,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
m_ui.useBlitSwapChain = nullptr;
|
||||
m_ui.disableMailboxPresentation = nullptr;
|
||||
m_ui.extendedUpscales = nullptr;
|
||||
m_ui.ntscFrameRate = nullptr;
|
||||
m_ui.palFrameRate = nullptr;
|
||||
m_ui.spinCPUDuringReadbacks = nullptr;
|
||||
m_ui.spinGPUDuringReadbacks = nullptr;
|
||||
m_ui.overrideTextureBarriers = nullptr;
|
||||
@@ -723,6 +732,8 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.shadeBoostContrast, tr("Contrast"), tr("50"), tr("Adjusts contrast. 50 is normal."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.shadeBoostGamma, tr("Gamma"), tr("50"), tr("Adjusts gamma. 50 is normal."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.shadeBoostSaturation, tr("Saturation"), tr("50"), tr("Adjusts saturation. 50 is normal."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.tvShader, tr("TV Shader"), tr("None (Default)"),
|
||||
@@ -857,6 +868,12 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
tr("Skips synchronizing with the GS thread and host GPU for GS downloads. "
|
||||
"Can result in a large speed boost on slower systems, at the cost of many broken graphical effects. "
|
||||
"If games are broken and you have this option enabled, please disable it first."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.ntscFrameRate, tr("NTSC Frame Rate"), tr("59.94 Hz"),
|
||||
tr("Determines what frame rate NTSC games run at."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.palFrameRate, tr("PAL Frame Rate"), tr("50.00 Hz"),
|
||||
tr("Determines what frame rate PAL games run at."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -934,6 +951,7 @@ void GraphicsSettingsWidget::onShadeBoostChanged()
|
||||
const bool enabled = m_dialog->getEffectiveBoolValue("EmuCore/GS", "ShadeBoost", false);
|
||||
m_ui.shadeBoostBrightness->setEnabled(enabled);
|
||||
m_ui.shadeBoostContrast->setEnabled(enabled);
|
||||
m_ui.shadeBoostGamma->setEnabled(enabled);
|
||||
m_ui.shadeBoostSaturation->setEnabled(enabled);
|
||||
}
|
||||
|
||||
@@ -1262,8 +1280,8 @@ void GraphicsSettingsWidget::populateUpscaleMultipliers(u32 max_upscale_multipli
|
||||
m_ui.upscaleMultiplier->clear();
|
||||
|
||||
const u32 max_shown_multiplier = m_ui.extendedUpscales && m_ui.extendedUpscales->checkState() == Qt::Checked ?
|
||||
max_upscale_multiplier :
|
||||
std::min(max_upscale_multiplier, max_non_advanced_multiplier);
|
||||
max_upscale_multiplier :
|
||||
std::min(max_upscale_multiplier, max_non_advanced_multiplier);
|
||||
for (const auto& [name, value] : templates)
|
||||
{
|
||||
if (value > max_shown_multiplier)
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>720</width>
|
||||
<height>588</height>
|
||||
<width>722</width>
|
||||
<height>626</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
@@ -60,7 +60,7 @@
|
||||
<property name="documentMode">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="gameDisplayTab">
|
||||
<widget class="QWidget" name="gameDisplayTab">
|
||||
<attribute name="title">
|
||||
<string>Display</string>
|
||||
</attribute>
|
||||
@@ -391,7 +391,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="hardwareRenderingTab">
|
||||
<widget class="QWidget" name="hardwareRenderingTab">
|
||||
<attribute name="title">
|
||||
<string>Rendering</string>
|
||||
</attribute>
|
||||
@@ -652,7 +652,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="hardwareFixesTab">
|
||||
<widget class="QWidget" name="hardwareFixesTab">
|
||||
<attribute name="title">
|
||||
<string>Hardware Fixes</string>
|
||||
</attribute>
|
||||
@@ -950,7 +950,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="upscalingFixesTab">
|
||||
<widget class="QWidget" name="upscalingFixesTab">
|
||||
<attribute name="title">
|
||||
<string>Upscaling Fixes</string>
|
||||
</attribute>
|
||||
@@ -1433,6 +1433,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="gammaLabel">
|
||||
<property name="text">
|
||||
<string>Gamma:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="shadeBoostGamma">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="saturationLabel">
|
||||
<property name="text">
|
||||
@@ -1470,7 +1487,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="osdTab">
|
||||
<widget class="QWidget" name="osdTab">
|
||||
<attribute name="title">
|
||||
<string>OSD</string>
|
||||
</attribute>
|
||||
@@ -1837,7 +1854,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="recordingTab">
|
||||
<widget class="QWidget" name="recordingTab">
|
||||
<attribute name="title">
|
||||
<string>Media Capture</string>
|
||||
</attribute>
|
||||
@@ -2158,7 +2175,7 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
@@ -2170,248 +2187,394 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="advancedTab">
|
||||
<widget class="QWidget" name="advancedTab">
|
||||
<attribute name="title">
|
||||
<string extracomment="Advanced here refers to the advanced graphics options.">Advanced</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="advancedTabLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="advancedOptions">
|
||||
<property name="title">
|
||||
<string>Advanced Options</string>
|
||||
<widget class="QScrollArea" name="advancedScrollArea">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="advancedOptionsFormLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="hwDownloadModeLabel">
|
||||
<property name="text">
|
||||
<string>Hardware Download Mode:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="gsDownloadMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Accurate (Recommended)</string>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="advancedScrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>722</width>
|
||||
<height>499</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>499</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="advancedOptions">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Disable Readbacks (Synchronize GS Thread)</string>
|
||||
<property name="title">
|
||||
<string>Advanced Options</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Unsynchronized (Non-Deterministic)</string>
|
||||
<layout class="QFormLayout" name="advancedOptionsFormLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="hwDownloadModeLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hardware Download Mode:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="gsDownloadMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Accurate (Recommended)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Disable Readbacks (Synchronize GS Thread)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Unsynchronized (Non-Deterministic)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Disabled (Ignore Transfers)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="gsDumpCompressionLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>GS Dump Compression:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="gsDumpCompression">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Uncompressed</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>LZMA (xz)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Zstandard (zst)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="advancedLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="extendedUpscales">
|
||||
<property name="text">
|
||||
<string>Extended Upscaling Multipliers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="disableMailboxPresentation">
|
||||
<property name="text">
|
||||
<string extracomment="Mailbox Presentation: a type of graphics-rendering technique that has not been exposed to the public that often, so chances are you will need to keep the word mailbox in English. It does not have anything to do with postal mailboxes or email inboxes/outboxes.">Disable Mailbox Presentation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="useBlitSwapChain">
|
||||
<property name="text">
|
||||
<string extracomment="Blit = a data operation. You might want to write it as-is, but fully uppercased. More information: https://en.wikipedia.org/wiki/Bit_blit \nSwap chain: see Microsoft's Terminology Portal.">Use Blit Swap Chain</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="spinCPUDuringReadbacks">
|
||||
<property name="text">
|
||||
<string>Spin CPU During Readbacks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="spinGPUDuringReadbacks">
|
||||
<property name="text">
|
||||
<string>Spin GPU During Readbacks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="exclussiveFSLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Allow Exclusive Fullscreen:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="exclusiveFullscreenControl">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Automatic (Default)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Disallowed</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Allowed</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="texturePreloading">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Partial</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Full (Hash Cache)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Texture Preloading:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="frameRateOptions">
|
||||
<property name="title">
|
||||
<string>Frame Rate Options</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Disabled (Ignore Transfers)</string>
|
||||
<layout class="QGridLayout" name="frameRateOptionsFormLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="ntscLabel">
|
||||
<property name="text">
|
||||
<string>NTSC Frame Rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QDoubleSpinBox" name="ntscFrameRate">
|
||||
<property name="suffix">
|
||||
<string extracomment="Hz=Hertz, as in the measuring unit. Shown after the corresponding number. Those languages who'd need to remove the space or do something in between should do so."> Hz</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>300.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="palLabel">
|
||||
<property name="text">
|
||||
<string>PAL Frame Rate:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QDoubleSpinBox" name="palFrameRate">
|
||||
<property name="suffix">
|
||||
<string> Hz</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>300.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="debuggingOptions">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="gsDumpCompressionLabel">
|
||||
<property name="text">
|
||||
<string>GS Dump Compression:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="gsDumpCompression">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Uncompressed</string>
|
||||
<property name="title">
|
||||
<string>Debugging Options</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>LZMA (xz)</string>
|
||||
<layout class="QFormLayout" name="debuggingOptionsFormLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="barriersLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Override Texture Barriers:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="overrideTextureBarriers">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Automatic (Default)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Force Disabled</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Force Enabled</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="debuggingOptionsLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="disableFramebufferFetch">
|
||||
<property name="text">
|
||||
<string>Disable Framebuffer Fetch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="disableShaderCache">
|
||||
<property name="text">
|
||||
<string>Disable Shader Cache</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="disableVertexShaderExpand">
|
||||
<property name="text">
|
||||
<string>Disable Vertex Shader Expand</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="useDebugDevice">
|
||||
<property name="text">
|
||||
<string>Use Debug Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Zstandard (zst)</string>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="10" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="advancedLayout">
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="extendedUpscales">
|
||||
<property name="text">
|
||||
<string>Extended Upscaling Multipliers</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="disableMailboxPresentation">
|
||||
<property name="text">
|
||||
<string extracomment="Mailbox Presentation: a type of graphics-rendering technique that has not been exposed to the public that often, so chances are you will need to keep the word mailbox in English. It does not have anything to do with postal mailboxes or email inboxes/outboxes.">Disable Mailbox Presentation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="useBlitSwapChain">
|
||||
<property name="text">
|
||||
<string extracomment="Blit = a data operation. You might want to write it as-is, but fully uppercased. More information: https://en.wikipedia.org/wiki/Bit_blit \nSwap chain: see Microsoft's Terminology Portal.">Use Blit Swap Chain</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="spinCPUDuringReadbacks">
|
||||
<property name="text">
|
||||
<string>Spin CPU During Readbacks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="spinGPUDuringReadbacks">
|
||||
<property name="text">
|
||||
<string>Spin GPU During Readbacks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="exclussiveFSLabel">
|
||||
<property name="text">
|
||||
<string>Allow Exclusive Fullscreen:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QComboBox" name="exclusiveFullscreenControl">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Automatic (Default)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Disallowed</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Allowed</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QComboBox" name="texturePreloading">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>None</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Partial</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Full (Hash Cache)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Texture Preloading:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="debuggingOptions">
|
||||
<property name="title">
|
||||
<string>Debugging Options</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="debuggingOptionsFormLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="barriersLabel">
|
||||
<property name="text">
|
||||
<string>Override Texture Barriers:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="overrideTextureBarriers">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Automatic (Default)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Force Disabled</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Force Enabled</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="debuggingOptionsLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="disableFramebufferFetch">
|
||||
<property name="text">
|
||||
<string>Disable Framebuffer Fetch</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="disableShaderCache">
|
||||
<property name="text">
|
||||
<string>Disable Shader Cache</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="disableVertexShaderExpand">
|
||||
<property name="text">
|
||||
<string>Disable Vertex Shader Expand</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="useDebugDevice">
|
||||
<property name="text">
|
||||
<string>Use Debug Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
||||
@@ -260,7 +260,7 @@ void InputBindingWidget::clearBinding()
|
||||
void InputBindingWidget::reloadBinding()
|
||||
{
|
||||
m_bindings_settings = m_sif ? m_sif->GetStringList(m_section_name.c_str(), m_key_name.c_str()) :
|
||||
Host::GetBaseStringListSetting(m_section_name.c_str(), m_key_name.c_str());
|
||||
Host::GetBaseStringListSetting(m_section_name.c_str(), m_key_name.c_str());
|
||||
|
||||
m_bindings_ui.clear();
|
||||
m_bindings_ui.reserve(m_bindings_settings.size());
|
||||
|
||||
@@ -250,7 +250,7 @@ void MemoryCardConvertDialog::ConvertCard()
|
||||
baseName.replace(extensionPos, 4, "");
|
||||
// Add _converted to the end of it
|
||||
baseName.append("_converted");
|
||||
|
||||
|
||||
size_t num = 0;
|
||||
QString destName = baseName;
|
||||
destName.append(".ps2");
|
||||
@@ -322,5 +322,5 @@ void MemoryCardConvertDialog::SetType_Folder()
|
||||
|
||||
void MemoryCardConvertDialog::FileOpenError(const QString errmsg)
|
||||
{
|
||||
QMessageBox::critical(this, tr("Cannot Convert Memory Card"),tr("There was an error when accessing the memory card directory. Error message: %0").arg(errmsg));
|
||||
QMessageBox::critical(this, tr("Cannot Convert Memory Card"), tr("There was an error when accessing the memory card directory. Error message: %0").arg(errmsg));
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ private:
|
||||
void SetType_64();
|
||||
void SetType_Folder();
|
||||
void FileOpenError(const QString errmsg);
|
||||
|
||||
|
||||
Ui::MemoryCardConvertDialog m_ui;
|
||||
|
||||
bool isSetup = false;
|
||||
@@ -57,7 +57,7 @@ private:
|
||||
static constexpr u32 FLAGS = FILESYSTEM_FIND_RECURSIVE | FILESYSTEM_FIND_FOLDERS | FILESYSTEM_FIND_FILES;
|
||||
};
|
||||
|
||||
// Card capacities computed from freshly formatted superblocks.
|
||||
// Card capacities computed from freshly formatted superblocks.
|
||||
namespace CardCapacity
|
||||
{
|
||||
static constexpr size_t _8_MB = 0x1f40 * 512 * 2; //(0x1fc7 - 0x29) * 2 * 512;
|
||||
|
||||
@@ -75,7 +75,7 @@ bool MemoryCardConvertWorker::ConvertToFile(const std::string& srcFolderName, co
|
||||
{
|
||||
sourceFolderMemoryCard.Read(sourceBuffer.data() + address, address, FolderMemoryCard::PageSizeRaw);
|
||||
address += FolderMemoryCard::PageSizeRaw;
|
||||
|
||||
|
||||
// Only report progress every 16 pages. Substantially speeds up the conversion.
|
||||
if (address % (FolderMemoryCard::PageSizeRaw * 16) == 0)
|
||||
this->SetProgressValue(address);
|
||||
@@ -140,7 +140,7 @@ bool MemoryCardConvertWorker::ConvertToFolder(const std::string& srcFileName, co
|
||||
{
|
||||
targetFolderMemoryCard.Save(sourceBuffer.data() + address, address, FolderMemoryCard::PageSizeRaw);
|
||||
address += FolderMemoryCard::PageSizeRaw;
|
||||
|
||||
|
||||
// Only report progress every 16 pages. Substantially speeds up the conversion.
|
||||
if (address % (FolderMemoryCard::PageSizeRaw * 16) == 0)
|
||||
this->SetProgressValue(address + (i * sourceBuffer.size()));
|
||||
|
||||
@@ -101,7 +101,7 @@ void MemoryCardCreateDialog::createCard()
|
||||
const QString name = m_ui.name->text();
|
||||
const std::string name_str = QStringLiteral("%1.%2").arg(name)
|
||||
.arg((m_fileType == MemoryCardFileType::PS1) ? QStringLiteral("mcr") : QStringLiteral("ps2"))
|
||||
.toStdString();
|
||||
.toStdString();
|
||||
if (!Path::IsValidFileName(name_str, false))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Create Memory Card"),
|
||||
@@ -123,7 +123,7 @@ void MemoryCardCreateDialog::createCard()
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _WIN32
|
||||
if (m_type == MemoryCardType::File)
|
||||
{
|
||||
const std::string fullPath = Path::Combine(EmuFolders::MemoryCards, name_str);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -701,13 +701,13 @@ uint32_t Achievements::ClientReadMemory(uint32_t address, uint8_t* buffer, uint3
|
||||
void Achievements::ClientServerCall(
|
||||
const rc_api_request_t* request, rc_client_server_callback_t callback, void* callback_data, rc_client_t* client)
|
||||
{
|
||||
HTTPDownloader::Request::Callback hd_callback = [callback, callback_data](s32 status_code, const std::string& content_type,
|
||||
HTTPDownloader::Request::Data data) {
|
||||
HTTPDownloader::Request::Callback hd_callback = [callback, callback_data](s32 status_code, const std::string& content_type, HTTPDownloader::Request::Data data)
|
||||
{
|
||||
rc_api_server_response_t rr;
|
||||
rr.http_status_code = (status_code <= 0) ? (status_code == HTTPDownloader::HTTP_STATUS_CANCELLED ?
|
||||
RC_API_SERVER_RESPONSE_CLIENT_ERROR :
|
||||
RC_API_SERVER_RESPONSE_RETRYABLE_CLIENT_ERROR) :
|
||||
status_code;
|
||||
RC_API_SERVER_RESPONSE_CLIENT_ERROR :
|
||||
RC_API_SERVER_RESPONSE_RETRYABLE_CLIENT_ERROR)
|
||||
: status_code;
|
||||
rr.body_length = data.size();
|
||||
rr.body = reinterpret_cast<const char*>(data.data());
|
||||
|
||||
@@ -1486,7 +1486,7 @@ bool Achievements::ResetHardcoreMode(bool is_booting)
|
||||
// because the gameid can be cached, and identify immediately on GameChanged(),
|
||||
// which gets called before ResetHardcoreMode().
|
||||
const bool wanted_hardcore_mode = (IsLoggedInOrLoggingIn() || s_load_game_request) &&
|
||||
EmuConfig.Achievements.HardcoreMode;
|
||||
EmuConfig.Achievements.HardcoreMode;
|
||||
if (s_hardcore_mode == wanted_hardcore_mode)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -12,13 +12,15 @@ using namespace R5900::Interpreter;
|
||||
//#define CP2COND (vif1Regs.stat.VEW)
|
||||
|
||||
//Run the FINISH either side of the VCALL's as we have no control over it past here.
|
||||
void VCALLMS() {
|
||||
void VCALLMS()
|
||||
{
|
||||
_vu0FinishMicro();
|
||||
vu0ExecMicro(((cpuRegs.code >> 6) & 0x7FFF));
|
||||
//vif0Regs.stat.VEW = false;
|
||||
}
|
||||
|
||||
void VCALLMSR() {
|
||||
void VCALLMSR()
|
||||
{
|
||||
_vu0FinishMicro();
|
||||
vu0ExecMicro(VU0.VI[REG_CMSAR0].US[0]);
|
||||
//vif0Regs.stat.VEW = false;
|
||||
@@ -50,7 +52,7 @@ void BC2FL()
|
||||
}
|
||||
else
|
||||
{
|
||||
cpuRegs.pc+= 4;
|
||||
cpuRegs.pc += 4;
|
||||
}
|
||||
}
|
||||
void BC2TL()
|
||||
@@ -62,6 +64,6 @@ void BC2TL()
|
||||
}
|
||||
else
|
||||
{
|
||||
cpuRegs.pc+= 4;
|
||||
cpuRegs.pc += 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace
|
||||
// When this happens, the cache still fills with the data and when it gets evicted the data is lost.
|
||||
// We don't emulate memory access on a logic level, so we need to ensure that we don't try to load/store to a non-existant physical address.
|
||||
// This fixes the Find My Own Way demo.
|
||||
|
||||
|
||||
// The lower parts of a cache tags structure is as follows:
|
||||
// 31 - 12: The physical address cache tag.
|
||||
// 11: Used by PCSX2 to indicate if the physical address is valid.
|
||||
@@ -468,7 +468,7 @@ namespace R5900
|
||||
const int way = addr & 0x1;
|
||||
CacheLine line = cache.lineAt(index, way);
|
||||
|
||||
line.tag.setAddr(cpuRegs.CP0.n.TagLo);
|
||||
line.tag.setAddr(cpuRegs.CP0.n.TagLo);
|
||||
line.tag.rawValue &= ~CacheTag::ALL_FLAGS;
|
||||
line.tag.rawValue |= (cpuRegs.CP0.n.TagLo & CacheTag::ALL_FLAGS);
|
||||
|
||||
|
||||
@@ -704,6 +704,11 @@ struct Pcsx2Config
|
||||
static constexpr int DEFAULT_AUDIO_CAPTURE_BITRATE = 192;
|
||||
static const char* DEFAULT_CAPTURE_CONTAINER;
|
||||
|
||||
static constexpr int DEFAULT_SHADEBOOST_BRIGHTNESS = 50;
|
||||
static constexpr int DEFAULT_SHADEBOOST_CONTRAST = 50;
|
||||
static constexpr int DEFAULT_SHADEBOOST_GAMMA = 50;
|
||||
static constexpr int DEFAULT_SHADEBOOST_SATURATION = 50;
|
||||
|
||||
union
|
||||
{
|
||||
u64 bitset;
|
||||
@@ -781,7 +786,8 @@ struct Pcsx2Config
|
||||
EnableVideoCaptureParameters : 1,
|
||||
VideoCaptureAutoResolution : 1,
|
||||
EnableAudioCapture : 1,
|
||||
EnableAudioCaptureParameters : 1;
|
||||
EnableAudioCaptureParameters : 1,
|
||||
OrganizeScreenshotsByGame : 1;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -836,9 +842,10 @@ struct Pcsx2Config
|
||||
s8 OverrideTextureBarriers = -1;
|
||||
|
||||
u8 CAS_Sharpness = 50;
|
||||
u8 ShadeBoost_Brightness = 50;
|
||||
u8 ShadeBoost_Contrast = 50;
|
||||
u8 ShadeBoost_Saturation = 50;
|
||||
u8 ShadeBoost_Brightness = DEFAULT_SHADEBOOST_BRIGHTNESS;
|
||||
u8 ShadeBoost_Contrast = DEFAULT_SHADEBOOST_CONTRAST;
|
||||
u8 ShadeBoost_Saturation = DEFAULT_SHADEBOOST_SATURATION;
|
||||
u8 ShadeBoost_Gamma = DEFAULT_SHADEBOOST_GAMMA;
|
||||
u8 PNGCompressionLevel = 1;
|
||||
|
||||
u16 SWExtraThreads = 2;
|
||||
@@ -1428,10 +1435,12 @@ namespace EmuFolders
|
||||
|
||||
// ------------ CPU / Recompiler Options ---------------
|
||||
|
||||
#ifdef _M_X86 // TODO(Stenzek): Remove me once EE/VU/IOP recs are added.
|
||||
#define THREAD_VU1 (EmuConfig.Cpu.Recompiler.EnableVU1 && EmuConfig.Speedhacks.vuThread)
|
||||
#ifdef _M_X86 // TODO: Remove me once EE/VU/IOP recs are added.
|
||||
#define REC_VU1 (EmuConfig.Cpu.Recompiler.EnableVU1)
|
||||
#define THREAD_VU1 (REC_VU1 && EmuConfig.Speedhacks.vuThread)
|
||||
#else
|
||||
#define THREAD_VU1 false
|
||||
#define REC_VU1 false
|
||||
#endif
|
||||
#define INSTANT_VU1 (EmuConfig.Speedhacks.vu1Instant)
|
||||
#define CHECK_EEREC (EmuConfig.Cpu.Recompiler.EnableEE)
|
||||
|
||||
@@ -234,7 +234,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, double framesPerSecond, u32 sca
|
||||
{
|
||||
hBlank /= 2;
|
||||
hRender /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Carry fixed-point math all the way through the entire vsync and hsync counting processes, and continually apply rounding
|
||||
//as needed for each scheduled v/hsync related event. Much better to handle than this messed state.
|
||||
@@ -412,8 +412,8 @@ void UpdateVSyncRate(bool force)
|
||||
s32 vdiff = vsyncCounter.deltaCycles;
|
||||
hsyncCounter.deltaCycles = (hsyncCounter.Mode == MODE_HBLANK) ? vSyncInfo.hBlank : vSyncInfo.hRender;
|
||||
vsyncCounter.deltaCycles = (vsyncCounter.Mode == MODE_GSBLANK) ?
|
||||
vSyncInfo.GSBlank :
|
||||
((vsyncCounter.Mode == MODE_VBLANK) ? vSyncInfo.Blank : vSyncInfo.Render);
|
||||
vSyncInfo.GSBlank :
|
||||
((vsyncCounter.Mode == MODE_VBLANK) ? vSyncInfo.Blank : vSyncInfo.Render);
|
||||
|
||||
hsyncCounter.startCycle += hdiff - hsyncCounter.deltaCycles;
|
||||
vsyncCounter.startCycle += vdiff - vsyncCounter.deltaCycles;
|
||||
@@ -653,10 +653,10 @@ __fi void rcntUpdate_hScanline()
|
||||
}
|
||||
else
|
||||
{ //HBLANK START / HRENDER End
|
||||
|
||||
|
||||
// set up the hblank's start and end cycle information:
|
||||
hsyncCounter.startCycle += vSyncInfo.hRender; // start (absolute cycle value)
|
||||
hsyncCounter.deltaCycles = vSyncInfo.hBlank; // endpoint (delta from start value)
|
||||
hsyncCounter.deltaCycles = vSyncInfo.hBlank; // endpoint (delta from start value)
|
||||
if (!GSSMODE1reg.SINT)
|
||||
{
|
||||
if (!CSRreg.HSINT)
|
||||
@@ -765,7 +765,7 @@ __fi void rcntUpdate()
|
||||
rcntSyncCounter(i);
|
||||
|
||||
if (counters[i].mode.ClockSource == 0x3 || !rcntCanCount(i)) // don't count hblank sources
|
||||
continue;
|
||||
continue;
|
||||
|
||||
_cpuTestOverflow(i);
|
||||
_cpuTestTarget(i);
|
||||
@@ -813,7 +813,7 @@ static __fi void rcntStartGate(bool isVblank, u32 sCycle)
|
||||
|
||||
switch (counters[i].mode.GateMode)
|
||||
{
|
||||
case 0x0: //Count When Signal is low (V_RENDER ONLY)
|
||||
case 0x0: // Count When Signal is low (V_RENDER ONLY)
|
||||
|
||||
// Just set the start cycle -- counting will be done as needed
|
||||
// for events (overflows, targets, mode changes, and the gate off below)
|
||||
@@ -955,7 +955,7 @@ __fi u32 rcntRcount(int index)
|
||||
u32 ret;
|
||||
|
||||
rcntSyncCounter(index);
|
||||
|
||||
|
||||
ret = counters[index].count;
|
||||
|
||||
// Spams the Console.
|
||||
|
||||
@@ -355,10 +355,10 @@ bool GSopen(const Pcsx2Config::GSOptions& config, GSRendererType renderer, u8* b
|
||||
|
||||
if (!res)
|
||||
{
|
||||
Host::ReportErrorAsync(
|
||||
"Error", fmt::format(TRANSLATE_FS("GS","Failed to create render device. This may be due to your GPU not supporting the "
|
||||
"chosen renderer ({}), or because your graphics drivers need to be updated."),
|
||||
Pcsx2Config::GSOptions::GetRendererName(GSConfig.Renderer)));
|
||||
Host::ReportErrorAsync("Error",
|
||||
fmt::format(TRANSLATE_FS("GS", "Failed to create render device. This may be due to your GPU not supporting the "
|
||||
"chosen renderer ({}), or because your graphics drivers need to be updated."),
|
||||
Pcsx2Config::GSOptions::GetRendererName(GSConfig.Renderer)));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -500,7 +500,7 @@ void GSEndCapture()
|
||||
{
|
||||
if (g_gs_renderer)
|
||||
g_gs_renderer->EndCapture();
|
||||
}
|
||||
}
|
||||
|
||||
void GSPresentCurrentFrame()
|
||||
{
|
||||
@@ -661,7 +661,7 @@ void GSgetStats(SmallStringBase& info)
|
||||
const double fillrate = pm.Get(GSPerfMon::Fillrate);
|
||||
double pps = fps * fillrate;
|
||||
char prefix = '\0';
|
||||
|
||||
|
||||
if (pps >= 170000000)
|
||||
{
|
||||
pps /= 1073741824; // Gpps
|
||||
@@ -689,7 +689,7 @@ void GSgetStats(SmallStringBase& info)
|
||||
(int)pm.Get(GSPerfMon::Draw),
|
||||
pm.Get(GSPerfMon::Swizzle) / 1024,
|
||||
pm.Get(GSPerfMon::Unswizzle) / 1024,
|
||||
pps,prefix);
|
||||
pps, prefix);
|
||||
}
|
||||
else if (GSCurrentRenderer == GSRendererType::Null)
|
||||
{
|
||||
|
||||
@@ -1384,12 +1384,12 @@ TinyString GSCapture::GetElapsedTime()
|
||||
if (s_video_stream)
|
||||
{
|
||||
seconds = (s_next_video_pts * static_cast<s64>(s_video_codec_context->time_base.num)) /
|
||||
static_cast<s64>(s_video_codec_context->time_base.den);
|
||||
static_cast<s64>(s_video_codec_context->time_base.den);
|
||||
}
|
||||
else if (s_audio_stream)
|
||||
{
|
||||
seconds = (s_next_audio_pts * static_cast<s64>(s_audio_codec_context->time_base.num)) /
|
||||
static_cast<s64>(s_audio_codec_context->time_base.den);
|
||||
static_cast<s64>(s_audio_codec_context->time_base.den);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace GSCapture
|
||||
CodecList GetVideoCodecList(const char* container);
|
||||
CodecList GetAudioCodecList(const char* container);
|
||||
|
||||
using FormatName = std::pair<int , std::string>; // id,name
|
||||
using FormatName = std::pair<int, std::string>; // id,name
|
||||
using FormatList = std::vector<FormatName>;
|
||||
FormatList GetVideoFormatList(const char* codec);
|
||||
}; // namespace GSCapture
|
||||
|
||||
@@ -185,7 +185,7 @@ bool GSClut::CanLoadCLUT(const GIFRegTEX0& TEX0, const bool update_CBP)
|
||||
case 4:
|
||||
if (m_CBP[0] == TEX0.CBP)
|
||||
return false;
|
||||
if(update_CBP)
|
||||
if (update_CBP)
|
||||
m_CBP[0] = TEX0.CBP;
|
||||
break;
|
||||
case 5:
|
||||
@@ -531,7 +531,7 @@ void GSClut::GetAlphaMinMax32(int& amin_out, int& amax_out)
|
||||
void GSClut::WriteCLUT_T32_I8_CSM1(const u32* RESTRICT src, u16* RESTRICT clut, u16 offset)
|
||||
{
|
||||
// This is required when CSA is offset from the base of the CLUT so we point to the right data
|
||||
for (int i = offset; i < 16; i ++)
|
||||
for (int i = offset; i < 16; i++)
|
||||
{
|
||||
const int off = i << 4; // WriteCLUT_T32_I4_CSM1 loads 16 at a time
|
||||
// Source column
|
||||
|
||||
@@ -509,15 +509,15 @@ GSVector4i GSLocalMemory::GetRectForPageOffset(u32 base_bp, u32 offset_bp, u32 b
|
||||
return GSVector4i(pgs * page_offset_xy).xyxy() + GSVector4i::loadh(pgs);
|
||||
}
|
||||
|
||||
bool GSLocalMemory::HasOverlap(const u32 src_bp, const u32 src_bw, const u32 src_psm, const GSVector4i src_rect
|
||||
, const u32 dst_bp, const u32 dst_bw, const u32 dst_psm, const GSVector4i dst_rect)
|
||||
bool GSLocalMemory::HasOverlap(const u32 src_bp, const u32 src_bw, const u32 src_psm, const GSVector4i src_rect,
|
||||
const u32 dst_bp, const u32 dst_bw, const u32 dst_psm, const GSVector4i dst_rect)
|
||||
{
|
||||
const u32 src_start_bp = GSLocalMemory::GetStartBlockAddress(src_bp, src_bw, src_psm, src_rect) & ~(GS_BLOCKS_PER_PAGE - 1);
|
||||
const u32 dst_start_bp = GSLocalMemory::GetStartBlockAddress(dst_bp, dst_bw, dst_psm, dst_rect) & ~(GS_BLOCKS_PER_PAGE - 1);
|
||||
|
||||
u32 src_end_bp = ((GSLocalMemory::GetEndBlockAddress(src_bp, src_bw, src_psm, src_rect) + 1) + (GS_BLOCKS_PER_PAGE - 1)) & ~(GS_BLOCKS_PER_PAGE - 1);
|
||||
u32 dst_end_bp = ((GSLocalMemory::GetEndBlockAddress(dst_bp, dst_bw, dst_psm, dst_rect) + 1) + (GS_BLOCKS_PER_PAGE - 1)) & ~(GS_BLOCKS_PER_PAGE - 1);
|
||||
|
||||
|
||||
if (src_start_bp == src_end_bp)
|
||||
{
|
||||
src_end_bp = (src_end_bp + GS_BLOCKS_PER_PAGE) & ~(GS_MAX_BLOCKS - 1);
|
||||
|
||||
@@ -23,7 +23,7 @@ void GSPerfMon::EndFrame(bool frame_only)
|
||||
{
|
||||
m_frame++;
|
||||
|
||||
if(!frame_only)
|
||||
if (!frame_only)
|
||||
m_count++;
|
||||
}
|
||||
|
||||
|
||||
@@ -2916,14 +2916,14 @@ void GSState::GrowVertexBuffer()
|
||||
u32 old_size;
|
||||
u32 new_size;
|
||||
};
|
||||
std::vector<AllocDesc> alloc_desc = {
|
||||
const std::array<AllocDesc, 5> alloc_desc = {{
|
||||
{reinterpret_cast<void**>(&m_vertex.buff), old_vertex_size, new_vertex_size},
|
||||
// discard contents of buff_copy by setting old_size = 0
|
||||
{reinterpret_cast<void**>(&m_vertex.buff_copy), 0, new_vertex_size},
|
||||
{reinterpret_cast<void**>(&m_draw_vertex.buff), old_vertex_size, new_vertex_size},
|
||||
{reinterpret_cast<void**>(&m_index.buff), old_index_size, new_index_size},
|
||||
{reinterpret_cast<void**>(&m_draw_index.buff), old_index_size, new_index_size}
|
||||
};
|
||||
}};
|
||||
|
||||
// For logging
|
||||
u32 total_size = 0;
|
||||
|
||||
@@ -25,38 +25,12 @@
|
||||
namespace {
|
||||
struct GSUtilMaps
|
||||
{
|
||||
u8 PrimClassField[8] = {};
|
||||
u8 VertexCountField[8] = {};
|
||||
u8 ClassVertexCountField[4] = {};
|
||||
u32 CompatibleBitsField[64][2] = {};
|
||||
u32 SharedBitsField[64][2] = {};
|
||||
u32 SwizzleField[64][2] = {};
|
||||
|
||||
constexpr GSUtilMaps()
|
||||
{
|
||||
PrimClassField[GS_POINTLIST] = GS_POINT_CLASS;
|
||||
PrimClassField[GS_LINELIST] = GS_LINE_CLASS;
|
||||
PrimClassField[GS_LINESTRIP] = GS_LINE_CLASS;
|
||||
PrimClassField[GS_TRIANGLELIST] = GS_TRIANGLE_CLASS;
|
||||
PrimClassField[GS_TRIANGLESTRIP] = GS_TRIANGLE_CLASS;
|
||||
PrimClassField[GS_TRIANGLEFAN] = GS_TRIANGLE_CLASS;
|
||||
PrimClassField[GS_SPRITE] = GS_SPRITE_CLASS;
|
||||
PrimClassField[GS_INVALID] = GS_INVALID_CLASS;
|
||||
|
||||
VertexCountField[GS_POINTLIST] = 1;
|
||||
VertexCountField[GS_LINELIST] = 2;
|
||||
VertexCountField[GS_LINESTRIP] = 2;
|
||||
VertexCountField[GS_TRIANGLELIST] = 3;
|
||||
VertexCountField[GS_TRIANGLESTRIP] = 3;
|
||||
VertexCountField[GS_TRIANGLEFAN] = 3;
|
||||
VertexCountField[GS_SPRITE] = 2;
|
||||
VertexCountField[GS_INVALID] = 1;
|
||||
|
||||
ClassVertexCountField[GS_POINT_CLASS] = 1;
|
||||
ClassVertexCountField[GS_LINE_CLASS] = 2;
|
||||
ClassVertexCountField[GS_TRIANGLE_CLASS] = 3;
|
||||
ClassVertexCountField[GS_SPRITE_CLASS] = 2;
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
CompatibleBitsField[i][i >> 5] |= 1U << (i & 0x1f);
|
||||
@@ -120,21 +94,6 @@ const char* GSUtil::GetAFAILName(u32 afail)
|
||||
return (afail < std::size(names)) ? names[afail] : "";
|
||||
}
|
||||
|
||||
GS_PRIM_CLASS GSUtil::GetPrimClass(u32 prim)
|
||||
{
|
||||
return (GS_PRIM_CLASS)s_maps.PrimClassField[prim];
|
||||
}
|
||||
|
||||
int GSUtil::GetVertexCount(u32 prim)
|
||||
{
|
||||
return s_maps.VertexCountField[prim];
|
||||
}
|
||||
|
||||
int GSUtil::GetClassVertexCount(u32 primclass)
|
||||
{
|
||||
return s_maps.ClassVertexCountField[primclass];
|
||||
}
|
||||
|
||||
const u32* GSUtil::HasSharedBitsPtr(u32 dpsm)
|
||||
{
|
||||
return s_maps.SharedBitsField[dpsm];
|
||||
|
||||
@@ -13,10 +13,6 @@ public:
|
||||
static const char* GetAFAILName(u32 afail);
|
||||
static const char* GetPSMName(int psm);
|
||||
|
||||
static GS_PRIM_CLASS GetPrimClass(u32 prim);
|
||||
static int GetVertexCount(u32 prim);
|
||||
static int GetClassVertexCount(u32 primclass);
|
||||
|
||||
static const u32* HasSharedBitsPtr(u32 dpsm);
|
||||
static bool HasSharedBits(u32 spsm, const u32* ptr);
|
||||
static bool HasSharedBits(u32 spsm, u32 dpsm);
|
||||
@@ -27,4 +23,41 @@ public:
|
||||
static u32 GetChannelMask(u32 spsm, u32 fbmsk);
|
||||
|
||||
static GSRendererType GetPreferredRenderer();
|
||||
|
||||
static constexpr GS_PRIM_CLASS GetPrimClass(u32 prim)
|
||||
{
|
||||
switch (prim)
|
||||
{
|
||||
case GS_POINTLIST:
|
||||
return GS_POINT_CLASS;
|
||||
case GS_LINELIST:
|
||||
case GS_LINESTRIP:
|
||||
return GS_LINE_CLASS;
|
||||
case GS_TRIANGLELIST:
|
||||
case GS_TRIANGLESTRIP:
|
||||
case GS_TRIANGLEFAN:
|
||||
return GS_TRIANGLE_CLASS;
|
||||
case GS_SPRITE:
|
||||
return GS_SPRITE_CLASS;
|
||||
default:
|
||||
return GS_INVALID_CLASS;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr int GetClassVertexCount(u32 primclass)
|
||||
{
|
||||
switch (primclass)
|
||||
{
|
||||
case GS_POINT_CLASS: return 1;
|
||||
case GS_LINE_CLASS: return 2;
|
||||
case GS_TRIANGLE_CLASS: return 3;
|
||||
case GS_SPRITE_CLASS: return 2;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr int GetVertexCount(u32 prim)
|
||||
{
|
||||
return GetClassVertexCount(GetPrimClass(prim));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -835,6 +835,7 @@ void GSDevice::ShadeBoost()
|
||||
static_cast<float>(GSConfig.ShadeBoost_Brightness) * (1.0f / 50.0f),
|
||||
static_cast<float>(GSConfig.ShadeBoost_Contrast) * (1.0f / 50.0f),
|
||||
static_cast<float>(GSConfig.ShadeBoost_Saturation) * (1.0f / 50.0f),
|
||||
static_cast<float>(GSConfig.ShadeBoost_Gamma) * (1.0f / 50.0f),
|
||||
};
|
||||
|
||||
DoShadeBoost(m_current, m_target_tmp, params);
|
||||
|
||||
@@ -876,7 +876,30 @@ static std::string GSGetBaseFilename()
|
||||
std::string GSGetBaseSnapshotFilename()
|
||||
{
|
||||
// prepend snapshots directory
|
||||
return Path::Combine(EmuFolders::Snapshots, GSGetBaseFilename());
|
||||
std::string base_path = EmuFolders::Snapshots;
|
||||
|
||||
// If organize by game is enabled, create a game-specific folder
|
||||
if (GSConfig.OrganizeScreenshotsByGame)
|
||||
{
|
||||
std::string game_name = VMManager::GetTitle(true);
|
||||
if (!game_name.empty())
|
||||
{
|
||||
Path::SanitizeFileName(&game_name);
|
||||
if (game_name.length() > 219)
|
||||
{
|
||||
game_name.resize(219);
|
||||
}
|
||||
const std::string game_dir = Path::Combine(base_path, game_name);
|
||||
if (!FileSystem::DirectoryExists(game_dir.c_str()))
|
||||
{
|
||||
FileSystem::CreateDirectoryPath(game_dir.c_str(), false);
|
||||
}
|
||||
|
||||
base_path = game_dir;
|
||||
}
|
||||
}
|
||||
|
||||
return Path::Combine(base_path, GSGetBaseFilename());
|
||||
}
|
||||
|
||||
std::string GSGetBaseVideoFilename()
|
||||
|
||||
@@ -586,8 +586,8 @@ void GSDevice11::SetFeatures(IDXGIAdapter1* adapter)
|
||||
{
|
||||
// Check all three formats, since the feature means any can be used.
|
||||
m_features.dxt_textures = SupportsTextureFormat(m_dev.get(), DXGI_FORMAT_BC1_UNORM) &&
|
||||
SupportsTextureFormat(m_dev.get(), DXGI_FORMAT_BC2_UNORM) &&
|
||||
SupportsTextureFormat(m_dev.get(), DXGI_FORMAT_BC3_UNORM);
|
||||
SupportsTextureFormat(m_dev.get(), DXGI_FORMAT_BC2_UNORM) &&
|
||||
SupportsTextureFormat(m_dev.get(), DXGI_FORMAT_BC3_UNORM);
|
||||
|
||||
m_features.bptc_textures = SupportsTextureFormat(m_dev.get(), DXGI_FORMAT_BC7_UNORM);
|
||||
|
||||
@@ -595,8 +595,8 @@ void GSDevice11::SetFeatures(IDXGIAdapter1* adapter)
|
||||
m_features.cas_sharpening = (m_feature_level >= D3D_FEATURE_LEVEL_11_0);
|
||||
|
||||
m_max_texture_size = (m_feature_level >= D3D_FEATURE_LEVEL_11_0) ?
|
||||
D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION :
|
||||
D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION :
|
||||
D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
}
|
||||
|
||||
bool GSDevice11::HasSurface() const
|
||||
@@ -752,7 +752,7 @@ bool GSDevice11::CreateSwapChain()
|
||||
else
|
||||
{
|
||||
Console.ErrorFmt("D3D11: GetParent() on swap chain to get factory failed: {}", Error::CreateHResult(hr).GetDescription());
|
||||
}
|
||||
}
|
||||
|
||||
if (!CreateSwapChainRTV())
|
||||
{
|
||||
@@ -801,7 +801,7 @@ bool GSDevice11::CreateSwapChainRTV()
|
||||
SUCCEEDED(m_swap_chain->GetDesc(&desc)))
|
||||
{
|
||||
m_window_info.surface_refresh_rate = static_cast<float>(desc.BufferDesc.RefreshRate.Numerator) /
|
||||
static_cast<float>(desc.BufferDesc.RefreshRate.Denominator);
|
||||
static_cast<float>(desc.BufferDesc.RefreshRate.Denominator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1263,7 +1263,7 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, bool red, bool green, bool blue, bool alpha, ShaderConvert shader)
|
||||
{
|
||||
const u8 index = static_cast<u8>(red) | (static_cast<u8>(green) << 1) | (static_cast<u8>(blue) << 2) |
|
||||
(static_cast<u8>(alpha) << 3);
|
||||
(static_cast<u8>(alpha) << 3);
|
||||
StretchRect(sTex, sRect, dTex, dRect, m_convert.ps[static_cast<int>(shader)].get(), nullptr,
|
||||
m_convert.bs[index].get(), false);
|
||||
}
|
||||
@@ -1316,7 +1316,7 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
|
||||
};
|
||||
|
||||
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices));
|
||||
IASetVertexBuffer(vertices, sizeof(vertices[0]), std::size(vertices));
|
||||
IASetInputLayout(m_convert.il.get());
|
||||
IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
|
||||
@@ -1795,8 +1795,8 @@ void GSDevice11::SetupPS(const PSSelector& sel, const GSHWDrawConfig::PSConstant
|
||||
}};
|
||||
|
||||
const u8 index = (static_cast<u8>(ssel.IsMipFilterLinear()) << 2) |
|
||||
(static_cast<u8>(ssel.IsMagFilterLinear()) << 1) |
|
||||
static_cast<u8>(ssel.IsMinFilterLinear());
|
||||
(static_cast<u8>(ssel.IsMagFilterLinear()) << 1) |
|
||||
static_cast<u8>(ssel.IsMinFilterLinear());
|
||||
sd.Filter = filters[index];
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ bool GSTexture11::Update(const GSVector4i& r, const void* data, int pitch, int l
|
||||
g_perfmon.Put(GSPerfMon::TextureUploads, 1);
|
||||
|
||||
const u32 bs = GetCompressedBlockSize();
|
||||
|
||||
|
||||
const D3D11_BOX box = {Common::AlignDownPow2((u32)r.left, bs), Common::AlignDownPow2((u32)r.top, bs), 0U,
|
||||
Common::AlignUpPow2((u32)r.right, bs), Common::AlignUpPow2((u32)r.bottom, bs), 1U};
|
||||
const UINT subresource = layer; // MipSlice + (ArraySlice * MipLevels).
|
||||
|
||||
@@ -134,7 +134,7 @@ bool GSDevice12::SupportsTextureFormat(DXGI_FORMAT format)
|
||||
|
||||
D3D12_FEATURE_DATA_FORMAT_SUPPORT support = {format};
|
||||
return SUCCEEDED(m_device->CheckFeatureSupport(D3D12_FEATURE_FORMAT_SUPPORT, &support, sizeof(support))) &&
|
||||
(support.Support1 & required) == required;
|
||||
(support.Support1 & required) == required;
|
||||
}
|
||||
|
||||
u32 GSDevice12::GetAdapterVendorID() const
|
||||
@@ -958,7 +958,7 @@ bool GSDevice12::CreateSwapChainRTV()
|
||||
SUCCEEDED(m_swap_chain->GetDesc(&desc)))
|
||||
{
|
||||
m_window_info.surface_refresh_rate = static_cast<float>(desc.BufferDesc.RefreshRate.Numerator) /
|
||||
static_cast<float>(desc.BufferDesc.RefreshRate.Denominator);
|
||||
static_cast<float>(desc.BufferDesc.RefreshRate.Denominator);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1238,8 +1238,8 @@ bool GSDevice12::CheckFeatures(const u32& vendor_id)
|
||||
m_features.vs_expand = !GSConfig.DisableVertexShaderExpand;
|
||||
|
||||
m_features.dxt_textures = SupportsTextureFormat(DXGI_FORMAT_BC1_UNORM) &&
|
||||
SupportsTextureFormat(DXGI_FORMAT_BC2_UNORM) &&
|
||||
SupportsTextureFormat(DXGI_FORMAT_BC3_UNORM);
|
||||
SupportsTextureFormat(DXGI_FORMAT_BC2_UNORM) &&
|
||||
SupportsTextureFormat(DXGI_FORMAT_BC3_UNORM);
|
||||
m_features.bptc_textures = SupportsTextureFormat(DXGI_FORMAT_BC7_UNORM);
|
||||
|
||||
m_max_texture_size = D3D12_REQ_TEXTURE2D_U_OR_V_DIMENSION;
|
||||
@@ -1643,8 +1643,8 @@ void GSDevice12::BeginRenderPassForStretchRect(
|
||||
GSTexture12* dTex, const GSVector4i& dtex_rc, const GSVector4i& dst_rc, bool allow_discard)
|
||||
{
|
||||
const D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE load_op = (allow_discard && dst_rc.eq(dtex_rc)) ?
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD :
|
||||
GetLoadOpForTexture(dTex);
|
||||
D3D12_RENDER_PASS_BEGINNING_ACCESS_TYPE_DISCARD :
|
||||
GetLoadOpForTexture(dTex);
|
||||
dTex->SetState(GSTexture::State::Dirty);
|
||||
|
||||
if (dTex->GetType() != GSTexture::Type::DepthStencil)
|
||||
@@ -1742,8 +1742,8 @@ void GSDevice12::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
|
||||
(sTex[0] && (sTex[0]->GetState() == GSTexture::State::Dirty ||
|
||||
(sTex[0]->GetState() == GSTexture::State::Cleared || sTex[0]->GetClearColor() != 0)));
|
||||
const bool has_input_1 = (PMODE.SLBG == 0 || feedback_write_2_but_blend_bg) && sTex[1] &&
|
||||
(sTex[1]->GetState() == GSTexture::State::Dirty ||
|
||||
(sTex[1]->GetState() == GSTexture::State::Cleared || sTex[1]->GetClearColor() != 0));
|
||||
(sTex[1]->GetState() == GSTexture::State::Dirty ||
|
||||
(sTex[1]->GetState() == GSTexture::State::Cleared || sTex[1]->GetClearColor() != 0));
|
||||
if (has_input_0)
|
||||
{
|
||||
static_cast<GSTexture12*>(sTex[0])->CommitClear();
|
||||
@@ -2261,7 +2261,7 @@ bool GSDevice12::GetSampler(D3D12DescriptorHandle* cpu_handle, GSHWDrawConfig::S
|
||||
}};
|
||||
|
||||
const u8 index = (static_cast<u8>(ss.IsMipFilterLinear()) << 2) |
|
||||
(static_cast<u8>(ss.IsMagFilterLinear()) << 1) | static_cast<u8>(ss.IsMinFilterLinear());
|
||||
(static_cast<u8>(ss.IsMagFilterLinear()) << 1) | static_cast<u8>(ss.IsMinFilterLinear());
|
||||
sd.Filter = filters[index];
|
||||
}
|
||||
|
||||
@@ -2448,8 +2448,7 @@ bool GSDevice12::CompileConvertPipelines()
|
||||
gpb.SetNoBlendingState();
|
||||
gpb.SetVertexShader(m_convert_vs.get());
|
||||
|
||||
for (ShaderConvert i = ShaderConvert::COPY; static_cast<int>(i) < static_cast<int>(ShaderConvert::Count);
|
||||
i = static_cast<ShaderConvert>(static_cast<int>(i) + 1))
|
||||
for (ShaderConvert i = ShaderConvert::COPY; i < ShaderConvert::Count; i = static_cast<ShaderConvert>(static_cast<int>(i) + 1))
|
||||
{
|
||||
const bool depth = HasDepthOutput(i);
|
||||
const int index = static_cast<int>(i);
|
||||
@@ -2621,8 +2620,7 @@ bool GSDevice12::CompilePresentPipelines()
|
||||
gpb.SetNoStencilState();
|
||||
gpb.SetRenderTarget(0, DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
|
||||
for (PresentShader i = PresentShader::COPY; static_cast<int>(i) < static_cast<int>(PresentShader::Count);
|
||||
i = static_cast<PresentShader>(static_cast<int>(i) + 1))
|
||||
for (PresentShader i = PresentShader::COPY; i < PresentShader::Count; i = static_cast<PresentShader>(static_cast<int>(i) + 1))
|
||||
{
|
||||
const int index = static_cast<int>(i);
|
||||
|
||||
@@ -2963,8 +2961,8 @@ GSDevice12::ComPtr<ID3D12PipelineState> GSDevice12::CreateTFXPipeline(const Pipe
|
||||
if (p.rt)
|
||||
{
|
||||
const GSTexture::Format format = IsDATEModePrimIDInit(p.ps.date) ?
|
||||
GSTexture::Format::PrimID :
|
||||
(p.ps.colclip_hw ? GSTexture::Format::ColorClip : GSTexture::Format::Color);
|
||||
GSTexture::Format::PrimID :
|
||||
(p.ps.colclip_hw ? GSTexture::Format::ColorClip : GSTexture::Format::Color);
|
||||
|
||||
DXGI_FORMAT native_format;
|
||||
LookupNativeFormat(format, nullptr, nullptr, &native_format, nullptr);
|
||||
@@ -3650,8 +3648,8 @@ bool GSDevice12::ApplyTFXState(bool already_execed)
|
||||
{
|
||||
m_current_root_signature = RootSignature::TFX;
|
||||
flags |= DIRTY_FLAG_VS_CONSTANT_BUFFER_BINDING | DIRTY_FLAG_PS_CONSTANT_BUFFER_BINDING |
|
||||
DIRTY_FLAG_TEXTURES_DESCRIPTOR_TABLE | DIRTY_FLAG_SAMPLERS_DESCRIPTOR_TABLE |
|
||||
DIRTY_FLAG_TEXTURES_DESCRIPTOR_TABLE_2 | DIRTY_FLAG_PIPELINE;
|
||||
DIRTY_FLAG_TEXTURES_DESCRIPTOR_TABLE | DIRTY_FLAG_SAMPLERS_DESCRIPTOR_TABLE |
|
||||
DIRTY_FLAG_TEXTURES_DESCRIPTOR_TABLE_2 | DIRTY_FLAG_PIPELINE;
|
||||
cmdlist->SetGraphicsRootSignature(m_tfx_root_signature.get());
|
||||
}
|
||||
|
||||
|
||||
@@ -544,11 +544,11 @@ private:
|
||||
DIRTY_FLAG_STENCIL_REF = (1 << 19),
|
||||
|
||||
DIRTY_BASE_STATE = DIRTY_FLAG_VS_CONSTANT_BUFFER_BINDING | DIRTY_FLAG_PS_CONSTANT_BUFFER_BINDING |
|
||||
DIRTY_FLAG_VS_VERTEX_BUFFER_BINDING | DIRTY_FLAG_TEXTURES_DESCRIPTOR_TABLE |
|
||||
DIRTY_FLAG_SAMPLERS_DESCRIPTOR_TABLE | DIRTY_FLAG_TEXTURES_DESCRIPTOR_TABLE_2 |
|
||||
DIRTY_FLAG_VERTEX_BUFFER | DIRTY_FLAG_INDEX_BUFFER | DIRTY_FLAG_PRIMITIVE_TOPOLOGY |
|
||||
DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR | DIRTY_FLAG_RENDER_TARGET | DIRTY_FLAG_PIPELINE |
|
||||
DIRTY_FLAG_BLEND_CONSTANTS | DIRTY_FLAG_STENCIL_REF,
|
||||
DIRTY_FLAG_VS_VERTEX_BUFFER_BINDING | DIRTY_FLAG_TEXTURES_DESCRIPTOR_TABLE |
|
||||
DIRTY_FLAG_SAMPLERS_DESCRIPTOR_TABLE | DIRTY_FLAG_TEXTURES_DESCRIPTOR_TABLE_2 |
|
||||
DIRTY_FLAG_VERTEX_BUFFER | DIRTY_FLAG_INDEX_BUFFER | DIRTY_FLAG_PRIMITIVE_TOPOLOGY |
|
||||
DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR | DIRTY_FLAG_RENDER_TARGET | DIRTY_FLAG_PIPELINE |
|
||||
DIRTY_FLAG_BLEND_CONSTANTS | DIRTY_FLAG_STENCIL_REF,
|
||||
|
||||
DIRTY_TFX_STATE =
|
||||
DIRTY_BASE_STATE | DIRTY_FLAG_TFX_TEXTURES | DIRTY_FLAG_TFX_SAMPLERS | DIRTY_FLAG_TFX_RT_TEXTURES,
|
||||
|
||||
@@ -125,7 +125,7 @@ std::unique_ptr<GSTexture12> GSTexture12::Create(Type type, Format format, int w
|
||||
// This is a little annoying. basically, to do mipmap generation, we need to be a render target.
|
||||
// If it's a compressed texture, we won't be generating mips anyway, so this should be fine.
|
||||
desc.Flags = (levels > 1 && !IsCompressedFormat(format)) ? D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET :
|
||||
D3D12_RESOURCE_FLAG_NONE;
|
||||
D3D12_RESOURCE_FLAG_NONE;
|
||||
state = D3D12_RESOURCE_STATE_COPY_DEST;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1093,7 +1093,7 @@ bool GSHwHack::OI_SonicUnleashed(GSRendererHW& r, GSTexture* rt, GSTexture* ds,
|
||||
rt_again->m_texture = tex;
|
||||
rt = tex;
|
||||
}
|
||||
|
||||
|
||||
GSVector2i rt_size(rt->GetSize());
|
||||
|
||||
// This is awful, but so is the CRC hack... it's a texture shuffle split horizontally instead of vertically.
|
||||
@@ -1102,14 +1102,14 @@ bool GSHwHack::OI_SonicUnleashed(GSRendererHW& r, GSTexture* rt, GSTexture* ds,
|
||||
if (rt_again->m_unscaled_size.x < src->m_unscaled_size.x || rt_again->m_unscaled_size.y < src->m_unscaled_size.y)
|
||||
{
|
||||
GSVector2i new_size = GSVector2i(std::max(rt_again->m_unscaled_size.x, src->m_unscaled_size.x),
|
||||
std::max(rt_again->m_unscaled_size.y, src->m_unscaled_size.y));
|
||||
std::max(rt_again->m_unscaled_size.y, src->m_unscaled_size.y));
|
||||
rt_again->ResizeTexture(new_size.x, new_size.y);
|
||||
rt = rt_again->m_texture;
|
||||
rt_size = new_size * GSVector2i(src->GetScale());
|
||||
rt_again->UpdateDrawn(GSVector4i::loadh(new_size));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const GSVector2i copy_size(std::min(rt_size.x, src_size.x), std::min(rt_size.y, src_size.y));
|
||||
|
||||
|
||||
@@ -332,7 +332,7 @@ void GSRendererHW::ConvertSpriteTextureShuffle(u32& process_rg, u32& process_ba,
|
||||
const GSVertex second_vert = (start_verts[0].XYZ.X <= start_verts[1].XYZ.X) ? start_verts[1] : start_verts[0];
|
||||
// vertex position is 8 to 16 pixels, therefore it is the 16-31 bits of the colors
|
||||
const int pos = (first_vert.XYZ.X - o.OFX) & 0xFF;
|
||||
|
||||
|
||||
// Read texture is 8 to 16 pixels (same as above)
|
||||
const float tw = static_cast<float>(1u << m_cached_ctx.TEX0.TW);
|
||||
int tex_pos = (PRIM->FST) ? first_vert.U : static_cast<int>(tw * first_vert.ST.S * 16.0f);
|
||||
@@ -359,7 +359,7 @@ void GSRendererHW::ConvertSpriteTextureShuffle(u32& process_rg, u32& process_ba,
|
||||
const u32 minu = (m_cached_ctx.CLAMP.MINU & 8);
|
||||
if (maxu)
|
||||
{
|
||||
process_ba |= SHUFFLE_READ;
|
||||
process_ba |= SHUFFLE_READ;
|
||||
process_rg &= ~SHUFFLE_READ;
|
||||
if (!PRIM->ABE && (process_rg & SHUFFLE_WRITE))
|
||||
{
|
||||
@@ -1124,7 +1124,7 @@ GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex, const b
|
||||
height = std::min(height, valid_max_size);
|
||||
}
|
||||
|
||||
return GSVector2i(width, height);
|
||||
return GSVector2i(width, height);
|
||||
}
|
||||
|
||||
GSVector2i GSRendererHW::GetTargetSize(const GSTextureCache::Source* tex, const bool can_expand, const bool is_shuffle)
|
||||
@@ -1167,7 +1167,7 @@ bool GSRendererHW::IsPossibleChannelShuffle() const
|
||||
const int draw_height = std::abs(v[1].XYZ.Y - v[0].XYZ.Y) >> 4;
|
||||
|
||||
const bool mask_clamp = (m_cached_ctx.CLAMP.WMS | m_cached_ctx.CLAMP.WMT) & 0x2;
|
||||
|
||||
|
||||
const bool draw_match = (draw_height == 2) || (draw_width == 8);
|
||||
|
||||
if (draw_match || mask_clamp)
|
||||
@@ -1616,18 +1616,18 @@ bool GSRendererHW::IsRTWritten()
|
||||
const u32 written_bits = (~m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk);
|
||||
const GIFRegALPHA ALPHA = m_context->ALPHA;
|
||||
return (
|
||||
// A not masked
|
||||
(written_bits & 0xFF000000u) != 0) ||
|
||||
(
|
||||
// RGB not entirely masked
|
||||
((written_bits & 0x00FFFFFFu) != 0) &&
|
||||
// RGB written through no-blending, or blend result being non-zero
|
||||
(!PRIM->ABE || // not blending
|
||||
ALPHA.D != 1 || // additive to Cs
|
||||
(ALPHA.A != ALPHA.B && // left side is not zero
|
||||
(ALPHA.C == 1 || // multiply by Ad
|
||||
(ALPHA.C == 2 && ALPHA.FIX != 0) || // multiply by 0
|
||||
(ALPHA.C == 0 && GetAlphaMinMax().max != 0)))));
|
||||
// A not masked
|
||||
(written_bits & 0xFF000000u) != 0) ||
|
||||
(
|
||||
// RGB not entirely masked
|
||||
((written_bits & 0x00FFFFFFu) != 0) &&
|
||||
// RGB written through no-blending, or blend result being non-zero
|
||||
(!PRIM->ABE || // not blending
|
||||
ALPHA.D != 1 || // additive to Cs
|
||||
(ALPHA.A != ALPHA.B && // left side is not zero
|
||||
(ALPHA.C == 1 || // multiply by Ad
|
||||
(ALPHA.C == 2 && ALPHA.FIX != 0) || // multiply by 0
|
||||
(ALPHA.C == 0 && GetAlphaMinMax().max != 0)))));
|
||||
}
|
||||
|
||||
bool GSRendererHW::IsDepthAlwaysPassing()
|
||||
@@ -1636,8 +1636,8 @@ bool GSRendererHW::IsDepthAlwaysPassing()
|
||||
const int check_index = m_vt.m_primclass == GS_SPRITE_CLASS ? 1 : 0;
|
||||
// Depth is always pass/fail (no read) and write are discarded.
|
||||
return (!m_cached_ctx.TEST.ZTE || m_cached_ctx.TEST.ZTST <= ZTST_ALWAYS) ||
|
||||
// Depth test will always pass
|
||||
(m_cached_ctx.TEST.ZTST == ZTST_GEQUAL && m_vt.m_eq.z && std::min(m_vertex.buff[check_index].XYZ.Z, max_z) == max_z);
|
||||
// Depth test will always pass
|
||||
(m_cached_ctx.TEST.ZTST == ZTST_GEQUAL && m_vt.m_eq.z && std::min(m_vertex.buff[check_index].XYZ.Z, max_z) == max_z);
|
||||
}
|
||||
|
||||
bool GSRendererHW::IsUsingCsInBlend()
|
||||
@@ -1673,14 +1673,14 @@ bool GSRendererHW::IsTBPFrameOrZ(u32 tbp, bool frame_only)
|
||||
const u32 max_z = (0xFFFFFFFF >> (GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].fmt * 8));
|
||||
const bool no_rt = (!IsRTWritten() && !m_cached_ctx.TEST.DATE);
|
||||
const bool no_ds = (
|
||||
// Depth is always pass/fail (no read) and write are discarded.
|
||||
(zm != 0 && m_cached_ctx.TEST.ZTST <= ZTST_ALWAYS) ||
|
||||
// Depth test will always pass
|
||||
(zm != 0 && m_cached_ctx.TEST.ZTST == ZTST_GEQUAL && m_vt.m_eq.z && std::min(m_vertex.buff[0].XYZ.Z, max_z) == max_z) ||
|
||||
// Depth will be written through the RT
|
||||
(!no_rt && m_cached_ctx.FRAME.FBP == m_cached_ctx.ZBUF.ZBP && !PRIM->TME && zm == 0 && (fm & fm_mask) == 0 && m_cached_ctx.TEST.ZTE)) ||
|
||||
// No color or Z being written.
|
||||
(no_rt && zm != 0);
|
||||
// Depth is always pass/fail (no read) and write are discarded.
|
||||
(zm != 0 && m_cached_ctx.TEST.ZTST <= ZTST_ALWAYS) ||
|
||||
// Depth test will always pass
|
||||
(zm != 0 && m_cached_ctx.TEST.ZTST == ZTST_GEQUAL && m_vt.m_eq.z && std::min(m_vertex.buff[0].XYZ.Z, max_z) == max_z) ||
|
||||
// Depth will be written through the RT
|
||||
(!no_rt && m_cached_ctx.FRAME.FBP == m_cached_ctx.ZBUF.ZBP && !PRIM->TME && zm == 0 && (fm & fm_mask) == 0 && m_cached_ctx.TEST.ZTE)) ||
|
||||
// No color or Z being written.
|
||||
(no_rt && zm != 0);
|
||||
|
||||
// Relying a lot on the optimizer here... I don't like it.
|
||||
return (is_frame && !no_rt) || (is_z && !no_ds && !frame_only);
|
||||
@@ -1777,7 +1777,7 @@ void GSRendererHW::InvalidateLocalMem(const GIFRegBITBLTBUF& BITBLTBUF, const GS
|
||||
|
||||
if (!(iter->draw == s_n && BITBLTBUF.SBP == iter->blit.DBP && iter->blit.DPSM == BITBLTBUF.SPSM && r.eq(iter->rect)))
|
||||
continue;
|
||||
|
||||
|
||||
g_texture_cache->InvalidateVideoMem(m_mem.GetOffset(BITBLTBUF.SBP, BITBLTBUF.SBW, BITBLTBUF.SPSM), r);
|
||||
skip = true;
|
||||
break;
|
||||
@@ -1917,12 +1917,12 @@ void GSRendererHW::SwSpriteRender()
|
||||
|
||||
const GSVertex& v = m_index.tail > 0 ? m_vertex.buff[m_index.buff[m_index.tail - 1]] : GSVertex(); // Last vertex if any.
|
||||
const GSVector4i vc = GSVector4i(v.RGBAQ.R, v.RGBAQ.G, v.RGBAQ.B, v.RGBAQ.A) // 0x000000AA000000BB000000GG000000RR
|
||||
.ps32(); // 0x00AA00BB00GG00RR00AA00BB00GG00RR
|
||||
.ps32(); // 0x00AA00BB00GG00RR00AA00BB00GG00RR
|
||||
|
||||
const GSVector4i a_mask = GSVector4i::xff000000().u8to16(); // 0x00FF00000000000000FF000000000000
|
||||
const GSVector4i a_mask = GSVector4i::xff000000().u8to16(); // 0x00FF00000000000000FF000000000000
|
||||
|
||||
const bool fb_mask_enabled = m_cached_ctx.FRAME.FBMSK != 0x0;
|
||||
const GSVector4i fb_mask = GSVector4i(m_cached_ctx.FRAME.FBMSK).u8to16(); // 0x00AA00BB00GG00RR00AA00BB00GG00RR
|
||||
const GSVector4i fb_mask = GSVector4i(m_cached_ctx.FRAME.FBMSK).u8to16(); // 0x00AA00BB00GG00RR00AA00BB00GG00RR
|
||||
|
||||
const u8 tex0_tfx = m_cached_ctx.TEX0.TFX;
|
||||
const u8 tex0_tcc = m_cached_ctx.TEX0.TCC;
|
||||
@@ -2250,8 +2250,8 @@ void GSRendererHW::Draw()
|
||||
// Tomb Raider: Underworld does similar, except with R, G, B in separate palettes, therefore
|
||||
// we need to split on those too.
|
||||
m_channel_shuffle = !m_channel_shuffle_abort && IsPossibleChannelShuffle() && m_last_channel_shuffle_fbmsk == m_context->FRAME.FBMSK &&
|
||||
m_last_channel_shuffle_fbp <= m_context->FRAME.Block() && m_last_channel_shuffle_end_block > m_context->FRAME.Block() &&
|
||||
m_last_channel_shuffle_tbp <= m_context->TEX0.TBP0;
|
||||
m_last_channel_shuffle_fbp <= m_context->FRAME.Block() && m_last_channel_shuffle_end_block > m_context->FRAME.Block() &&
|
||||
m_last_channel_shuffle_tbp <= m_context->TEX0.TBP0;
|
||||
|
||||
if (m_channel_shuffle)
|
||||
{
|
||||
@@ -2296,7 +2296,7 @@ void GSRendererHW::Draw()
|
||||
else
|
||||
m_conf.scissor.z = std::min(m_conf.scissor.z, static_cast<int>((m_channel_shuffle_width * 64) * m_conf.cb_ps.ScaleFactor.z));
|
||||
}
|
||||
|
||||
|
||||
m_last_rt->UpdateValidity(valid_area);
|
||||
|
||||
g_gs_device->RenderHW(m_conf);
|
||||
@@ -2308,7 +2308,7 @@ void GSRendererHW::Draw()
|
||||
if (m_last_rt && GSConfig.SaveRT)
|
||||
{
|
||||
const u64 frame = g_perfmon.GetFrame();
|
||||
|
||||
|
||||
std::string s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_(%05x)_%s.bmp", s_n - 1, frame, m_last_channel_shuffle_fbp, m_last_rt->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM));
|
||||
|
||||
m_last_rt->m_texture->Save(s);
|
||||
@@ -2354,9 +2354,9 @@ void GSRendererHW::Draw()
|
||||
// Note: do it first so we know if frame/depth writes are masked
|
||||
u32 fm = m_cached_ctx.FRAME.FBMSK;
|
||||
u32 zm = (m_cached_ctx.ZBUF.ZMSK || m_cached_ctx.TEST.ZTE == 0 ||
|
||||
(m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.ATST == ZTST_NEVER && m_cached_ctx.TEST.AFAIL != AFAIL_ZB_ONLY)) ?
|
||||
0xffffffffu :
|
||||
0;
|
||||
(m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.ATST == ZTST_NEVER && m_cached_ctx.TEST.AFAIL != AFAIL_ZB_ONLY)) ?
|
||||
0xffffffffu :
|
||||
0;
|
||||
const u32 fm_mask = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk;
|
||||
|
||||
// Note required to compute TryAlphaTest below. So do it now.
|
||||
@@ -2424,8 +2424,8 @@ void GSRendererHW::Draw()
|
||||
bool no_rt = (!IsRTWritten() && !m_cached_ctx.TEST.DATE);
|
||||
const bool all_depth_tests_pass = IsDepthAlwaysPassing();
|
||||
bool no_ds = (zm != 0 && all_depth_tests_pass) ||
|
||||
// No color or Z being written.
|
||||
(no_rt && zm != 0);
|
||||
// No color or Z being written.
|
||||
(no_rt && zm != 0);
|
||||
|
||||
// No Z test if no z buffer.
|
||||
if (no_ds || all_depth_tests_pass)
|
||||
@@ -2465,7 +2465,6 @@ void GSRendererHW::Draw()
|
||||
g_gs_device->Recycle(colclip_texture);
|
||||
|
||||
g_gs_device->SetColorClipTexture(nullptr);
|
||||
|
||||
}
|
||||
else
|
||||
DevCon.Warning("HW: Error resolving colclip texture for pre-draw resolve");
|
||||
@@ -2922,13 +2921,13 @@ void GSRendererHW::Draw()
|
||||
(m_vt.m_primclass == GS_SPRITE_CLASS || (m_vt.m_primclass == GS_TRIANGLE_CLASS && (m_index.tail % 6) == 0 && TrianglesAreQuads(true) && m_index.tail > 6)))
|
||||
{
|
||||
// Tail check is to make sure we have enough strips to go all the way across the page, or if it's using a region clamp could be used to draw strips.
|
||||
if (GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 &&
|
||||
if (GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 &&
|
||||
(m_index.tail >= (m_cached_ctx.TEX0.TBW * 2) || m_cached_ctx.TEX0.TBP0 == m_cached_ctx.FRAME.Block() || m_cached_ctx.CLAMP.WMS > CLAMP_CLAMP || m_cached_ctx.CLAMP.WMT > CLAMP_CLAMP))
|
||||
{
|
||||
const GSVertex* v = &m_vertex.buff[0];
|
||||
|
||||
const int first_x = std::clamp((static_cast<int>(((v[0].XYZ.X - m_context->XYOFFSET.OFX) + 8))) >> 4, 0, 2048);
|
||||
const bool offset_last = PRIM->FST ? (v[1].U > v[0].U) : ((v[1].ST.S / v[1].RGBAQ.Q) > (v[0].ST.S / v[1].RGBAQ.Q));
|
||||
const bool offset_last = PRIM->FST ? (v[1].U > v[0].U) : ((v[1].ST.S / v[1].RGBAQ.Q) > (v[0].ST.S / v[1].RGBAQ.Q));
|
||||
const int first_u = PRIM->FST ? ((v[0].U + (offset_last ? 0 : 9)) >> 4) : std::clamp(static_cast<int>(((1 << m_cached_ctx.TEX0.TW) * (v[0].ST.S / v[1].RGBAQ.Q)) + (offset_last ? 0.0f : 0.6f)), 0, 2048);
|
||||
const int second_u = PRIM->FST ? ((v[1].U + (offset_last ? 9 : 0)) >> 4) : std::clamp(static_cast<int>(((1 << m_cached_ctx.TEX0.TW) * (v[1].ST.S / v[1].RGBAQ.Q)) + (offset_last ? 0.6f : 0.0f)), 0, 2048);
|
||||
// offset coordinates swap around RG/BA. (Ace Combat)
|
||||
@@ -3007,9 +3006,9 @@ void GSRendererHW::Draw()
|
||||
}
|
||||
else
|
||||
{
|
||||
src = tex_psm.depth ? g_texture_cache->LookupDepthSource(true, TEX0, m_cached_ctx.TEXA, MIP_CLAMP, tmm.coverage, possible_shuffle, m_vt.IsLinear(), m_cached_ctx.FRAME, req_color, req_alpha) :
|
||||
g_texture_cache->LookupSource(true, TEX0, m_cached_ctx.TEXA, MIP_CLAMP, tmm.coverage, (GSConfig.HWMipmap || GSConfig.TriFilter == TriFiltering::Forced) ? &hash_lod_range : nullptr,
|
||||
possible_shuffle, m_vt.IsLinear(), m_cached_ctx.FRAME, req_color, req_alpha);
|
||||
src = tex_psm.depth ? g_texture_cache->LookupDepthSource(true, TEX0, m_cached_ctx.TEXA, MIP_CLAMP, tmm.coverage, possible_shuffle, m_vt.IsLinear(), m_cached_ctx.FRAME, req_color, req_alpha)
|
||||
: g_texture_cache->LookupSource(true, TEX0, m_cached_ctx.TEXA, MIP_CLAMP, tmm.coverage, (GSConfig.HWMipmap || GSConfig.TriFilter == TriFiltering::Forced) ? &hash_lod_range : nullptr,
|
||||
possible_shuffle, m_vt.IsLinear(), m_cached_ctx.FRAME, req_color, req_alpha);
|
||||
|
||||
if (!src) [[unlikely]]
|
||||
{
|
||||
@@ -3022,9 +3021,8 @@ void GSRendererHW::Draw()
|
||||
|
||||
const u32 draw_end = GSLocalMemory::GetEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r) + 1;
|
||||
const u32 draw_start = GSLocalMemory::GetStartBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r);
|
||||
draw_uses_target = src->m_from_target && ((src->m_from_target_TEX0.TBP0 <= draw_start &&
|
||||
src->m_from_target->UnwrappedEndBlock() > m_cached_ctx.FRAME.Block()) ||
|
||||
(m_cached_ctx.FRAME.Block() < src->m_from_target_TEX0.TBP0 && draw_end > src->m_from_target_TEX0.TBP0));
|
||||
draw_uses_target = src->m_from_target && ((src->m_from_target_TEX0.TBP0 <= draw_start && src->m_from_target->UnwrappedEndBlock() > m_cached_ctx.FRAME.Block()) ||
|
||||
(m_cached_ctx.FRAME.Block() < src->m_from_target_TEX0.TBP0 && draw_end > src->m_from_target_TEX0.TBP0));
|
||||
|
||||
if (possible_shuffle && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp != 16)
|
||||
possible_shuffle &= draw_uses_target;
|
||||
@@ -3047,9 +3045,9 @@ void GSRendererHW::Draw()
|
||||
|
||||
u32 new_fm = m_context->FRAME.FBMSK;
|
||||
u32 new_zm = (m_cached_ctx.ZBUF.ZMSK || m_cached_ctx.TEST.ZTE == 0 ||
|
||||
(m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.ATST == ZTST_NEVER && m_cached_ctx.TEST.AFAIL != AFAIL_ZB_ONLY)) ?
|
||||
0xffffffffu :
|
||||
0;
|
||||
(m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.ATST == ZTST_NEVER && m_cached_ctx.TEST.AFAIL != AFAIL_ZB_ONLY)) ?
|
||||
0xffffffffu :
|
||||
0;
|
||||
if (m_cached_ctx.TEST.ATE && GSRenderer::TryAlphaTest(new_fm, new_zm))
|
||||
{
|
||||
m_cached_ctx.TEST.ATE = false;
|
||||
@@ -3059,10 +3057,10 @@ void GSRendererHW::Draw()
|
||||
zm = new_zm;
|
||||
no_rt = no_rt || (!IsRTWritten() && !m_cached_ctx.TEST.DATE);
|
||||
no_ds = no_ds || (zm != 0 && all_depth_tests_pass) ||
|
||||
// Depth will be written through the RT
|
||||
(!no_rt && m_cached_ctx.FRAME.FBP == m_cached_ctx.ZBUF.ZBP && !PRIM->TME && zm == 0 && (fm & fm_mask) == 0 && m_cached_ctx.TEST.ZTE) ||
|
||||
// No color or Z being written.
|
||||
(no_rt && zm != 0);
|
||||
// Depth will be written through the RT
|
||||
(!no_rt && m_cached_ctx.FRAME.FBP == m_cached_ctx.ZBUF.ZBP && !PRIM->TME && zm == 0 && (fm & fm_mask) == 0 && m_cached_ctx.TEST.ZTE) ||
|
||||
// No color or Z being written.
|
||||
(no_rt && zm != 0);
|
||||
if (no_rt && no_ds)
|
||||
{
|
||||
GL_INS("HW: Late draw cancel because no pixels pass alpha test.");
|
||||
@@ -3362,16 +3360,18 @@ void GSRendererHW::Draw()
|
||||
|
||||
if (!no_rt)
|
||||
{
|
||||
possible_shuffle |= draw_sprite_tex && m_process_texture && m_primitive_covers_without_gaps != NoGapsType::FullCover && (((src && src->m_target && src->m_from_target && src->m_from_target->m_32_bits_fmt) &&
|
||||
(GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 || draw_uses_target) && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) ||
|
||||
IsPossibleChannelShuffle());
|
||||
possible_shuffle |= draw_sprite_tex && m_process_texture && m_primitive_covers_without_gaps != NoGapsType::FullCover &&
|
||||
(((src && src->m_target && src->m_from_target && src->m_from_target->m_32_bits_fmt) &&
|
||||
(GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 || draw_uses_target) &&
|
||||
GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) ||
|
||||
IsPossibleChannelShuffle());
|
||||
|
||||
const bool possible_horizontal_texture_shuffle = possible_shuffle && src && src->m_from_target && m_r.w <= src->m_from_target->m_valid.w && m_r.z > src->m_from_target->m_valid.z && m_cached_ctx.FRAME.FBW > src->m_from_target_TEX0.TBW;
|
||||
|
||||
// FBW is going to be wrong for channel shuffling into a new target, so take it from the source.
|
||||
FRAME_TEX0.U64 = 0;
|
||||
FRAME_TEX0.TBP0 = ((m_last_channel_shuffle_end_block + 1) == m_cached_ctx.FRAME.Block() && possible_shuffle) ? m_last_channel_shuffle_fbp : m_cached_ctx.FRAME.Block();
|
||||
FRAME_TEX0.TBW = (possible_horizontal_texture_shuffle || (possible_shuffle && src && src->m_from_target && IsPossibleChannelShuffle()&& m_cached_ctx.FRAME.FBW <= 2)) ? src->m_from_target_TEX0.TBW : m_cached_ctx.FRAME.FBW;
|
||||
FRAME_TEX0.TBW = (possible_horizontal_texture_shuffle || (possible_shuffle && src && src->m_from_target && IsPossibleChannelShuffle() && m_cached_ctx.FRAME.FBW <= 2)) ? src->m_from_target_TEX0.TBW : m_cached_ctx.FRAME.FBW;
|
||||
FRAME_TEX0.PSM = m_cached_ctx.FRAME.PSM;
|
||||
|
||||
// Don't clamp on shuffle, the height cache may troll us with the REAL height.
|
||||
@@ -3459,8 +3459,8 @@ void GSRendererHW::Draw()
|
||||
return;
|
||||
}
|
||||
|
||||
rt = g_texture_cache->CreateTarget(FRAME_TEX0, t_size, GetValidSize(src, possible_shuffle), (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && scale_draw < 0 && is_possible_mem_clear != ClearType::NormalClear) ? ((src && src->m_from_target) ? src->m_from_target->GetScale() : (ds ? ds->m_scale : 1.0f)) : target_scale,
|
||||
GSTextureCache::RenderTarget, true, fm, false, force_preload, preserve_rt_color || possible_shuffle, lookup_rect, src);
|
||||
rt = g_texture_cache->CreateTarget(FRAME_TEX0, t_size, GetValidSize(src, possible_shuffle), (GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && scale_draw < 0 && is_possible_mem_clear != ClearType::NormalClear) ? ((src && src->m_from_target) ? src->m_from_target->GetScale() : (ds ? ds->m_scale : 1.0f)) : target_scale,
|
||||
GSTextureCache::RenderTarget, true, fm, false, force_preload, preserve_rt_color || possible_shuffle, lookup_rect, src);
|
||||
|
||||
if (!rt) [[unlikely]]
|
||||
{
|
||||
@@ -3474,8 +3474,8 @@ void GSRendererHW::Draw()
|
||||
rt->UpdateValidity(GSVector4i::loadh(GSVector2i(GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.x, GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs.y)), true);
|
||||
}
|
||||
|
||||
if (src && !src->m_from_target && GSLocalMemory::m_psm[src->m_TEX0.PSM].bpp == GSLocalMemory::m_psm[m_context->FRAME.PSM].bpp &&
|
||||
(GSUtil::GetChannelMask(src->m_TEX0.PSM) & GSUtil::GetChannelMask(m_context->FRAME.PSM)) != 0)
|
||||
if (src && !src->m_from_target && GSLocalMemory::m_psm[src->m_TEX0.PSM].bpp == GSLocalMemory::m_psm[m_context->FRAME.PSM].bpp &&
|
||||
(GSUtil::GetChannelMask(src->m_TEX0.PSM) & GSUtil::GetChannelMask(m_context->FRAME.PSM)) != 0)
|
||||
{
|
||||
const u32 draw_end = GSLocalMemory::GetEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r) + 1;
|
||||
const u32 draw_start = GSLocalMemory::GetStartBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r);
|
||||
@@ -3494,7 +3494,7 @@ void GSRendererHW::Draw()
|
||||
src->m_valid_rect = rt->m_valid;
|
||||
src->m_alpha_minmax.first = rt->m_alpha_min;
|
||||
src->m_alpha_minmax.second = rt->m_alpha_max;
|
||||
|
||||
|
||||
const int target_width = std::max(FRAME_TEX0.TBW, 1U);
|
||||
const int page_offset = (src->m_TEX0.TBP0 - rt->m_TEX0.TBP0) >> 5;
|
||||
const int vertical_page_offset = page_offset / target_width;
|
||||
@@ -3652,7 +3652,7 @@ void GSRendererHW::Draw()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Z or RT are offset from each other, so we need a temp Z to align it
|
||||
if (ds && rt && ((m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) != (m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) || (g_texture_cache->GetTemporaryZ() != nullptr && g_texture_cache->GetTemporaryZInfo().ZBP == ds->m_TEX0.TBP0)))
|
||||
{
|
||||
@@ -3716,7 +3716,7 @@ void GSRendererHW::Draw()
|
||||
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
|
||||
const int vertical_page_offset = (rt_page_offset / std::max(static_cast<int>(rt->m_TEX0.TBW), 1));
|
||||
const int vertical_offset = vertical_page_offset * frame_psm.pgs.y;
|
||||
const int horizontal_offset = (rt_page_offset - (vertical_page_offset * std::max(static_cast<int>(rt->m_TEX0.TBW), 1))) * frame_psm.pgs.x;
|
||||
const int horizontal_offset = (rt_page_offset - (vertical_page_offset * std::max(static_cast<int>(rt->m_TEX0.TBW), 1))) * frame_psm.pgs.x;
|
||||
|
||||
const u32 horizontal_size = std::max(rt->m_unscaled_size.x, ds->m_unscaled_size.x);
|
||||
const u32 vertical_size = std::max(rt->m_unscaled_size.y, ds->m_unscaled_size.y);
|
||||
@@ -3768,7 +3768,6 @@ void GSRendererHW::Draw()
|
||||
src->m_texture = rt->m_texture;
|
||||
src->m_scale = rt->GetScale();
|
||||
src->m_unscaled_size = rt->m_unscaled_size;
|
||||
|
||||
}
|
||||
|
||||
target_scale = rt->GetScale();
|
||||
@@ -3884,17 +3883,16 @@ void GSRendererHW::Draw()
|
||||
|
||||
// copy of a 16bit source in to this target, make sure it's opaque and not bilinear to reduce false positives.
|
||||
m_copy_16bit_to_target_shuffle = m_cached_ctx.TEX0.TBP0 != m_cached_ctx.FRAME.Block() && rt->m_32_bits_fmt == true && IsOpaque()
|
||||
&& !(context->TEX1.MMIN & 1) && !src->m_32_bits_fmt && m_cached_ctx.FRAME.FBMSK;
|
||||
&& !(context->TEX1.MMIN & 1) && !src->m_32_bits_fmt && m_cached_ctx.FRAME.FBMSK;
|
||||
|
||||
// It's not actually possible to do a C16->C16 texture shuffle of B to A as they are the same group
|
||||
// However you can do it by using C32 and offsetting the target verticies to point to B A, then mask as appropriate.
|
||||
m_same_group_texture_shuffle = draw_uses_target && (m_cached_ctx.TEX0.PSM & 0xE) == PSMCT32 && (m_cached_ctx.FRAME.PSM & 0x7) == PSMCT16 && (m_vt.m_min.p.x == 8.0f);
|
||||
|
||||
// Both input and output are 16 bits and texture was initially 32 bits! Same for the target, Sonic Unleash makes a new target which really is 16bit.
|
||||
m_texture_shuffle = ((m_same_group_texture_shuffle || (tex_psm.bpp == 16)) && (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) &&
|
||||
(shuffle_coords || rt->m_32_bits_fmt)) &&
|
||||
(src->m_32_bits_fmt || m_copy_16bit_to_target_shuffle) &&
|
||||
(draw_sprite_tex || (m_vt.m_primclass == GS_TRIANGLE_CLASS && (m_index.tail % 6) == 0 && TrianglesAreQuads(true)));
|
||||
m_texture_shuffle = ((m_same_group_texture_shuffle || (tex_psm.bpp == 16)) && (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) && (shuffle_coords || rt->m_32_bits_fmt)) &&
|
||||
(src->m_32_bits_fmt || m_copy_16bit_to_target_shuffle) &&
|
||||
(draw_sprite_tex || (m_vt.m_primclass == GS_TRIANGLE_CLASS && (m_index.tail % 6) == 0 && TrianglesAreQuads(true)));
|
||||
|
||||
if (m_texture_shuffle && IsSplitTextureShuffle(rt->m_TEX0, rt->m_valid))
|
||||
{
|
||||
@@ -4285,7 +4283,8 @@ void GSRendererHW::Draw()
|
||||
{
|
||||
// if the height cache gave a different size to our final size, we need to check if it needs preloading.
|
||||
// Pirates - Legend of the Black Kat starts a draw of 416, but Z is 448 and it preloads the background.
|
||||
if (rt->m_drawn_since_read.rempty() && rt->m_dirty.size() > 0 && new_height && (preserve_rt_color || preserve_rt_alpha)) {
|
||||
if (rt->m_drawn_since_read.rempty() && rt->m_dirty.size() > 0 && new_height && (preserve_rt_color || preserve_rt_alpha))
|
||||
{
|
||||
RGBAMask mask;
|
||||
mask._u32 = preserve_rt_color ? 0x7 : 0;
|
||||
mask.c.a |= preserve_rt_alpha;
|
||||
@@ -4659,8 +4658,11 @@ void GSRendererHW::Draw()
|
||||
if (!m_temp_z_full_copy && was_written)
|
||||
{
|
||||
GSVector4i dRect = GSVector4i((z_horizontal_offset + (real_rect.x - horizontal_offset)) * ds->m_scale, (z_vertical_offset + (real_rect.y - vertical_offset)) * ds->m_scale, ((z_horizontal_offset + real_rect.z + (1.0f / ds->m_scale)) - horizontal_offset) * ds->m_scale, (z_vertical_offset + (real_rect.w + (1.0f / ds->m_scale) - vertical_offset)) * ds->m_scale);
|
||||
GSVector4 sRect = GSVector4((real_rect.x * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()), static_cast<float>(real_rect.y * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()), ((real_rect.z + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
|
||||
static_cast<float>((real_rect.w + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()));
|
||||
GSVector4 sRect = GSVector4(
|
||||
(real_rect.x * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
|
||||
static_cast<float>(real_rect.y * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()),
|
||||
((real_rect.z + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
|
||||
static_cast<float>((real_rect.w + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()));
|
||||
|
||||
GL_CACHE("HW: RT in RT Z copy back draw %d z_vert_offset %d rt_vert_offset %d z_horz_offset %d rt_horz_offset %d", s_n, z_vertical_offset, vertical_offset, z_horizontal_offset, horizontal_offset);
|
||||
g_gs_device->StretchRect(g_texture_cache->GetTemporaryZ(), sRect, ds->m_texture, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
|
||||
@@ -4669,7 +4671,10 @@ void GSRendererHW::Draw()
|
||||
else if (m_temp_z_full_copy)
|
||||
{
|
||||
GSVector4i dRect = GSVector4i((ds->m_valid.x + z_horizontal_offset) * ds->m_scale, (ds->m_valid.y + z_vertical_offset) * ds->m_scale, (ds->m_valid.z + z_horizontal_offset + (1.0f / ds->m_scale)) * ds->m_scale, (ds->m_valid.w + z_vertical_offset + (1.0f / ds->m_scale)) * ds->m_scale);
|
||||
GSVector4 sRect = GSVector4(((ds->m_valid.x + horizontal_offset) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()), static_cast<float>((ds->m_valid.y + vertical_offset) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()), (((ds->m_valid.z + horizontal_offset) + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
|
||||
GSVector4 sRect = GSVector4(
|
||||
((ds->m_valid.x + horizontal_offset) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
|
||||
static_cast<float>((ds->m_valid.y + vertical_offset) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()),
|
||||
(((ds->m_valid.z + horizontal_offset) + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetWidth()),
|
||||
static_cast<float>((ds->m_valid.w + vertical_offset + (1.0f / ds->m_scale)) * ds->m_scale) / static_cast<float>(g_texture_cache->GetTemporaryZ()->GetHeight()));
|
||||
|
||||
GL_CACHE("HW: RT in RT Z copy back draw %d z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset);
|
||||
@@ -5371,7 +5376,7 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool
|
||||
// Page align test to limit false detections (there is a few).
|
||||
GSVector4i min_uv = GSVector4i(m_vt.m_min.t.upld(GSVector4::zero()));
|
||||
ChannelFetch channel = ChannelFetch_NONE;
|
||||
const GSLocalMemory::psm_t& t_psm = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM];;
|
||||
const GSLocalMemory::psm_t& t_psm = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM];
|
||||
const GSLocalMemory::psm_t& f_psm = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM];
|
||||
GSVector4i block_offset = GSVector4i(min_uv.x / t_psm.bs.x, min_uv.y / t_psm.bs.y).xyxy();
|
||||
GSVector4i m_r_block_offset = GSVector4i((m_r.x & (f_psm.pgs.x - 1)) / f_psm.bs.x, (m_r.y & (f_psm.pgs.y - 1)) / f_psm.bs.y);
|
||||
@@ -5444,7 +5449,7 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool
|
||||
s[1].U = 16384;
|
||||
s[0].V = 0;
|
||||
s[1].V = 16384;
|
||||
|
||||
|
||||
m_r = GSVector4i(0, 0, 1024, 1024);
|
||||
|
||||
// We need to count the pages that get shuffled to, some games (like Hitman Blood Money dialogue blur effects) only do half the screen.
|
||||
@@ -5476,7 +5481,7 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool
|
||||
if (rt && rt->m_TEX0.TBP0 == m_cached_ctx.FRAME.Block())
|
||||
{
|
||||
const bool req_offset = (m_cached_ctx.CLAMP.WMS != 3 || (m_cached_ctx.CLAMP.MAXU & ~0xF) == 0) &&
|
||||
(m_cached_ctx.CLAMP.WMT != 3 || (m_cached_ctx.CLAMP.MAXV & ~0x3) == 0);
|
||||
(m_cached_ctx.CLAMP.WMT != 3 || (m_cached_ctx.CLAMP.MAXV & ~0x3) == 0);
|
||||
//DevCon.Warning("HW: Draw %d offset %d", s_n, frame_page_offset);
|
||||
// Offset the frame but clear the draw offset
|
||||
if (req_offset)
|
||||
@@ -5514,7 +5519,7 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool
|
||||
new_valid.w = std::max(new_valid.w, offset_height);
|
||||
rt->UpdateValidity(new_valid, true);
|
||||
}
|
||||
|
||||
|
||||
m_vertex.head = m_vertex.tail = m_vertex.next = 2;
|
||||
m_index.tail = 2;
|
||||
|
||||
@@ -5568,7 +5573,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
#endif
|
||||
|
||||
// If the colour is modulated to zero or we're not using a texture and the color is zero, we can replace any Cs with 0
|
||||
if ((!PRIM->TME || m_cached_ctx.TEX0.TFX != TFX_DECAL) && (!PRIM->FGE || m_draw_env->FOGCOL.U32[0] == 0) &&
|
||||
if ((!PRIM->TME || m_cached_ctx.TEX0.TFX != TFX_DECAL) && (!PRIM->FGE || m_draw_env->FOGCOL.U32[0] == 0) &&
|
||||
((m_vt.m_max.c == GSVector4i::zero()).mask() & 0xfff) == 0xfff)
|
||||
{
|
||||
// If using modulate or is HIGHLIGHT by the vertex alpha is zero, we should be safe to kill it.
|
||||
@@ -5739,7 +5744,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
// Condition 4: If it's tex in fb draw and there's no overlap prefer sw blend, fb is already being read.
|
||||
const bool prefer_sw_blend = (features.texture_barrier && m_conf.require_full_barrier) || (m_conf.require_one_barrier && (no_prim_overlap || m_channel_shuffle)) || m_conf.ps.shuffle || (no_prim_overlap && (m_conf.tex == m_conf.rt));
|
||||
const bool free_blend = blend_non_recursive // Free sw blending, doesn't require barriers or reading fb
|
||||
|| accumulation_blend; // Mix of hw/sw blending
|
||||
|| accumulation_blend; // Mix of hw/sw blending
|
||||
|
||||
// Warning no break on purpose
|
||||
// Note: the [[fallthrough]] attribute tell compilers not to complain about not having breaks.
|
||||
@@ -5795,7 +5800,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
else
|
||||
{
|
||||
const bool ad_second_pass = blend_multi_pass_support && alpha_c1_high_no_rta_correct && COLCLAMP.CLAMP &&
|
||||
(blend_flag & (BLEND_HW3 | BLEND_HW5 | BLEND_HW6 | BLEND_HW7 | BLEND_HW9));
|
||||
(blend_flag & (BLEND_HW3 | BLEND_HW5 | BLEND_HW6 | BLEND_HW7 | BLEND_HW9));
|
||||
|
||||
switch (GSConfig.AccurateBlendingUnit)
|
||||
{
|
||||
@@ -6137,7 +6142,7 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
|
||||
new_rt_alpha_scale = true;
|
||||
alpha_c1_high_no_rta_correct = false;
|
||||
|
||||
|
||||
m_conf.ps.rta_correction = rt->m_rt_alpha_scale;
|
||||
}
|
||||
|
||||
@@ -6307,9 +6312,9 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
|
||||
// Remove second color output when unused. Works around bugs in some drivers (e.g. Intel).
|
||||
m_conf.ps.no_color1 = !GSDevice::IsDualSourceBlendFactor(m_conf.blend.src_factor) &&
|
||||
!GSDevice::IsDualSourceBlendFactor(m_conf.blend.dst_factor) &&
|
||||
!GSDevice::IsDualSourceBlendFactor(m_conf.blend_multi_pass.blend.src_factor) &&
|
||||
!GSDevice::IsDualSourceBlendFactor(m_conf.blend_multi_pass.blend.dst_factor);
|
||||
!GSDevice::IsDualSourceBlendFactor(m_conf.blend.dst_factor) &&
|
||||
!GSDevice::IsDualSourceBlendFactor(m_conf.blend_multi_pass.blend.src_factor) &&
|
||||
!GSDevice::IsDualSourceBlendFactor(m_conf.blend_multi_pass.blend.dst_factor);
|
||||
}
|
||||
|
||||
// Notify the shader that it needs to invert rounding
|
||||
@@ -6380,9 +6385,9 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
|
||||
// we keep the shader clamp. See #5851 on github, and the note in Draw().
|
||||
[[maybe_unused]] static constexpr const char* clamp_modes[] = {"REPEAT", "CLAMP", "REGION_CLAMP", "REGION_REPEAT"};
|
||||
const bool redundant_wms = IsRedundantClamp(m_cached_ctx.CLAMP.WMS, m_cached_ctx.CLAMP.MINU,
|
||||
m_cached_ctx.CLAMP.MAXU, m_cached_ctx.TEX0.TW);
|
||||
m_cached_ctx.CLAMP.MAXU, m_cached_ctx.TEX0.TW);
|
||||
const bool redundant_wmt = IsRedundantClamp(m_cached_ctx.CLAMP.WMT, m_cached_ctx.CLAMP.MINV,
|
||||
m_cached_ctx.CLAMP.MAXV, m_cached_ctx.TEX0.TH);
|
||||
m_cached_ctx.CLAMP.MAXV, m_cached_ctx.TEX0.TH);
|
||||
const u8 wms = EffectiveClamp(m_cached_ctx.CLAMP.WMS, !tex->m_target && (source_region.HasX() || redundant_wms));
|
||||
const u8 wmt = EffectiveClamp(m_cached_ctx.CLAMP.WMT, !tex->m_target && (source_region.HasY() || redundant_wmt));
|
||||
const bool complex_wms_wmt = !!((wms | wmt) & 2) || target_region;
|
||||
@@ -6394,7 +6399,7 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
|
||||
|
||||
const bool need_mipmap = IsMipMapDraw();
|
||||
const bool shader_emulated_sampler = tex->m_palette || (tex->m_target && !m_conf.ps.shuffle && cpsm.fmt != 0) ||
|
||||
complex_wms_wmt || psm.depth || target_region;
|
||||
complex_wms_wmt || psm.depth || target_region;
|
||||
const bool can_trilinear = !tex->m_palette && !tex->m_target && !m_conf.ps.shuffle;
|
||||
const bool trilinear_manual = need_mipmap && GSConfig.HWMipmap;
|
||||
|
||||
@@ -6667,7 +6672,7 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
|
||||
// This "fixes" a lot of the rainbow garbage in games when upscaling (and xenosaga shadows + VP2 forest seem quite happy).
|
||||
// Note that this is done on the original texture scale, during upscales it can mess up otherwise.
|
||||
const GSVector4 region_clamp_offset = GSVector4::cxpr(0.5f, 0.5f, 0.1f, 0.1f) + (GSVector4::cxpr(0.1f, 0.1f, 0.0f, 0.0f) * tex->GetScale());
|
||||
|
||||
|
||||
const GSVector4 region_clamp = (GSVector4(clamp) + region_clamp_offset) / WH.xyxy();
|
||||
if (wms >= CLAMP_REGION_CLAMP)
|
||||
{
|
||||
@@ -6680,7 +6685,7 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
|
||||
m_conf.cb_ps.MinMax.w = (wmt == CLAMP_REGION_CLAMP && !m_conf.ps.depth_fmt) ? region_clamp.w : region_repeat.w;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (trilinear_manual)
|
||||
{
|
||||
m_conf.cb_ps.LODParams.x = static_cast<float>(m_context->TEX1.K) / 16.0f;
|
||||
@@ -6711,8 +6716,8 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
|
||||
|
||||
// Remove linear from trilinear, since we're doing the bilinear in the shader, and we only want this for mip selection.
|
||||
m_conf.sampler.triln = (trilinear >= static_cast<u8>(GS_MIN_FILTER::Linear_Mipmap_Nearest)) ?
|
||||
(trilinear - static_cast<u8>(GS_MIN_FILTER::Nearest_Mipmap_Nearest)) :
|
||||
0;
|
||||
(trilinear - static_cast<u8>(GS_MIN_FILTER::Nearest_Mipmap_Nearest)) :
|
||||
0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -6933,8 +6938,8 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
static_cast<int>(std::ceil(static_cast<float>(copy_size.y) * scale)));
|
||||
|
||||
src_copy.reset(src_target->m_texture->IsDepthStencil() ?
|
||||
g_gs_device->CreateDepthStencil(scaled_copy_size.x, scaled_copy_size.y, src_target->m_texture->GetFormat(), false) :
|
||||
g_gs_device->CreateRenderTarget(scaled_copy_size.x, scaled_copy_size.y, src_target->m_texture->GetFormat(), true, true));
|
||||
g_gs_device->CreateDepthStencil(scaled_copy_size.x, scaled_copy_size.y, src_target->m_texture->GetFormat(), false) :
|
||||
g_gs_device->CreateRenderTarget(scaled_copy_size.x, scaled_copy_size.y, src_target->m_texture->GetFormat(), true, true));
|
||||
if (!src_copy) [[unlikely]]
|
||||
{
|
||||
Console.Error("HW: Failed to allocate %dx%d texture for hazard copy", scaled_copy_size.x, scaled_copy_size.y);
|
||||
@@ -6961,8 +6966,8 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
// causing bleeding into the edges of the downsampled texture.
|
||||
const u32 downsample_factor = static_cast<u32>(src_target->GetScale());
|
||||
const GSVector2i clamp_min = (GSConfig.UserHacks_HalfPixelOffset < GSHalfPixelOffset::Native) ?
|
||||
GSVector2i(0, 0) :
|
||||
GSVector2i(downsample_factor, downsample_factor);
|
||||
GSVector2i(0, 0) :
|
||||
GSVector2i(downsample_factor, downsample_factor);
|
||||
GSVector4i copy_rect = tmm.coverage;
|
||||
if (target_region)
|
||||
{
|
||||
@@ -7212,7 +7217,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
m_conf.ps.scanmsk = env.SCANMSK.MSK;
|
||||
m_conf.rt = rt ? rt->m_texture : nullptr;
|
||||
m_conf.ds = ds ? (m_using_temp_z ? g_texture_cache->GetTemporaryZ() : ds->m_texture) : nullptr;
|
||||
|
||||
|
||||
pxAssert(!ds || !rt || (m_conf.ds->GetSize().x == m_conf.rt->GetSize().x && m_conf.ds->GetSize().y == m_conf.rt->GetSize().y));
|
||||
|
||||
// Z setup has to come before channel shuffle
|
||||
@@ -7802,12 +7807,12 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
const int unscaled_y = rt_or_ds ? rt_or_ds->GetUnscaledHeight() : 0;
|
||||
sx = 2.0f / (unscaled_x << 4);
|
||||
sy = 2.0f / (unscaled_y << 4);
|
||||
|
||||
|
||||
if (GSConfig.UserHacks_HalfPixelOffset == GSHalfPixelOffset::NativeWTexOffset)
|
||||
{
|
||||
ox2 = (-1.0f / (unscaled_x * rtscale));
|
||||
oy2 = (-1.0f / (unscaled_y * rtscale));
|
||||
|
||||
|
||||
// Having the vertex negatively offset is a common thing for copying sprites but this causes problems when upscaling, so we need to further adjust the offset.
|
||||
// This kinda screws things up when using ST, so let's not.
|
||||
if (m_vt.m_primclass == GS_SPRITE_CLASS && rtscale > 1.0f && (tex && PRIM->FST))
|
||||
@@ -8127,7 +8132,7 @@ GSRendererHW::CLUTDrawTestResult GSRendererHW::PossibleCLUTDraw()
|
||||
const float draw_width = (m_vt.m_max.p.x - m_vt.m_min.p.x);
|
||||
const float draw_height = (m_vt.m_max.p.y - m_vt.m_min.p.y);
|
||||
const bool valid_size = ((draw_width >= min_clut_width || draw_height >= min_clut_height))
|
||||
&& (((draw_width < page_width && draw_height <= page_height) || (draw_width == page_width)) && draw_divder_match); // Make sure draw is multiples of 8 wide (AC5 midetection).
|
||||
&& (((draw_width < page_width && draw_height <= page_height) || (draw_width == page_width)) && draw_divder_match); // Make sure draw is multiples of 8 wide (AC5 midetection).
|
||||
|
||||
// Make sure the draw hits the next CLUT and it's marked as invalid (kind of a sanity check).
|
||||
// We can also allow draws which are of a sensible size within the page, as they could also be CLUT draws (or gradients for the CLUT).
|
||||
@@ -8257,7 +8262,7 @@ bool GSRendererHW::CanUseSwPrimRender(bool no_rt, bool no_ds, bool draw_sprite_t
|
||||
{
|
||||
GSTextureCache::Target* dst_target = g_texture_cache->GetTargetWithSharedBits(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.PSM);
|
||||
|
||||
if (dst_target && dst_target->m_dirty.empty() && ((!(GSUtil::GetChannelMask(m_cached_ctx.FRAME.PSM) & 0x7)) || dst_target->m_valid_rgb) &&
|
||||
if (dst_target && dst_target->m_dirty.empty() && ((!(GSUtil::GetChannelMask(m_cached_ctx.FRAME.PSM) & 0x7)) || dst_target->m_valid_rgb) &&
|
||||
((!(GSUtil::GetChannelMask(m_cached_ctx.FRAME.PSM) & 0x8)) || (dst_target->m_valid_alpha_low && dst_target->m_valid_alpha_high)))
|
||||
return false;
|
||||
}
|
||||
@@ -8355,12 +8360,11 @@ bool GSRendererHW::DetectStripedDoubleClear(bool& no_rt, bool& no_ds)
|
||||
{
|
||||
const bool single_page_offset =
|
||||
std::abs(static_cast<int>(m_cached_ctx.FRAME.FBP) - static_cast<int>(m_cached_ctx.ZBUF.ZBP)) == 1;
|
||||
const bool z_is_frame = (m_cached_ctx.FRAME.FBP == m_cached_ctx.ZBUF.ZBP ||
|
||||
(m_cached_ctx.FRAME.FBW > 1 && single_page_offset)) && // GT4O Public Beta
|
||||
!m_cached_ctx.ZBUF.ZMSK &&
|
||||
(m_cached_ctx.FRAME.PSM & 0x30) != (m_cached_ctx.ZBUF.PSM & 0x30) &&
|
||||
(m_cached_ctx.FRAME.PSM & 0xF) == (m_cached_ctx.ZBUF.PSM & 0xF) && m_vt.m_eq.z == 1 &&
|
||||
m_vertex.buff[1].XYZ.Z == m_vertex.buff[1].RGBAQ.U32[0];
|
||||
const bool z_is_frame = (m_cached_ctx.FRAME.FBP == m_cached_ctx.ZBUF.ZBP || (m_cached_ctx.FRAME.FBW > 1 && single_page_offset)) && // GT4O Public Beta
|
||||
!m_cached_ctx.ZBUF.ZMSK &&
|
||||
(m_cached_ctx.FRAME.PSM & 0x30) != (m_cached_ctx.ZBUF.PSM & 0x30) &&
|
||||
(m_cached_ctx.FRAME.PSM & 0xF) == (m_cached_ctx.ZBUF.PSM & 0xF) && m_vt.m_eq.z == 1 &&
|
||||
m_vertex.buff[1].XYZ.Z == m_vertex.buff[1].RGBAQ.U32[0];
|
||||
|
||||
// Z and color must be constant and the same and must be drawing strips.
|
||||
if (!z_is_frame || m_vt.m_eq.rgba != 0xFFFF)
|
||||
@@ -8874,7 +8878,7 @@ void GSRendererHW::ClearGSLocalMemory(const GSOffset& off, const GSVector4i& r,
|
||||
else if (format == GSLocalMemory::PSM_FMT_16)
|
||||
{
|
||||
const u16 converted_color = ((vert_color >> 16) & 0x8000) | ((vert_color >> 9) & 0x7C00) |
|
||||
((vert_color >> 6) & 0x7E0) | ((vert_color >> 3) & 0x1F);
|
||||
((vert_color >> 6) & 0x7E0) | ((vert_color >> 3) & 0x1F);
|
||||
const GSVector4i vcolor = GSVector4i::broadcast16(converted_color);
|
||||
const u32 iterations_per_page = (pages_wide * pixels_per_page) / 8;
|
||||
pxAssert((off.bp() & (GS_BLOCKS_PER_PAGE - 1)) == 0);
|
||||
@@ -8997,27 +9001,27 @@ bool GSRendererHW::OI_BlitFMV(GSTextureCache::Target* _rt, GSTextureCache::Sourc
|
||||
bool GSRendererHW::AreAnyPixelsDiscarded() const
|
||||
{
|
||||
return ((m_draw_env->SCANMSK.MSK & 2) || // skipping rows
|
||||
(m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.AFAIL != AFAIL_FB_ONLY) || // testing alpha (might discard some pixels)
|
||||
m_cached_ctx.TEST.DATE); // reading alpha
|
||||
(m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.AFAIL != AFAIL_FB_ONLY) || // testing alpha (might discard some pixels)
|
||||
m_cached_ctx.TEST.DATE); // reading alpha
|
||||
}
|
||||
|
||||
bool GSRendererHW::IsDiscardingDstColor()
|
||||
{
|
||||
return ((!PRIM->ABE || IsOpaque() || m_context->ALPHA.IsBlack()) && // no blending or writing black
|
||||
!AreAnyPixelsDiscarded() && (m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) == 0); // no channels masked
|
||||
!AreAnyPixelsDiscarded() && (m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) == 0); // no channels masked
|
||||
}
|
||||
|
||||
bool GSRendererHW::IsDiscardingDstRGB()
|
||||
{
|
||||
return ((!PRIM->ABE || IsOpaque() || m_context->ALPHA.IsBlack() || !m_context->ALPHA.IsCdInBlend()) && // no blending or writing black
|
||||
((m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) & 0xFFFFFFu) == 0); // RGB isn't masked
|
||||
((m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) & 0xFFFFFFu) == 0); // RGB isn't masked
|
||||
}
|
||||
|
||||
bool GSRendererHW::IsDiscardingDstAlpha() const
|
||||
{
|
||||
return ((!PRIM->ABE || m_context->ALPHA.C != 1) && // not using Ad
|
||||
((m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) & 0xFF000000u) == 0) && // alpha isn't masked
|
||||
(!m_cached_ctx.TEST.ATE || !(m_cached_ctx.TEST.ATST == ATST_NEVER && m_cached_ctx.TEST.AFAIL == AFAIL_RGB_ONLY && m_cached_ctx.FRAME.PSM == PSMCT32)); // No alpha test or no rbg only
|
||||
((m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) & 0xFF000000u) == 0) && // alpha isn't masked
|
||||
(!m_cached_ctx.TEST.ATE || !(m_cached_ctx.TEST.ATST == ATST_NEVER && m_cached_ctx.TEST.AFAIL == AFAIL_RGB_ONLY && m_cached_ctx.FRAME.PSM == PSMCT32)); // No alpha test or no rbg only
|
||||
}
|
||||
|
||||
// Like PrimitiveCoversWithoutGaps but with texture coordinates.
|
||||
@@ -9068,12 +9072,12 @@ bool GSRendererHW::TextureCoversWithoutGapsNotEqual()
|
||||
const int this_start_U = v[i].U;
|
||||
const int last_start_U = v[i - 2].U;
|
||||
|
||||
const int dtU = v[i + 1].U - v[i].U;
|
||||
const int dtU = v[i + 1].U - v[i].U;
|
||||
|
||||
if (this_start_U < last_start_U)
|
||||
{
|
||||
if (std::abs(dtU - last_start_U) >= 16 || std::abs(this_start_U) >= 16)
|
||||
{;
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -9440,7 +9444,7 @@ void GSRendererHW::EndHLEHardwareDraw(bool force_copy_on_hazard /* = false */)
|
||||
return;
|
||||
}
|
||||
|
||||
const GSVector4i copy_rect = config.drawarea.rintersect(src->GetRect());
|
||||
const GSVector4i copy_rect = config.drawarea.rintersect(src->GetRect());
|
||||
g_gs_device->CopyRect(src, copy, copy_rect - copy_rect.xyxy(), copy_rect.x, copy_rect.y);
|
||||
config.tex = copy;
|
||||
}
|
||||
@@ -9449,8 +9453,8 @@ void GSRendererHW::EndHLEHardwareDraw(bool force_copy_on_hazard /* = false */)
|
||||
// Drop color1 if dual-source is not being used.
|
||||
config.ps.no_color = !config.rt;
|
||||
config.ps.no_color1 = !config.rt || !config.blend.enable ||
|
||||
(!GSDevice::IsDualSourceBlendFactor(config.blend.src_factor) &&
|
||||
!GSDevice::IsDualSourceBlendFactor(config.blend.dst_factor));
|
||||
(!GSDevice::IsDualSourceBlendFactor(config.blend.src_factor) &&
|
||||
!GSDevice::IsDualSourceBlendFactor(config.blend.dst_factor));
|
||||
|
||||
g_gs_device->RenderHW(m_conf);
|
||||
|
||||
|
||||
@@ -348,7 +348,7 @@ GSVector4i GSTextureCache::TranslateAlignedRectByPage(u32 tbp, u32 tebp, u32 tbw
|
||||
const int rect_pages = std::max(((in_rect.width() / t_psm.pgs.x) % src_pgw) + ((in_rect.height() / t_psm.pgs.y) * src_pgw), 1);
|
||||
page_offset += rect_offset;
|
||||
in_rect -= GSVector4i(horizontal_offset * t_psm.pgs.x, vertical_offset * t_psm.pgs.y).xyxy();
|
||||
|
||||
|
||||
if (sbw == 0) // Intentionally check this separately
|
||||
{
|
||||
// BW == 0 loops vertically on the first page. So just copy the whole page vertically.
|
||||
@@ -391,7 +391,7 @@ GSVector4i GSTextureCache::TranslateAlignedRectByPage(u32 tbp, u32 tebp, u32 tbw
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
|
||||
// Fills full length, so count pages based on the width, adjust rect to fill original rect.
|
||||
// Battle Assault 3 does a move with BW 7 instead of 8 and does 448x512, instead of 512x448. Same result, but confusing for us.
|
||||
@@ -1334,7 +1334,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
continue;
|
||||
|
||||
const bool width_match = (std::max(64U, bw * 64U) >> GSLocalMemory::m_psm[psm].info.pageShiftX()) ==
|
||||
(std::max(64U, t->m_TEX0.TBW * 64U) >> GSLocalMemory::m_psm[t->m_TEX0.PSM].info.pageShiftX());
|
||||
(std::max(64U, t->m_TEX0.TBW * 64U) >> GSLocalMemory::m_psm[t->m_TEX0.PSM].info.pageShiftX());
|
||||
|
||||
if (bp == t->m_TEX0.TBP0 && !t->m_dirty.empty() && GSUtil::GetChannelMask(psm) == GSUtil::GetChannelMask(t->m_TEX0.PSM) && GSRendererHW::GetInstance()->m_draw_transfers.size() > 0)
|
||||
{
|
||||
@@ -1461,7 +1461,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
{
|
||||
rect_clean = false;
|
||||
|
||||
if(!dirty_rect.rintersect(t->m_valid).eq(t->m_valid) || GSUtil::GetChannelMask(t->m_TEX0.PSM) != t->m_dirty.GetDirtyChannels())
|
||||
if (!dirty_rect.rintersect(t->m_valid).eq(t->m_valid) || GSUtil::GetChannelMask(t->m_TEX0.PSM) != t->m_dirty.GetDirtyChannels())
|
||||
partial |= !new_rect.rintersect(dirty_rect).eq(new_rect) || dirty_rect.eq(new_rect);
|
||||
else // Nothing is valid anymore, kill it.
|
||||
{
|
||||
@@ -1484,7 +1484,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
const u32 channels = t->m_dirty.GetDirtyChannels() & channel_mask;
|
||||
const bool dirty_overlap = !t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size).rintersect(new_rect).rempty();
|
||||
// If the source is reading the rt, make sure it's big enough.
|
||||
if (!possible_shuffle && t && GSUtil::HasCompatibleBits(psm, t->m_TEX0.PSM)&& real_fmt_match)
|
||||
if (!possible_shuffle && t && GSUtil::HasCompatibleBits(psm, t->m_TEX0.PSM) && real_fmt_match)
|
||||
{
|
||||
// Be careful if a new texture has been uploaded that expands the current one (Valkyrie Profile 2 does this)
|
||||
GSVector4i dirty_rect = (t->m_dirty.size() > 0 && bw == t->m_TEX0.TBW) ? t->m_dirty.GetTotalRect(t->m_TEX0, GSVector2i(new_rect.z, new_rect.w)) : GSVector4i(GSVector4(t->m_valid) * GSVector4(2));
|
||||
@@ -1595,7 +1595,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
const u32 color_psm = ((psm & 0x30) == 0x30) ? (psm & ~0x30) : psm;
|
||||
const u32 tex_color_psm = ((t->m_TEX0.PSM & 0x30) == 0x30) ? (t->m_TEX0.PSM & ~0x30) : t->m_TEX0.PSM;
|
||||
const bool can_convert = (GSUtil::HasCompatibleBits(psm, t_psm) && ((bw == t->m_TEX0.TBW) || (bw <= 1 && req_rect.w < GSLocalMemory::m_psm[psm].pgs.y))) ||
|
||||
(possible_shuffle && ((bw == t->m_TEX0.TBW) || (bw == (t->m_TEX0.TBW * 2) || bw <= 2)) && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 32);
|
||||
(possible_shuffle && ((bw == t->m_TEX0.TBW) || (bw == (t->m_TEX0.TBW * 2) || bw <= 2)) && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 32);
|
||||
|
||||
if (t->m_was_dst_matched)
|
||||
{
|
||||
@@ -1608,7 +1608,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
for (Target* dst_match : m_dst[DepthStencil])
|
||||
{
|
||||
// Be careful of dirty overlap on the targets, we don't really want dirty data.
|
||||
if (dst_match->m_TEX0.TBP0 != t->m_TEX0.TBP0 || !dst_match->m_valid_rgb ||(!dst_match->m_dirty.empty() && !dst_match->m_dirty.GetTotalRect(dst_match->m_TEX0, dst_match->m_unscaled_size).rintersect(block_boundary_rect).rempty()))
|
||||
if (dst_match->m_TEX0.TBP0 != t->m_TEX0.TBP0 || !dst_match->m_valid_rgb || (!dst_match->m_dirty.empty() && !dst_match->m_dirty.GetTotalRect(dst_match->m_TEX0, dst_match->m_unscaled_size).rintersect(block_boundary_rect).rempty()))
|
||||
continue;
|
||||
|
||||
if (!CopyRGBFromDepthToColor(t, dst_match))
|
||||
@@ -1684,8 +1684,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
// Make sure the texture actually is INSIDE the RT, it's possibly not valid if it isn't.
|
||||
// Also check BP >= TBP, create source isn't equpped to expand it backwards and all data comes from the target. (GH3)
|
||||
else if (GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets &&
|
||||
(GSLocalMemory::m_psm[color_psm].bpp >= 16 || (/*possible_shuffle &&*/ GSLocalMemory::m_psm[color_psm].bpp == 8 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp >= 16)) && // Channel shuffles or non indexed lookups.
|
||||
t->m_age <= 1 && (!found_t || t->m_last_draw > dst->m_last_draw) /*&& CanTranslate(bp, bw, psm, block_boundary_rect, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW)*/)
|
||||
(GSLocalMemory::m_psm[color_psm].bpp >= 16 || (/*possible_shuffle &&*/ GSLocalMemory::m_psm[color_psm].bpp == 8 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp >= 16)) && // Channel shuffles or non indexed lookups.
|
||||
t->m_age <= 1 && (!found_t || t->m_last_draw > dst->m_last_draw) /*&& CanTranslate(bp, bw, psm, block_boundary_rect, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW)*/)
|
||||
{
|
||||
u32 rt_tbw = std::max(1U, t->m_TEX0.TBW);
|
||||
u32 horz_page_offset = ((bp - t->m_TEX0.TBP0) >> 5) % rt_tbw;
|
||||
@@ -1694,18 +1694,20 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
continue;
|
||||
|
||||
if (GSLocalMemory::m_psm[color_psm].bpp == 16 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 32 && bw != 1 &&
|
||||
((t->m_TEX0.TBW < (horz_page_offset + ((block_boundary_rect.z + GSLocalMemory::m_psm[psm].pgs.x - 1) / GSLocalMemory::m_psm[psm].pgs.x)) ||
|
||||
(t->m_TEX0.TBW != bw && block_boundary_rect.w > GSLocalMemory::m_psm[psm].pgs.y))))
|
||||
((t->m_TEX0.TBW < (horz_page_offset + ((block_boundary_rect.z + GSLocalMemory::m_psm[psm].pgs.x - 1) / GSLocalMemory::m_psm[psm].pgs.x)) ||
|
||||
(t->m_TEX0.TBW != bw && block_boundary_rect.w > GSLocalMemory::m_psm[psm].pgs.y))))
|
||||
{
|
||||
DbgCon.Warning("BP %x - 16bit bad match for target bp %x bw %d src %d format %d", bp, t->m_TEX0.TBP0, t->m_TEX0.TBW, bw, t->m_TEX0.PSM);
|
||||
continue;
|
||||
}
|
||||
// Keep note that 2 bw is basically 1 normal page, as bw is in 64 pixels, and 8bit pages are 128 pixels wide, aka 2 bw.
|
||||
// Also check for 4HH/HL and 8H which use the alpha channel, if the page order is wrong this can cause problems as well (Jak X font).
|
||||
else if (!possible_shuffle && GSLocalMemory::m_psm[psm].trbpp <= 8 && (GSUtil::GetChannelMask(t->m_TEX0.PSM) != 0xF ||
|
||||
((GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp != 16 || GSLocalMemory::m_psm[psm].bpp < 16) && (!(block_boundary_rect.w <= GSLocalMemory::m_psm[psm].pgs.y &&
|
||||
((GSLocalMemory::m_psm[psm].bpp == 32) ? bw : ((bw + 1) / 2)) <= t->m_TEX0.TBW) &&
|
||||
!(((GSLocalMemory::m_psm[psm].bpp == 32) ? bw : ((bw + 1) / 2)) == rt_tbw)))))
|
||||
else if (!possible_shuffle && GSLocalMemory::m_psm[psm].trbpp <= 8 &&
|
||||
(GSUtil::GetChannelMask(t->m_TEX0.PSM) != 0xF ||
|
||||
((GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp != 16 || GSLocalMemory::m_psm[psm].bpp < 16) &&
|
||||
(!(block_boundary_rect.w <= GSLocalMemory::m_psm[psm].pgs.y &&
|
||||
((GSLocalMemory::m_psm[psm].bpp == 32) ? bw : ((bw + 1) / 2)) <= t->m_TEX0.TBW) &&
|
||||
!(((GSLocalMemory::m_psm[psm].bpp == 32) ? bw : ((bw + 1) / 2)) == rt_tbw)))))
|
||||
{
|
||||
DbgCon.Warning("BP %x - 8bit bad match for target bp %x bw %d src %d format %d", bp, t->m_TEX0.TBP0, t->m_TEX0.TBW, bw, t->m_TEX0.PSM);
|
||||
continue;
|
||||
@@ -1870,9 +1872,9 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
const GSOffset offset(GSLocalMemory::m_psm[src_psm].info, bp, bw, psm);
|
||||
const u32 offset_bp = offset.bn(region.GetMinX(), region.GetMinY());
|
||||
if (bp < t->m_TEX0.TBP0 && region.HasX() && region.HasY() &&
|
||||
(region.GetMinX() & (page_size.x - 1)) == 0 && (region.GetMinY() & (page_size.y - 1)) == 0 &&
|
||||
(offset.bn(region.GetMinX(), region.GetMinY()) == t->m_TEX0.TBP0 ||
|
||||
((offset_bp >= t->m_TEX0.TBP0) && ((((offset_bp - t->m_TEX0.TBP0) >> 5) % bw) + (rect.width() / page_size.x)) <= bw)))
|
||||
(region.GetMinX() & (page_size.x - 1)) == 0 && (region.GetMinY() & (page_size.y - 1)) == 0 &&
|
||||
(offset.bn(region.GetMinX(), region.GetMinY()) == t->m_TEX0.TBP0 ||
|
||||
((offset_bp >= t->m_TEX0.TBP0) && ((((offset_bp - t->m_TEX0.TBP0) >> 5) % bw) + (rect.width() / page_size.x)) <= bw)))
|
||||
{
|
||||
GL_CACHE("TC: Target 0x%x detected in front of TBP 0x%x with %d,%d offset (%d pages)",
|
||||
t->m_TEX0.TBP0, TEX0.TBP0, region.GetMinX(), region.GetMinY(),
|
||||
@@ -2292,7 +2294,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
if (bp == t->m_TEX0.TBP0)
|
||||
{
|
||||
bool can_use = true;
|
||||
|
||||
|
||||
if (dst && ((GSState::s_n - dst->m_last_draw) < (GSState::s_n - t->m_last_draw) && dst->m_TEX0.TBP0 <= bp))
|
||||
{
|
||||
DevCon.Warning("Ignoring target at %x as one at %x is newer", t->m_TEX0.TBP0, dst->m_TEX0.TBP0);
|
||||
@@ -2452,7 +2454,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
const GSVector4i dirty_rect = t->m_dirty.empty() ? GSVector4i::zero() : t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size);
|
||||
const bool all_dirty = dirty_rect.eq(t->m_valid);
|
||||
|
||||
|
||||
|
||||
if (!is_shuffle && !dirty_rect.rempty() && (!preserve_alpha && !preserve_rgb) && (GSState::s_n - 3) > t->m_last_draw)
|
||||
{
|
||||
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s due to dirty areas not preserved (Likely change in target)", t->m_TEX0.TBP0, t->m_TEX0.TBW, GSUtil::GetPSMName(t->m_TEX0.PSM));
|
||||
@@ -2627,7 +2629,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
{
|
||||
calcRescale(dst);
|
||||
GSTexture* tex = type == RenderTarget ? g_gs_device->CreateRenderTarget(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::Color, clear) :
|
||||
g_gs_device->CreateDepthStencil(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::DepthStencil, clear);
|
||||
g_gs_device->CreateDepthStencil(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::DepthStencil, clear);
|
||||
if (!tex)
|
||||
return nullptr;
|
||||
|
||||
@@ -2680,8 +2682,11 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
new_scaled_size = ScaleRenderTargetSize(dst->m_unscaled_size, dst->m_scale);
|
||||
|
||||
dRect = (GSVector4(dst->m_valid) * GSVector4(dst->m_scale)).ceil();
|
||||
GSVector4 source_rect = GSVector4(static_cast<float>(dst->m_valid.x) / static_cast<float>(dst->m_unscaled_size.x), static_cast<float>(dst->m_valid.y) / static_cast<float>(dst->m_unscaled_size.y),
|
||||
static_cast<float>(dst->m_valid.z) / static_cast<float>(dst->m_unscaled_size.x), static_cast<float>(dst->m_valid.w) / static_cast<float>(dst->m_unscaled_size.y));
|
||||
GSVector4 source_rect = GSVector4(
|
||||
static_cast<float>(dst->m_valid.x) / static_cast<float>(dst->m_unscaled_size.x),
|
||||
static_cast<float>(dst->m_valid.y) / static_cast<float>(dst->m_unscaled_size.y),
|
||||
static_cast<float>(dst->m_valid.z) / static_cast<float>(dst->m_unscaled_size.x),
|
||||
static_cast<float>(dst->m_valid.w) / static_cast<float>(dst->m_unscaled_size.y));
|
||||
if (!is_shuffle || GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp == 16)
|
||||
{
|
||||
if (scale_down)
|
||||
@@ -2727,7 +2732,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
else
|
||||
{
|
||||
GSTexture* tex = type == RenderTarget ? g_gs_device->CreateRenderTarget(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::Color, clear) :
|
||||
g_gs_device->CreateDepthStencil(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::DepthStencil, clear);
|
||||
g_gs_device->CreateDepthStencil(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::DepthStencil, clear);
|
||||
if (!tex)
|
||||
return nullptr;
|
||||
|
||||
@@ -2748,7 +2753,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
else
|
||||
{
|
||||
GSTexture* tex = type == RenderTarget ? g_gs_device->CreateRenderTarget(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::Color, clear) :
|
||||
g_gs_device->CreateDepthStencil(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::DepthStencil, clear);
|
||||
g_gs_device->CreateDepthStencil(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::DepthStencil, clear);
|
||||
if (!tex)
|
||||
return nullptr;
|
||||
|
||||
@@ -2769,7 +2774,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
}
|
||||
|
||||
// New format or doing a shuffle to a 32bit target that used to be 16bit
|
||||
if ((!is_shuffle && (GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp != GSLocalMemory::m_psm[TEX0.PSM].bpp || GSLocalMemory::m_psm[dst->m_TEX0.PSM].depth != GSLocalMemory::m_psm[TEX0.PSM].depth)) ||
|
||||
if ((!is_shuffle && (GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp != GSLocalMemory::m_psm[TEX0.PSM].bpp || GSLocalMemory::m_psm[dst->m_TEX0.PSM].depth != GSLocalMemory::m_psm[TEX0.PSM].depth)) ||
|
||||
(is_shuffle && GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp == 16))
|
||||
{
|
||||
if (GSLocalMemory::m_psm[dst->m_TEX0.PSM].depth != GSLocalMemory::m_psm[TEX0.PSM].depth || dst->m_TEX0.TBW != TEX0.TBW)
|
||||
@@ -2835,8 +2840,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
}
|
||||
|
||||
const ShaderConvert shader = (GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp == 16) ? ShaderConvert::RGB5A1_TO_FLOAT16 :
|
||||
(GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp == 32) ? ShaderConvert::RGBA8_TO_FLOAT32 :
|
||||
ShaderConvert::RGBA8_TO_FLOAT24;
|
||||
(GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp == 32) ? ShaderConvert::RGBA8_TO_FLOAT32 :
|
||||
ShaderConvert::RGBA8_TO_FLOAT24;
|
||||
|
||||
g_gs_device->StretchRect(dst_match->m_texture, GSVector4(0, 0, 1, 1),
|
||||
dst->m_texture, GSVector4(dst->GetUnscaledRect()) * GSVector4(dst->GetScale()), shader, false);
|
||||
@@ -2859,10 +2864,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
// Unfortunately, we still have an alpha channel to preserve, and we can't clear RGB...
|
||||
// So, create a new target, clear/preload it, and copy RGB in.
|
||||
GSTexture* tex = (type == RenderTarget) ?
|
||||
g_gs_device->CreateRenderTarget(dst->m_texture->GetWidth(),
|
||||
dst->m_texture->GetHeight(), GSTexture::Format::Color, true) :
|
||||
g_gs_device->CreateDepthStencil(dst->m_texture->GetWidth(),
|
||||
dst->m_texture->GetHeight(), GSTexture::Format::DepthStencil, true);
|
||||
g_gs_device->CreateRenderTarget(dst->m_texture->GetWidth(), dst->m_texture->GetHeight(), GSTexture::Format::Color, true) :
|
||||
g_gs_device->CreateDepthStencil(dst->m_texture->GetWidth(), dst->m_texture->GetHeight(), GSTexture::Format::DepthStencil, true);
|
||||
if (!tex)
|
||||
return nullptr;
|
||||
|
||||
@@ -2943,7 +2946,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
}
|
||||
// If the format is completely different, but it's the same location, it's likely just overwriting it, so get rid.
|
||||
// Make sure it's not currently in use, that could be bad.
|
||||
if (!is_shuffle && (!ds || (ds != t)) &&
|
||||
if (!is_shuffle && (!ds || (ds != t)) &&
|
||||
t->m_TEX0.TBW != TEX0.TBW && TEX0.TBW != 1 && !preserve_rgb && min_rect.w > GSLocalMemory::m_psm[t->m_TEX0.PSM].pgs.y)
|
||||
{
|
||||
if (src && src->m_target && src->m_from_target == t && src->m_target_direct)
|
||||
@@ -3017,7 +3020,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
// If we don't need A, and the existing target doesn't have valid alpha, don't bother converting it.
|
||||
const bool has_alpha = dst_match->HasValidAlpha();
|
||||
const bool preserve_target = (preserve_rgb || (preserve_alpha && has_alpha)) ||
|
||||
!draw_rect.rintersect(dst_match->m_valid).eq(dst_match->m_valid);
|
||||
!draw_rect.rintersect(dst_match->m_valid).eq(dst_match->m_valid);
|
||||
|
||||
bool half_width = false;
|
||||
|
||||
@@ -3069,7 +3072,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
GL_CACHE("TC: Lookup Target(Depth) %dx%d, hit Color (0x%x, TBW %d, %s was %s)", new_size.x, new_size.y,
|
||||
bp, TEX0.TBW, GSUtil::GetPSMName(TEX0.PSM), GSUtil::GetPSMName(dst_match->m_TEX0.PSM));
|
||||
shader = (fmt_16_bits) ? ShaderConvert::RGB5A1_TO_FLOAT16 :
|
||||
(ShaderConvert)(static_cast<int>(ShaderConvert::RGBA8_TO_FLOAT32) + psm_s.fmt);
|
||||
(ShaderConvert)(static_cast<int>(ShaderConvert::RGBA8_TO_FLOAT32) + psm_s.fmt);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3402,7 +3405,7 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const GSVector4i dst_valid = dst->m_valid.rempty() ? GSVector4i::loadh(valid_size) : dst->m_valid;
|
||||
u32 dst_end_block = GSLocalMemory::GetEndBlockAddress(dst->m_TEX0.TBP0, dst->m_TEX0.TBW, dst->m_TEX0.PSM, dst_valid);
|
||||
if (dst_end_block < dst->m_TEX0.TBP0)
|
||||
@@ -3433,7 +3436,7 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
|
||||
// Probably best we don't poke the beast if it's being used as the current source.
|
||||
if (src && src->m_target_direct && src->m_from_target == t)
|
||||
continue;
|
||||
|
||||
|
||||
InvalidateSourcesFromTarget(t);
|
||||
i = list.erase(j);
|
||||
delete t;
|
||||
@@ -3541,7 +3544,7 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
|
||||
|
||||
GL_INS("TC: RT double buffer copy from FBP 0x%x, %dx%d => %d,%d", t->m_TEX0.TBP0, copy_width, copy_height, 0, dst_offset_scaled_height);
|
||||
|
||||
|
||||
|
||||
// Clear the dirty first
|
||||
t->Update();
|
||||
dst->Update();
|
||||
@@ -3621,11 +3624,12 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
|
||||
t->m_was_dst_matched = true;
|
||||
|
||||
dst->ResizeTexture(t->m_unscaled_size.x, t->m_unscaled_size.y);
|
||||
|
||||
const ShaderConvert shader = (GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp == 16) ? ShaderConvert::RGB5A1_TO_FLOAT16 :
|
||||
(GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp == 32) ? ShaderConvert::RGBA8_TO_FLOAT32 : ShaderConvert::RGBA8_TO_FLOAT24;
|
||||
|
||||
g_gs_device->StretchRect(t->m_texture, GSVector4(0,0,1,1),
|
||||
const ShaderConvert shader = (GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp == 16) ? ShaderConvert::RGB5A1_TO_FLOAT16 :
|
||||
(GSLocalMemory::m_psm[dst->m_TEX0.PSM].trbpp == 32) ? ShaderConvert::RGBA8_TO_FLOAT32 :
|
||||
ShaderConvert::RGBA8_TO_FLOAT24;
|
||||
|
||||
g_gs_device->StretchRect(t->m_texture, GSVector4(0, 0, 1, 1),
|
||||
dst->m_texture, GSVector4(t->GetUnscaledRect()) * GSVector4(dst->GetScale()), shader, false);
|
||||
|
||||
break;
|
||||
@@ -3658,10 +3662,8 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
|
||||
t->ResizeValidity(t->m_valid);
|
||||
|
||||
GSTexture* tex = (t->m_type == RenderTarget) ?
|
||||
g_gs_device->CreateRenderTarget(t->m_texture->GetWidth(),
|
||||
t->m_texture->GetHeight(), GSTexture::Format::Color, true) :
|
||||
g_gs_device->CreateDepthStencil(t->m_texture->GetWidth(),
|
||||
t->m_texture->GetHeight(), GSTexture::Format::DepthStencil, true);
|
||||
g_gs_device->CreateRenderTarget(t->m_texture->GetWidth(), t->m_texture->GetHeight(), GSTexture::Format::Color, true) :
|
||||
g_gs_device->CreateDepthStencil(t->m_texture->GetWidth(), t->m_texture->GetHeight(), GSTexture::Format::DepthStencil, true);
|
||||
if (tex)
|
||||
{
|
||||
g_gs_device->CopyRect(t->m_texture, tex, GSVector4i(0, height_adjust * t->m_scale, t->m_texture->GetWidth(), t->m_texture->GetHeight()), 0, 0);
|
||||
@@ -3702,7 +3704,6 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
i++;
|
||||
}
|
||||
@@ -3937,8 +3938,8 @@ float GSTextureCache::ConvertColorToDepth(u32 c, ShaderConvert convert)
|
||||
{
|
||||
case ShaderConvert::RGB5A1_TO_FLOAT16:
|
||||
return static_cast<float>(((c & 0xF8u) >> 3) | (((c >> 8) & 0xF8u) << 2) | (((c >> 16) & 0xF8u) << 7) |
|
||||
(((c >> 24) & 0x80u) << 8)) *
|
||||
mult;
|
||||
(((c >> 24) & 0x80u) << 8)) *
|
||||
mult;
|
||||
|
||||
case ShaderConvert::RGBA8_TO_FLOAT16:
|
||||
return static_cast<float>(c & 0x0000FFFF) * mult;
|
||||
@@ -4185,7 +4186,7 @@ void GSTextureCache::InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 wr
|
||||
if (type == DepthStencil && t->m_TEX0.TBP0 < start_bp && t->m_end_block > start_bp)
|
||||
{
|
||||
const GSVector4i masked_valid = GSVector4i(t->m_valid.x, t->m_valid.y, t->m_valid.z & ~1, t->m_valid.w & ~1);
|
||||
const u32 reduced_endblock = GSLocalMemory::GetEndBlockAddress(t->m_TEX0.TBP0, t->m_TEX0.TBW, t->m_TEX0.PSM, masked_valid);
|
||||
const u32 reduced_endblock = GSLocalMemory::GetEndBlockAddress(t->m_TEX0.TBP0, t->m_TEX0.TBW, t->m_TEX0.PSM, masked_valid);
|
||||
|
||||
if (reduced_endblock <= start_bp)
|
||||
{
|
||||
@@ -5040,8 +5041,8 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u
|
||||
if (SBP == DBP && (!(GSVector4i(sx, sy, sx + w, sy + h).rintersect(GSVector4i(dx, dy, dx + w, dy + h))).rempty() || renderer_is_directx))
|
||||
{
|
||||
GSTexture* tmp_texture = src->m_texture->IsDepthStencil() ?
|
||||
g_gs_device->CreateDepthStencil(src->m_texture->GetWidth(), src->m_texture->GetHeight(), src->m_texture->GetFormat(), false) :
|
||||
g_gs_device->CreateRenderTarget(src->m_texture->GetWidth(), src->m_texture->GetHeight(), src->m_texture->GetFormat(), false);
|
||||
g_gs_device->CreateDepthStencil(src->m_texture->GetWidth(), src->m_texture->GetHeight(), src->m_texture->GetFormat(), false) :
|
||||
g_gs_device->CreateRenderTarget(src->m_texture->GetWidth(), src->m_texture->GetHeight(), src->m_texture->GetFormat(), false);
|
||||
if (!tmp_texture)
|
||||
{
|
||||
Console.Error("(HW Move) Failed to allocate temporary %dx%d texture on HW move", w, h);
|
||||
@@ -5109,7 +5110,6 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u
|
||||
}
|
||||
const GSVector4 src_rect = GSVector4(scaled_sx, scaled_sy, scaled_sx + scaled_w, scaled_sy + scaled_h) / (GSVector4(src->m_texture->GetSize()).xyxy());
|
||||
g_gs_device->StretchRect(src->m_texture, src_rect, dst->m_texture, GSVector4(scaled_sx, scaled_sy, scaled_sx + scaled_w, scaled_sy + scaled_h), shader, false);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -5725,8 +5725,8 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
||||
const bool outside_target = ((x + w) > dst->m_texture->GetWidth() || (y + h) > dst->m_texture->GetHeight());
|
||||
GSTexture* sTex = dst->m_texture;
|
||||
GSTexture* dTex = outside_target ?
|
||||
g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color, true, PreferReusedLabelledTexture()) :
|
||||
g_gs_device->CreateTexture(w, h, tlevels, GSTexture::Format::Color, PreferReusedLabelledTexture());
|
||||
g_gs_device->CreateRenderTarget(w, h, GSTexture::Format::Color, true, PreferReusedLabelledTexture()) :
|
||||
g_gs_device->CreateTexture(w, h, tlevels, GSTexture::Format::Color, PreferReusedLabelledTexture());
|
||||
if (!dTex) [[unlikely]]
|
||||
{
|
||||
Console.Error("Failed to allocate %dx%d texture for offset source", w, h);
|
||||
@@ -6037,10 +6037,8 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
||||
// 'src' is the new texture cache entry (hence the output)
|
||||
GSTexture* sTex = dst->m_texture;
|
||||
GSTexture* dTex = use_texture ?
|
||||
g_gs_device->CreateTexture(new_size.x, new_size.y, 1, GSTexture::Format::Color,
|
||||
PreferReusedLabelledTexture()) :
|
||||
g_gs_device->CreateRenderTarget(new_size.x, new_size.y, GSTexture::Format::Color,
|
||||
source_rect_empty || destX != 0 || destY != 0, PreferReusedLabelledTexture());
|
||||
g_gs_device->CreateTexture(new_size.x, new_size.y, 1, GSTexture::Format::Color, PreferReusedLabelledTexture()) :
|
||||
g_gs_device->CreateRenderTarget(new_size.x, new_size.y, GSTexture::Format::Color, source_rect_empty || destX != 0 || destY != 0, PreferReusedLabelledTexture());
|
||||
if (!dTex) [[unlikely]]
|
||||
{
|
||||
Console.Error("Failed to allocate %dx%d texture for target copy to source", new_size.x, new_size.y);
|
||||
@@ -6090,7 +6088,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
||||
|
||||
// Adjust to match a PSMT8 texture (coordinates are double C32, we shouldn't be converting from anything else).
|
||||
x_offset *= 2;
|
||||
if (GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp == 32)
|
||||
if (GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp == 32)
|
||||
y_offset *= 2;
|
||||
|
||||
src->m_region.SetX(x_offset, x_offset + tw);
|
||||
@@ -6552,7 +6550,7 @@ GSTextureCache::HashCacheEntry* GSTextureCache::LookupHashCache(const GIFRegTEX0
|
||||
{
|
||||
// don't bother hashing if we're not dumping or replacing.
|
||||
const bool dump = GSConfig.DumpReplaceableTextures && (!FMVstarted || GSConfig.DumpTexturesWithFMVActive) &&
|
||||
(clut ? GSConfig.DumpPaletteTextures : GSConfig.DumpDirectTextures);
|
||||
(clut ? GSConfig.DumpPaletteTextures : GSConfig.DumpDirectTextures);
|
||||
const bool replace = GSConfig.LoadTextureReplacements && GSTextureReplacements::HasAnyReplacementTextures();
|
||||
bool can_cache = (TEX0.PSM >= PSMT8H && TEX0.PSM <= PSMT4HH) ? CanPreloadTextureSize(TEX0.TW, TEX0.TH) : CanCacheTextureSize(TEX0.TW, TEX0.TH);
|
||||
if (!dump && !replace && !can_cache)
|
||||
@@ -6773,8 +6771,8 @@ GSTextureCache::Target* GSTextureCache::Target::Create(GIFRegTEX0 TEX0, int w, i
|
||||
const int scaled_w = static_cast<int>(std::ceil(static_cast<float>(w) * scale));
|
||||
const int scaled_h = static_cast<int>(std::ceil(static_cast<float>(h) * scale));
|
||||
GSTexture* texture = (type == RenderTarget) ?
|
||||
g_gs_device->CreateRenderTarget(scaled_w, scaled_h, GSTexture::Format::Color, clear, PreferReusedLabelledTexture()) :
|
||||
g_gs_device->CreateDepthStencil(scaled_w, scaled_h, GSTexture::Format::DepthStencil, clear, PreferReusedLabelledTexture());
|
||||
g_gs_device->CreateRenderTarget(scaled_w, scaled_h, GSTexture::Format::Color, clear, PreferReusedLabelledTexture()) :
|
||||
g_gs_device->CreateDepthStencil(scaled_w, scaled_h, GSTexture::Format::DepthStencil, clear, PreferReusedLabelledTexture());
|
||||
if (!texture)
|
||||
return nullptr;
|
||||
|
||||
@@ -7314,7 +7312,7 @@ void GSTextureCache::Source::Flush(u32 count, int layer, const GSOffset& off)
|
||||
|
||||
// need to offset if we're a region texture
|
||||
const u8* src = s_unswizzle_buffer + (pitch * static_cast<u32>(std::max(tex_r.top - r.top, 0))) +
|
||||
(static_cast<u32>(std::max(tex_r.left - r.left, 0)) << (m_palette ? 0 : 2));
|
||||
(static_cast<u32>(std::max(tex_r.left - r.left, 0)) << (m_palette ? 0 : 2));
|
||||
m_texture->Update(rint - tex_r.xyxy(), src, pitch, layer);
|
||||
}
|
||||
|
||||
@@ -7410,8 +7408,8 @@ GSTextureCache::Target::~Target()
|
||||
if (src->m_from_target == this)
|
||||
{
|
||||
pxFail(fmt::format("Source at TBP {:x} for target at TBP {:x} on target invalidation",
|
||||
static_cast<u32>(src->m_TEX0.TBP0), static_cast<u32>(m_TEX0.TBP0))
|
||||
.c_str());
|
||||
static_cast<u32>(src->m_TEX0.TBP0), static_cast<u32>(m_TEX0.TBP0)
|
||||
).c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -7749,10 +7747,8 @@ bool GSTextureCache::Target::ResizeTexture(int new_unscaled_width, int new_unsca
|
||||
const bool clear = (new_size.x > size.x || new_size.y > size.y);
|
||||
|
||||
GSTexture* tex = m_texture->IsDepthStencil() ?
|
||||
g_gs_device->CreateDepthStencil(new_size.x, new_size.y, m_texture->GetFormat(), clear,
|
||||
PreferReusedLabelledTexture()) :
|
||||
g_gs_device->CreateRenderTarget(new_size.x, new_size.y, m_texture->GetFormat(), clear,
|
||||
PreferReusedLabelledTexture());
|
||||
g_gs_device->CreateDepthStencil(new_size.x, new_size.y, m_texture->GetFormat(), clear, PreferReusedLabelledTexture()) :
|
||||
g_gs_device->CreateRenderTarget(new_size.x, new_size.y, m_texture->GetFormat(), clear, PreferReusedLabelledTexture());
|
||||
if (!tex)
|
||||
{
|
||||
Console.Error("(ResizeTexture) Failed to allocate %dx%d texture from %dx%d texture", size.x, size.y, new_size.x, new_size.y);
|
||||
@@ -8261,8 +8257,8 @@ u64 GSTextureCache::PaletteKeyHash::operator()(const PaletteKey& key) const
|
||||
{
|
||||
pxAssert(key.pal == 16 || key.pal == 256);
|
||||
return key.pal == 16 ?
|
||||
GSXXH3_64bits(key.clut, sizeof(key.clut[0]) * 16) :
|
||||
GSXXH3_64bits(key.clut, sizeof(key.clut[0]) * 256);
|
||||
GSXXH3_64bits(key.clut, sizeof(key.clut[0]) * 16) :
|
||||
GSXXH3_64bits(key.clut, sizeof(key.clut[0]) * 256);
|
||||
};
|
||||
|
||||
// GSTextureCache::PaletteKeyEqual
|
||||
@@ -8571,7 +8567,7 @@ static void HashTextureLevel(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, GST
|
||||
|
||||
// Hash the expanded texture.
|
||||
u8* ptr = temp + (pitch * static_cast<u32>(rect.top - block_rect.top)) +
|
||||
static_cast<u32>(rect.left - block_rect.left);
|
||||
static_cast<u32>(rect.left - block_rect.left);
|
||||
if (pitch == row_size)
|
||||
{
|
||||
BlockHashAccumulate(hash_st, ptr, pitch * static_cast<u32>(th));
|
||||
@@ -8649,7 +8645,7 @@ void GSTextureCache::PreloadTexture(const GIFRegTEX0& TEX0, const GIFRegTEXA& TE
|
||||
rtx(mem, off, block_rect, buff, pitch, TEXA);
|
||||
|
||||
const u8* ptr = buff + (pitch * static_cast<u32>(rect.top - block_rect.top)) +
|
||||
(static_cast<u32>(rect.left - block_rect.left) << (paltex ? 0 : 2));
|
||||
(static_cast<u32>(rect.left - block_rect.left) << (paltex ? 0 : 2));
|
||||
|
||||
if (alpha_minmax)
|
||||
*alpha_minmax = GSGetRGBA8AlphaMinMax(ptr, unoffset_rect.width(), unoffset_rect.height(), pitch);
|
||||
|
||||
@@ -290,7 +290,7 @@ public:
|
||||
public:
|
||||
HashCacheEntry* m_from_hash_cache = nullptr;
|
||||
std::shared_ptr<Palette> m_palette_obj;
|
||||
std::unique_ptr<u32[]> m_valid;// each u32 bits map to the 32 blocks of that page
|
||||
std::unique_ptr<u32[]> m_valid; // each u32 bits map to the 32 blocks of that page
|
||||
GSTexture* m_palette = nullptr;
|
||||
GSVector4i m_valid_rect = {};
|
||||
GSVector2i m_lod = {};
|
||||
@@ -398,13 +398,13 @@ public:
|
||||
|
||||
struct SurfaceOffsetKey
|
||||
{
|
||||
std::array<SurfaceOffsetKeyElem, 2> elems; // A and B elems.
|
||||
std::array<SurfaceOffsetKeyElem, 2> elems; // A and B elems.
|
||||
};
|
||||
|
||||
struct SurfaceOffset
|
||||
{
|
||||
bool is_valid;
|
||||
GSVector4i b2a_offset; // B to A offset in B coords.
|
||||
GSVector4i b2a_offset; // B to A offset in B coords.
|
||||
};
|
||||
|
||||
struct SurfaceOffsetKeyHash
|
||||
@@ -504,9 +504,9 @@ public:
|
||||
Target* FindTargetOverlap(Target* target, int type, int psm);
|
||||
void CombineAlignedInsideTargets(Target* target, GSTextureCache::Source* src = nullptr);
|
||||
Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0,
|
||||
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_rgb = true, bool preserve_alpha = true,
|
||||
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_rgb = true, bool preserve_alpha = true,
|
||||
const GSVector4i draw_rc = GSVector4i::zero(), bool is_shuffle = false, bool possible_clear = false, bool preserve_scale = false, GSTextureCache::Source* src = nullptr, GSTextureCache::Target* ds = nullptr, int offset = -1);
|
||||
Target* CreateTarget(GIFRegTEX0 TEX0, const GSVector2i& size, const GSVector2i& valid_size,float scale, int type, bool used = true, u32 fbmask = 0,
|
||||
Target* CreateTarget(GIFRegTEX0 TEX0, const GSVector2i& size, const GSVector2i& valid_size, float scale, int type, bool used = true, u32 fbmask = 0,
|
||||
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_target = true,
|
||||
const GSVector4i draw_rc = GSVector4i::zero(), GSTextureCache::Source* src = nullptr);
|
||||
Target* LookupDisplayTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, bool is_feedback);
|
||||
|
||||
@@ -380,10 +380,8 @@ constexpr DDS_PIXELFORMAT DDSPF_R8G8B8 = {
|
||||
|
||||
static bool DDSPixelFormatMatches(const DDS_PIXELFORMAT& pf1, const DDS_PIXELFORMAT& pf2)
|
||||
{
|
||||
return std::tie(pf1.dwSize, pf1.dwFlags, pf1.dwFourCC, pf1.dwRGBBitCount, pf1.dwRBitMask,
|
||||
pf1.dwGBitMask, pf1.dwGBitMask, pf1.dwBBitMask, pf1.dwABitMask) ==
|
||||
std::tie(pf2.dwSize, pf2.dwFlags, pf2.dwFourCC, pf2.dwRGBBitCount, pf2.dwRBitMask,
|
||||
pf2.dwGBitMask, pf2.dwGBitMask, pf2.dwBBitMask, pf2.dwABitMask);
|
||||
return std::tie(pf1.dwSize, pf1.dwFlags, pf1.dwFourCC, pf1.dwRGBBitCount, pf1.dwRBitMask, pf1.dwGBitMask, pf1.dwGBitMask, pf1.dwBBitMask, pf1.dwABitMask) ==
|
||||
std::tie(pf2.dwSize, pf2.dwFlags, pf2.dwFourCC, pf2.dwRGBBitCount, pf2.dwRBitMask, pf2.dwGBitMask, pf2.dwGBitMask, pf2.dwBBitMask, pf2.dwABitMask);
|
||||
}
|
||||
|
||||
struct DDSLoadInfo
|
||||
|
||||
@@ -527,11 +527,12 @@ fragment half4 ps_imgui(ImGuiShaderData data [[stage_in]], texture2d<half> textu
|
||||
return data.c * texture.sample(s, data.t);
|
||||
}
|
||||
|
||||
fragment float4 ps_shadeboost(float4 p [[position]], DirectReadTextureIn<float> tex, constant float3& cb [[buffer(GSMTLBufferIndexUniforms)]])
|
||||
fragment float4 ps_shadeboost(float4 p [[position]], DirectReadTextureIn<float> tex, constant float4& cb [[buffer(GSMTLBufferIndexUniforms)]])
|
||||
{
|
||||
const float brt = cb.x;
|
||||
const float con = cb.y;
|
||||
const float sat = cb.z;
|
||||
const float gam = cb.w;
|
||||
// Increase or decrease these values to adjust r, g and b color channels separately
|
||||
const float AvgLumR = 0.5;
|
||||
const float AvgLumG = 0.5;
|
||||
@@ -546,5 +547,7 @@ fragment float4 ps_shadeboost(float4 p [[position]], DirectReadTextureIn<float>
|
||||
float3 satColor = mix(intensity, brtColor, sat);
|
||||
float3 conColor = mix(AvgLumin, satColor, con);
|
||||
|
||||
return float4(conColor, 1);
|
||||
float3 csb = pow(conColor, float3(1.0 / gam));
|
||||
|
||||
return float4(csb, 1);
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ std::unique_ptr<GSDownloadTextureOGL> GSDownloadTextureOGL::Create(u32 width, u3
|
||||
const u32 buffer_size = GetBufferSize(width, height, format, TEXTURE_UPLOAD_PITCH_ALIGNMENT);
|
||||
|
||||
const bool use_buffer_storage = (GLAD_GL_VERSION_4_4 || GLAD_GL_ARB_buffer_storage || GLAD_GL_EXT_buffer_storage) &&
|
||||
!GSDeviceOGL::GetInstance()->IsDownloadPBODisabled();
|
||||
!GSDeviceOGL::GetInstance()->IsDownloadPBODisabled();
|
||||
if (use_buffer_storage)
|
||||
{
|
||||
GLuint buffer_id;
|
||||
|
||||
@@ -658,8 +658,8 @@ bool GSDeviceVK::CreateDevice(VkSurfaceKHR surface, bool enable_validation_layer
|
||||
vkGetDeviceQueue(m_device, m_present_queue_family_index, 0, &m_present_queue);
|
||||
}
|
||||
m_spinning_supported = m_spin_queue_family_index != queue_family_count &&
|
||||
queue_family_properties[m_graphics_queue_family_index].timestampValidBits > 0 &&
|
||||
m_device_properties.limits.timestampPeriod > 0;
|
||||
queue_family_properties[m_graphics_queue_family_index].timestampValidBits > 0 &&
|
||||
m_device_properties.limits.timestampPeriod > 0;
|
||||
m_spin_queue_is_graphics_queue =
|
||||
m_spin_queue_family_index == m_graphics_queue_family_index && spin_queue_index == 0;
|
||||
|
||||
@@ -1089,7 +1089,7 @@ bool GSDeviceVK::SetGPUTimingEnabled(bool enabled)
|
||||
void GSDeviceVK::ScanForCommandBufferCompletion()
|
||||
{
|
||||
for (u32 check_index = (m_current_frame + 1) % NUM_COMMAND_BUFFERS; check_index != m_current_frame;
|
||||
check_index = (check_index + 1) % NUM_COMMAND_BUFFERS)
|
||||
check_index = (check_index + 1) % NUM_COMMAND_BUFFERS)
|
||||
{
|
||||
FrameResources& resources = m_frame_resources[check_index];
|
||||
if (resources.fence_counter <= m_completed_fence_counter)
|
||||
@@ -2719,8 +2719,8 @@ VkFormat GSDeviceVK::LookupNativeFormat(GSTexture::Format format) const
|
||||
}};
|
||||
|
||||
return (format != GSTexture::Format::DepthStencil || m_features.stencil_buffer) ?
|
||||
s_format_mapping[static_cast<int>(format)] :
|
||||
VK_FORMAT_D32_SFLOAT;
|
||||
s_format_mapping[static_cast<int>(format)] :
|
||||
VK_FORMAT_D32_SFLOAT;
|
||||
}
|
||||
|
||||
GSTexture* GSDeviceVK::CreateSurface(GSTexture::Type type, int width, int height, int levels, GSTexture::Format format)
|
||||
@@ -3197,12 +3197,10 @@ void GSDeviceVK::DoMerge(GSTexture* sTex[3], GSVector4* sRect, GSTexture* dTex,
|
||||
EndRenderPass();
|
||||
|
||||
// transition everything before starting the new render pass
|
||||
const bool has_input_0 =
|
||||
(sTex[0] && (sTex[0]->GetState() == GSTexture::State::Dirty ||
|
||||
(sTex[0]->GetState() == GSTexture::State::Cleared || sTex[0]->GetClearColor() != 0)));
|
||||
const bool has_input_0 = (sTex[0] &&
|
||||
(sTex[0]->GetState() == GSTexture::State::Dirty || (sTex[0]->GetState() == GSTexture::State::Cleared || sTex[0]->GetClearColor() != 0)));
|
||||
const bool has_input_1 = (PMODE.SLBG == 0 || feedback_write_2_but_blend_bg) && sTex[1] &&
|
||||
(sTex[1]->GetState() == GSTexture::State::Dirty ||
|
||||
(sTex[1]->GetState() == GSTexture::State::Cleared || sTex[1]->GetClearColor() != 0));
|
||||
(sTex[1]->GetState() == GSTexture::State::Dirty || (sTex[1]->GetState() == GSTexture::State::Cleared || sTex[1]->GetClearColor() != 0));
|
||||
if (has_input_0)
|
||||
{
|
||||
static_cast<GSTextureVK*>(sTex[0])->CommitClear();
|
||||
@@ -3825,15 +3823,14 @@ bool GSDeviceVK::CreateRenderPasses()
|
||||
{
|
||||
for (u32 opa = VK_ATTACHMENT_LOAD_OP_LOAD; opa <= VK_ATTACHMENT_LOAD_OP_DONT_CARE; opa++)
|
||||
{
|
||||
for (u32 opb = VK_ATTACHMENT_LOAD_OP_LOAD; opb <= VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
opb++)
|
||||
for (u32 opb = VK_ATTACHMENT_LOAD_OP_LOAD; opb <= VK_ATTACHMENT_LOAD_OP_DONT_CARE; opb++)
|
||||
{
|
||||
const VkFormat rp_rt_format =
|
||||
(rt != 0) ? ((colclip != 0) ? colclip_rt_format : rt_format) : VK_FORMAT_UNDEFINED;
|
||||
const VkFormat rp_depth_format = (ds != 0) ? depth_format : VK_FORMAT_UNDEFINED;
|
||||
const VkAttachmentLoadOp opc = (!stencil || !m_features.stencil_buffer) ?
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE :
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
VK_ATTACHMENT_LOAD_OP_DONT_CARE :
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
GET(m_tfx_render_pass[rt][ds][colclip][stencil][fbl][dsp][opa][opb], rp_rt_format,
|
||||
rp_depth_format, (fbl != 0), (dsp != 0), static_cast<VkAttachmentLoadOp>(opa),
|
||||
static_cast<VkAttachmentLoadOp>(opb), static_cast<VkAttachmentLoadOp>(opc));
|
||||
@@ -3896,8 +3893,7 @@ bool GSDeviceVK::CompileConvertPipelines()
|
||||
gpb.SetNoBlendingState();
|
||||
gpb.SetVertexShader(vs);
|
||||
|
||||
for (ShaderConvert i = ShaderConvert::COPY; static_cast<int>(i) < static_cast<int>(ShaderConvert::Count);
|
||||
i = static_cast<ShaderConvert>(static_cast<int>(i) + 1))
|
||||
for (ShaderConvert i = ShaderConvert::COPY; i < ShaderConvert::Count; i = static_cast<ShaderConvert>(static_cast<int>(i) + 1))
|
||||
{
|
||||
const bool depth = HasDepthOutput(i);
|
||||
const int index = static_cast<int>(i);
|
||||
@@ -4108,8 +4104,7 @@ bool GSDeviceVK::CompilePresentPipelines()
|
||||
gpb.SetNoStencilState();
|
||||
gpb.SetRenderPass(m_swap_chain_render_pass, 0);
|
||||
|
||||
for (PresentShader i = PresentShader::COPY; static_cast<int>(i) < static_cast<int>(PresentShader::Count);
|
||||
i = static_cast<PresentShader>(static_cast<int>(i) + 1))
|
||||
for (PresentShader i = PresentShader::COPY; i < PresentShader::Count; i = static_cast<PresentShader>(static_cast<int>(i) + 1))
|
||||
{
|
||||
const int index = static_cast<int>(i);
|
||||
|
||||
@@ -5610,7 +5605,7 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
// If we have a colclip in progress, we need to use the colclip texture, but we can't check this later as there's a chicken/egg problem with the pipe setup.
|
||||
GSTexture* backup_rt = config.rt;
|
||||
|
||||
if(colclip_rt)
|
||||
if (colclip_rt)
|
||||
config.rt = colclip_rt;
|
||||
|
||||
date_image = SetupPrimitiveTrackingDATE(config);
|
||||
@@ -5838,8 +5833,9 @@ void GSDeviceVK::RenderHW(GSHWDrawConfig& config)
|
||||
|
||||
// Only draw to the active area of the colclip hw target. Except when depth is cleared, we need to use the full
|
||||
// buffer size, otherwise it'll only clear the draw part of the depth buffer.
|
||||
const GSVector4i render_area = (pipe.ps.colclip_hw && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve) && ds_op != VK_ATTACHMENT_LOAD_OP_CLEAR) ? config.drawarea :
|
||||
GSVector4i::loadh(rtsize);
|
||||
const GSVector4i render_area = (pipe.ps.colclip_hw && (config.colclip_mode == GSHWDrawConfig::ColClipMode::ConvertAndResolve) && ds_op != VK_ATTACHMENT_LOAD_OP_CLEAR)
|
||||
? config.drawarea
|
||||
: GSVector4i::loadh(rtsize);
|
||||
|
||||
if (is_clearing_rt)
|
||||
{
|
||||
@@ -6053,7 +6049,7 @@ VkImageMemoryBarrier GSDeviceVK::GetColorBufferBarrier(GSTextureVK* rt) const
|
||||
VkDependencyFlags GSDeviceVK::GetColorBufferBarrierFlags() const
|
||||
{
|
||||
return UseFeedbackLoopLayout() ? (VK_DEPENDENCY_BY_REGION_BIT | VK_DEPENDENCY_FEEDBACK_LOOP_BIT_EXT) :
|
||||
VK_DEPENDENCY_BY_REGION_BIT;
|
||||
VK_DEPENDENCY_BY_REGION_BIT;
|
||||
}
|
||||
|
||||
void GSDeviceVK::SendHWDraw(const GSHWDrawConfig& config, GSTextureVK* draw_rt,
|
||||
|
||||
@@ -640,10 +640,10 @@ private:
|
||||
DIRTY_FLAG_TFX_TEXTURE_PRIMID = (DIRTY_FLAG_TFX_TEXTURE_0 << 3),
|
||||
|
||||
DIRTY_FLAG_TFX_TEXTURES = DIRTY_FLAG_TFX_TEXTURE_TEX | DIRTY_FLAG_TFX_TEXTURE_PALETTE |
|
||||
DIRTY_FLAG_TFX_TEXTURE_RT | DIRTY_FLAG_TFX_TEXTURE_PRIMID,
|
||||
DIRTY_FLAG_TFX_TEXTURE_RT | DIRTY_FLAG_TFX_TEXTURE_PRIMID,
|
||||
|
||||
DIRTY_BASE_STATE = DIRTY_FLAG_INDEX_BUFFER | DIRTY_FLAG_PIPELINE | DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR |
|
||||
DIRTY_FLAG_BLEND_CONSTANTS | DIRTY_FLAG_LINE_WIDTH,
|
||||
DIRTY_FLAG_BLEND_CONSTANTS | DIRTY_FLAG_LINE_WIDTH,
|
||||
DIRTY_TFX_STATE = DIRTY_BASE_STATE | DIRTY_FLAG_TFX_TEXTURES,
|
||||
DIRTY_UTILITY_STATE = DIRTY_BASE_STATE | DIRTY_FLAG_UTILITY_TEXTURE,
|
||||
DIRTY_CONSTANT_BUFFER_STATE = DIRTY_FLAG_VS_CONSTANT_BUFFER | DIRTY_FLAG_PS_CONSTANT_BUFFER,
|
||||
|
||||
@@ -33,14 +33,14 @@ static VkImageLayout GetVkImageLayout(GSTextureVK::Layout layout)
|
||||
VK_IMAGE_LAYOUT_GENERAL, // General
|
||||
}};
|
||||
return (layout == GSTextureVK::Layout::FeedbackLoop && GSDeviceVK::GetInstance()->UseFeedbackLoopLayout()) ?
|
||||
VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
|
||||
s_vk_layout_mapping[static_cast<u32>(layout)];
|
||||
VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
|
||||
s_vk_layout_mapping[static_cast<u32>(layout)];
|
||||
}
|
||||
|
||||
static VkAccessFlagBits GetFeedbackLoopInputAccessBits()
|
||||
{
|
||||
return GSDeviceVK::GetInstance()->UseFeedbackLoopLayout() ? VK_ACCESS_SHADER_READ_BIT :
|
||||
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
||||
VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
|
||||
}
|
||||
|
||||
GSTextureVK::GSTextureVK(Type type, Format format, int width, int height, int levels, VkImage image,
|
||||
@@ -102,8 +102,8 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Create(Type type, Format format, int w
|
||||
ici.usage =
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
(GSDeviceVK::GetInstance()->UseFeedbackLoopLayout() ? VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT :
|
||||
VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
|
||||
(GSDeviceVK::GetInstance()->UseFeedbackLoopLayout() ? VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT
|
||||
: VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -113,8 +113,8 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Create(Type type, Format format, int w
|
||||
ici.usage =
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
|
||||
(GSDeviceVK::GetInstance()->UseFeedbackLoopLayout() ? VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT :
|
||||
0);
|
||||
(GSDeviceVK::GetInstance()->UseFeedbackLoopLayout() ? VK_IMAGE_USAGE_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT
|
||||
: 0);
|
||||
vci.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
}
|
||||
break;
|
||||
@@ -123,7 +123,7 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Create(Type type, Format format, int w
|
||||
{
|
||||
pxAssert(levels == 1);
|
||||
ici.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
VK_IMAGE_USAGE_SAMPLED_BIT;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -202,8 +202,7 @@ void GSTextureVK::Destroy(bool defer)
|
||||
{
|
||||
if (other_tex)
|
||||
{
|
||||
for (auto other_it = other_tex->m_framebuffers.begin(); other_it != other_tex->m_framebuffers.end();
|
||||
++other_it)
|
||||
for (auto other_it = other_tex->m_framebuffers.begin(); other_it != other_tex->m_framebuffers.end(); ++other_it)
|
||||
{
|
||||
if (std::get<0>(*other_it) == this)
|
||||
{
|
||||
@@ -566,7 +565,7 @@ void GSTextureVK::TransitionSubresourcesToLayout(
|
||||
if (m_type == Type::DepthStencil)
|
||||
{
|
||||
aspect = g_gs_device->Features().stencil_buffer ? (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT) :
|
||||
VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -638,15 +637,12 @@ void GSTextureVK::TransitionSubresourcesToLayout(
|
||||
break;
|
||||
|
||||
case Layout::FeedbackLoop:
|
||||
barrier.srcAccessMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?
|
||||
(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
GetFeedbackLoopInputAccessBits()) :
|
||||
(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT);
|
||||
srcStageMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?
|
||||
(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) :
|
||||
(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
barrier.srcAccessMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
? (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | GetFeedbackLoopInputAccessBits())
|
||||
: (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT);
|
||||
srcStageMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
? (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
|
||||
: (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
break;
|
||||
|
||||
case Layout::ReadWriteImage:
|
||||
@@ -714,15 +710,12 @@ void GSTextureVK::TransitionSubresourcesToLayout(
|
||||
break;
|
||||
|
||||
case Layout::FeedbackLoop:
|
||||
barrier.dstAccessMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?
|
||||
(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
|
||||
GetFeedbackLoopInputAccessBits()) :
|
||||
(VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT);
|
||||
dstStageMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT) ?
|
||||
(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) :
|
||||
(VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
barrier.dstAccessMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
? (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | GetFeedbackLoopInputAccessBits())
|
||||
: (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT);
|
||||
dstStageMask = (aspect == VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
? (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
|
||||
: (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
break;
|
||||
|
||||
case Layout::ReadWriteImage:
|
||||
@@ -946,4 +939,4 @@ void GSDownloadTextureVK::SetDebugName(std::string_view name)
|
||||
Vulkan::SetObjectName(GSDeviceVK::GetInstance()->GetDevice(), m_buffer, "%.*s", static_cast<int>(name.size()), name.data());
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -114,14 +114,14 @@ namespace Vulkan
|
||||
void AddBlendAttachment(bool blend_enable, VkBlendFactor src_factor, VkBlendFactor dst_factor, VkBlendOp op,
|
||||
VkBlendFactor alpha_src_factor, VkBlendFactor alpha_dst_factor, VkBlendOp alpha_op,
|
||||
VkColorComponentFlags write_mask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
|
||||
void SetBlendAttachment(u32 attachment, bool blend_enable, VkBlendFactor src_factor, VkBlendFactor dst_factor,
|
||||
VkBlendOp op, VkBlendFactor alpha_src_factor, VkBlendFactor alpha_dst_factor, VkBlendOp alpha_op,
|
||||
VkColorComponentFlags write_mask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
|
||||
void SetColorWriteMask(
|
||||
u32 attachment, VkColorComponentFlags write_mask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
|
||||
void AddBlendFlags(u32 flags);
|
||||
void ClearBlendAttachments();
|
||||
|
||||
@@ -407,4 +407,4 @@ namespace Vulkan
|
||||
va_end(ap);
|
||||
#endif
|
||||
}
|
||||
} // namespace Vulkan
|
||||
} // namespace Vulkan
|
||||
|
||||
@@ -603,7 +603,7 @@ struct Gif_Unit
|
||||
}
|
||||
if (curSize >= size)
|
||||
return size;
|
||||
if(((flush && gifTag.tag.EOP) || !flush) && (CHECK_XGKICKHACK || !EmuConfig.Cpu.Recompiler.EnableVU1))
|
||||
if(((flush && gifTag.tag.EOP) || !flush) && (CHECK_XGKICKHACK || !REC_VU1))
|
||||
{
|
||||
return curSize | ((u32)gifTag.tag.EOP << 31);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <bitset>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -66,10 +67,18 @@ namespace
|
||||
{
|
||||
SmallStackString<L>::format("{} {}", icon, Host::TranslateToStringView(TR_CONTEXT, str));
|
||||
}
|
||||
__fi IconStackString(const char8_t* icon, const char* str)
|
||||
{
|
||||
SmallStackString<L>::format("{} {}", reinterpret_cast<const char*>(icon), Host::TranslateToStringView(TR_CONTEXT, str));
|
||||
}
|
||||
__fi IconStackString(const char* icon, const char* str, const char* suffix)
|
||||
{
|
||||
SmallStackString<L>::format("{} {}##{}", icon, Host::TranslateToStringView(TR_CONTEXT, str), suffix);
|
||||
}
|
||||
__fi IconStackString(const char8_t* icon, const char* str, const char* suffix)
|
||||
{
|
||||
SmallStackString<L>::format("{} {}##{}", reinterpret_cast<const char*>(icon), Host::TranslateToStringView(TR_CONTEXT, str), suffix);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
@@ -367,12 +376,9 @@ namespace FullscreenUI
|
||||
static void DrawIntSpinBoxSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section, const char* key,
|
||||
int default_value, int min_value, int max_value, int step_value, const char* format = "%d", bool enabled = true,
|
||||
float height = ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT, std::pair<ImFont*, float> font = g_large_font, std::pair<ImFont*, float> summary_font = g_medium_font);
|
||||
#if 0
|
||||
// Unused as of now
|
||||
static void DrawFloatRangeSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section, const char* key,
|
||||
float default_value, float min_value, float max_value, const char* format = "%f", float multiplier = 1.0f, bool enabled = true,
|
||||
float height = ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT, std::pair<ImFont*, float> font = g_large_font, std::pair<ImFont*, float> summary_font = g_medium_font);
|
||||
#endif
|
||||
static void DrawFloatSpinBoxSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section,
|
||||
const char* key, float default_value, float min_value, float max_value, float step_value, float multiplier,
|
||||
const char* format = "%f", bool enabled = true, float height = ImGuiFullscreen::LAYOUT_MENU_BUTTON_HEIGHT,
|
||||
@@ -1435,7 +1441,17 @@ void FullscreenUI::DrawLandingTemplate(ImVec2* menu_pos, ImVec2* menu_size)
|
||||
// draw time
|
||||
ImVec2 time_pos;
|
||||
{
|
||||
heading_str.format(FSUI_FSTR("{:%H:%M}"), fmt::localtime(std::time(nullptr)));
|
||||
// Waiting on (apple)clang support for P0355R7
|
||||
// Migrate to std::chrono::current_zone and zoned_time then
|
||||
const auto utc_now = std::chrono::system_clock::now();
|
||||
const auto utc_time_t = std::chrono::system_clock::to_time_t(utc_now);
|
||||
std::tm tm_local = {};
|
||||
#ifdef _MSC_VER
|
||||
localtime_s(&tm_local, &utc_time_t);
|
||||
#else
|
||||
localtime_r(&utc_time_t, &tm_local);
|
||||
#endif
|
||||
heading_str.format(FSUI_FSTR("{:%H:%M}"), tm_local);
|
||||
|
||||
const ImVec2 time_size = heading_font.first->CalcTextSizeA(heading_font.second, FLT_MAX, 0.0f, "00:00");
|
||||
time_pos = ImVec2(heading_size.x - LayoutScale(LAYOUT_MENU_BUTTON_X_PADDING) - time_size.x,
|
||||
@@ -2217,8 +2233,6 @@ void FullscreenUI::DrawIntSpinBoxSetting(SettingsInterface* bsi, const char* tit
|
||||
ImGui::PopFont();
|
||||
}
|
||||
|
||||
#if 0
|
||||
// Unused as of now
|
||||
void FullscreenUI::DrawFloatRangeSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section,
|
||||
const char* key, float default_value, float min_value, float max_value, const char* format, float multiplier, bool enabled,
|
||||
float height, std::pair<ImFont*, float> font, std::pair<ImFont*, float> summary_font)
|
||||
@@ -2275,7 +2289,6 @@ void FullscreenUI::DrawFloatRangeSetting(SettingsInterface* bsi, const char* tit
|
||||
ImGui::PopStyleVar(4);
|
||||
ImGui::PopFont();
|
||||
}
|
||||
#endif
|
||||
|
||||
void FullscreenUI::DrawFloatSpinBoxSetting(SettingsInterface* bsi, const char* title, const char* summary, const char* section,
|
||||
const char* key, float default_value, float min_value, float max_value, float step_value, float multiplier, const char* format,
|
||||
@@ -3682,7 +3695,7 @@ void FullscreenUI::DrawInterfaceSettingsPage()
|
||||
s_osd_position_options, s_osd_position_values, std::size(s_osd_position_options), true);
|
||||
|
||||
MenuHeading(FSUI_CSTR("Operations"));
|
||||
if (MenuButton(FSUI_ICONSTR(ICON_FA_DUMPSTER_FIRE, "Reset Settings"),
|
||||
if (MenuButton(FSUI_ICONSTR(u8"🔥", "Reset Settings"),
|
||||
FSUI_CSTR("Resets configuration to defaults (excluding controller settings)."), !IsEditingGameSettings(bsi)))
|
||||
{
|
||||
DoResetSettings();
|
||||
@@ -4409,12 +4422,14 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
|
||||
{
|
||||
const bool shadeboost_active = GetEffectiveBoolSetting(bsi, "EmuCore/GS", "ShadeBoost", false);
|
||||
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_GEM, "Shade Boost"), FSUI_CSTR("Enables brightness/contrast/saturation adjustment."), "EmuCore/GS",
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_GEM, "Shade Boost"), FSUI_CSTR("Enables brightness/contrast/gamma/saturation adjustment."), "EmuCore/GS",
|
||||
"ShadeBoost", false);
|
||||
DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_SUN, "Shade Boost Brightness"), FSUI_CSTR("Adjusts brightness. 50 is normal."), "EmuCore/GS",
|
||||
"ShadeBoost_Brightness", 50, 1, 100, "%d", shadeboost_active);
|
||||
DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_LIGHTBULB, "Shade Boost Contrast"), FSUI_CSTR("Adjusts contrast. 50 is normal."), "EmuCore/GS",
|
||||
"ShadeBoost_Contrast", 50, 1, 100, "%d", shadeboost_active);
|
||||
DrawIntRangeSetting(bsi, FSUI_CSTR("Shade Boost Gamma"), FSUI_CSTR("Adjusts gamma. 50 is normal."), "EmuCore/GS",
|
||||
"ShadeBoost_Gamma", 50, 1, 100, "%d", shadeboost_active);
|
||||
DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_DROPLET, "Shade Boost Saturation"), FSUI_CSTR("Adjusts saturation. 50 is normal."), "EmuCore/GS",
|
||||
"ShadeBoost_Saturation", 50, 1, 100, "%d", shadeboost_active);
|
||||
|
||||
@@ -4479,6 +4494,10 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
|
||||
"Uploads full textures to the GPU on use, rather than only the utilized regions. Can improve performance in some games."),
|
||||
"EmuCore/GS", "texture_preloading", static_cast<int>(TexturePreloadingLevel::Off), s_preloading_options,
|
||||
std::size(s_preloading_options), true);
|
||||
DrawFloatRangeSetting(bsi, FSUI_CSTR("NTSC Frame Rate"), FSUI_CSTR("Determines what frame rate NTSC games run at."),
|
||||
"EmuCore/GS", "FrameRateNTSC", 59.94f, 10.0f, 300.0f, "%.2f Hz");
|
||||
DrawFloatRangeSetting(bsi, FSUI_CSTR("PAL Frame Rate"), FSUI_CSTR("Determines what frame rate PAL games run at."),
|
||||
"EmuCore/GS", "FrameRatePAL", 50.0f, 10.0f, 300.0f, "%.2f Hz");
|
||||
}
|
||||
|
||||
EndMenuButtons();
|
||||
@@ -4866,7 +4885,7 @@ void FullscreenUI::DoSaveInputProfile()
|
||||
|
||||
void FullscreenUI::DoResetSettings()
|
||||
{
|
||||
OpenConfirmMessageDialog(FSUI_ICONSTR(ICON_FA_DUMPSTER_FIRE, "Reset Settings"),
|
||||
OpenConfirmMessageDialog(FSUI_ICONSTR(u8"🔥", "Reset Settings"),
|
||||
FSUI_STR("Are you sure you want to restore the default settings? Any preferences will be lost."), [](bool result) {
|
||||
if (result)
|
||||
{
|
||||
@@ -4894,7 +4913,7 @@ void FullscreenUI::DrawControllerSettingsPage()
|
||||
DoSaveInputProfile();
|
||||
}
|
||||
|
||||
if (MenuButton(FSUI_ICONSTR(ICON_FA_DUMPSTER_FIRE, "Reset Settings"),
|
||||
if (MenuButton(FSUI_ICONSTR(u8"🔥", "Reset Settings"),
|
||||
FSUI_CSTR("Resets all configuration to defaults (including bindings).")))
|
||||
{
|
||||
ResetControllerSettings();
|
||||
@@ -8172,9 +8191,11 @@ TRANSLATE_NOOP("FullscreenUI", "Enables FXAA post-processing shader.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enables FidelityFX Contrast Adaptive Sharpening.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Determines the intensity the sharpening effect in CAS post-processing.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Filters");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enables brightness/contrast/saturation adjustment.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Enables brightness/contrast/gamma/saturation adjustment.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Adjusts brightness. 50 is normal.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Adjusts contrast. 50 is normal.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Shade Boost Gamma");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Adjusts gamma. 50 is normal.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Adjusts saturation. 50 is normal.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Applies a shader which replicates the visual effects of different styles of television set.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Advanced");
|
||||
@@ -8200,6 +8221,10 @@ TRANSLATE_NOOP("FullscreenUI", "Disable Vertex Shader Expand");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Falls back to the CPU for expanding sprites/lines.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Texture Preloading");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Uploads full textures to the GPU on use, rather than only the utilized regions. Can improve performance in some games.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "NTSC Frame Rate");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Determines what frame rate NTSC games run at.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "PAL Frame Rate");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Determines what frame rate PAL games run at.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Audio Control");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Controls the volume of the audio played on the host.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Controls the volume of the audio played on the host when fast forwarding.");
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "fmt/format.h"
|
||||
#include "imgui.h"
|
||||
#include "imgui_freetype.h"
|
||||
#include "imgui_internal.h"
|
||||
#include "common/Image.h"
|
||||
|
||||
@@ -56,6 +57,7 @@ namespace ImGuiManager
|
||||
static ImFont* AddTextFont();
|
||||
static ImFont* AddFixedFont();
|
||||
static bool AddIconFonts();
|
||||
static bool AddEmojiFont();
|
||||
static void AcquirePendingOSDMessages(Common::Timer::Value current_time);
|
||||
static void DrawOSDMessages(Common::Timer::Value current_time);
|
||||
static void CreateSoftwareCursorTextures();
|
||||
@@ -74,6 +76,7 @@ static ImFont* s_fixed_font;
|
||||
|
||||
static std::vector<u8> s_standard_font_data;
|
||||
static std::vector<u8> s_fixed_font_data;
|
||||
static std::vector<u8> s_emoji_font_data;
|
||||
static std::vector<u8> s_icon_fa_font_data;
|
||||
static std::vector<u8> s_icon_pf_font_data;
|
||||
|
||||
@@ -415,6 +418,16 @@ bool ImGuiManager::LoadFontData()
|
||||
s_fixed_font_data = std::move(font_data.value());
|
||||
}
|
||||
|
||||
if (s_emoji_font_data.empty())
|
||||
{
|
||||
std::optional<std::vector<u8>> font_data = FileSystem::ReadBinaryFile(
|
||||
EmuFolders::GetOverridableResourcePath("fonts" FS_OSPATH_SEPARATOR_STR "NotoColorEmoji-Regular.ttf").c_str());
|
||||
if (!font_data.has_value())
|
||||
return false;
|
||||
|
||||
s_emoji_font_data = std::move(font_data.value());
|
||||
}
|
||||
|
||||
if (s_icon_fa_font_data.empty())
|
||||
{
|
||||
std::optional<std::vector<u8>> font_data =
|
||||
@@ -442,6 +455,7 @@ void ImGuiManager::UnloadFontData()
|
||||
{
|
||||
std::vector<u8>().swap(s_standard_font_data);
|
||||
std::vector<u8>().swap(s_fixed_font_data);
|
||||
std::vector<u8>().swap(s_emoji_font_data);
|
||||
std::vector<u8>().swap(s_icon_fa_font_data);
|
||||
std::vector<u8>().swap(s_icon_pf_font_data);
|
||||
}
|
||||
@@ -475,11 +489,15 @@ bool ImGuiManager::AddIconFonts()
|
||||
{
|
||||
// Load FontAwesome after to avoid aliased codepoints overriding promptfont
|
||||
{
|
||||
// Exclude emojis
|
||||
static constexpr ImWchar range_exclude_emojis[] = {0x10000, 0x1ffff, 0x0, 0x0};
|
||||
|
||||
ImFontConfig cfg;
|
||||
cfg.MergeMode = true;
|
||||
cfg.PixelSnapH = true;
|
||||
cfg.GlyphMinAdvanceX = FONT_BASE_SIZE;
|
||||
cfg.GlyphMaxAdvanceX = FONT_BASE_SIZE;
|
||||
cfg.GlyphExcludeRanges = range_exclude_emojis;
|
||||
cfg.FontDataOwnedByAtlas = false;
|
||||
|
||||
if (!ImGui::GetIO().Fonts->AddFontFromMemoryTTF(
|
||||
@@ -491,7 +509,7 @@ bool ImGuiManager::AddIconFonts()
|
||||
|
||||
{
|
||||
// Exclude any characters outside the BMP PUA plane
|
||||
static constexpr ImWchar range_exclude_non_bmp[] = {0x1, 0xdfff, 0xf900, 0xffff, 0x0, 0x0};
|
||||
static constexpr ImWchar range_exclude_non_bmp[] = {0x1, 0xdfff, 0xf900, 0x10ffff, 0x0, 0x0};
|
||||
|
||||
ImFontConfig cfg;
|
||||
cfg.MergeMode = true;
|
||||
@@ -511,17 +529,75 @@ bool ImGuiManager::AddIconFonts()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGuiManager::AddEmojiFont()
|
||||
{
|
||||
{
|
||||
// ImGui can't correctly handle some Unicode codepoints
|
||||
// Remove them to avoid rendering blank/fallback characters
|
||||
// See https://github.com/ocornut/imgui/issues/8240
|
||||
static ImFontLoader filter_loader;
|
||||
filter_loader.Name = "Emoji Preprocessor";
|
||||
filter_loader.FontSrcContainsGlyph = [](ImFontAtlas* atlas, ImFontConfig* src, ImWchar codepoint) {
|
||||
if (codepoint == 0xfe0e || codepoint == 0xfe0f)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
filter_loader.FontBakedLoadGlyph = [](ImFontAtlas* atlas, ImFontConfig* src, ImFontBaked* baked, void*, ImWchar codepoint, ImFontGlyph* out_glyph, float* out_advance_x) {
|
||||
if (codepoint != 0xfe0e && codepoint != 0xfe0f)
|
||||
return false;
|
||||
|
||||
// Metrics only mode
|
||||
if (out_advance_x != nullptr)
|
||||
{
|
||||
*out_advance_x = 0.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
out_glyph->Codepoint = codepoint;
|
||||
out_glyph->AdvanceX = 0.0f;
|
||||
out_glyph->Visible = false;
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
ImFontConfig cfg;
|
||||
StringUtil::Strlcpy(cfg.Name, filter_loader.Name, sizeof(cfg.Name));
|
||||
cfg.MergeMode = true;
|
||||
cfg.SizePixels = FONT_BASE_SIZE;
|
||||
cfg.FontLoader = &filter_loader;
|
||||
if (!ImGui::GetIO().Fonts->AddFont(&cfg))
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
ImFontConfig cfg;
|
||||
cfg.MergeMode = true;
|
||||
// Set GlyphMin/MaxAdvanceX to allow replacing FA/PF icons.
|
||||
cfg.GlyphMinAdvanceX = FONT_BASE_SIZE;
|
||||
cfg.GlyphMaxAdvanceX = FONT_BASE_SIZE;
|
||||
cfg.FontLoaderFlags |= ImGuiFreeTypeLoaderFlags_LoadColor;
|
||||
cfg.FontDataOwnedByAtlas = false;
|
||||
|
||||
if (!ImGui::GetIO().Fonts->AddFontFromMemoryTTF(
|
||||
s_emoji_font_data.data(), static_cast<int>(s_emoji_font_data.size()), FONT_BASE_SIZE, &cfg, nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImGuiManager::AddImGuiFonts()
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.Fonts->Clear();
|
||||
|
||||
s_standard_font = AddTextFont();
|
||||
if (!s_standard_font || !AddIconFonts())
|
||||
if (!s_standard_font || !AddIconFonts() || !AddEmojiFont())
|
||||
return false;
|
||||
|
||||
s_fixed_font = AddFixedFont();
|
||||
if (!s_fixed_font)
|
||||
if (!s_fixed_font || !AddEmojiFont())
|
||||
return false;
|
||||
|
||||
ImGuiFullscreen::SetFont(s_standard_font);
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "SIO/Pad/PadBase.h"
|
||||
#include "USB/USB.h"
|
||||
#include "VMManager.h"
|
||||
#include "cpuinfo.h"
|
||||
|
||||
#include "common/BitUtils.h"
|
||||
#include "common/FileSystem.h"
|
||||
@@ -307,10 +306,16 @@ __ri void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, f
|
||||
{
|
||||
// CPU
|
||||
text.clear();
|
||||
text.append_format("CPU: {} ({}C/{}T)",
|
||||
cpuinfo_get_package(0)->name,
|
||||
cpuinfo_get_cores_count(),
|
||||
cpuinfo_get_processors_count());
|
||||
const CPUInfo& info = GetCPUInfo();
|
||||
bool has_small = info.num_small_cores > 0;
|
||||
bool has_ht = info.num_threads != info.num_big_cores + info.num_small_cores;
|
||||
text.append_format("CPU: {}", info.name);
|
||||
if (has_ht & has_small)
|
||||
text.append_format(" ({}P/{}E/{}T)", info.num_big_cores, info.num_small_cores, info.num_threads);
|
||||
else if (has_small)
|
||||
text.append_format(" ({}P/{}E)", info.num_big_cores, info.num_small_cores);
|
||||
else
|
||||
text.append_format(" ({}C/{}T)", info.num_big_cores, info.num_threads);
|
||||
DRAW_LINE(fixed_font, font_size, text.c_str(), IM_COL32(255, 255, 255, 255));
|
||||
|
||||
// GPU
|
||||
@@ -1069,7 +1074,14 @@ void SaveStateSelectorUI::InitializeListEntry(const std::string& serial, u32 crc
|
||||
}
|
||||
|
||||
li->title = fmt::format(TRANSLATE_FS("ImGuiOverlays", "Save Slot {0}"), slot);
|
||||
li->summary = fmt::format(TRANSLATE_FS("ImGuiOverlays", DATE_TIME_FORMAT), fmt::localtime(sd.ModificationTime));
|
||||
|
||||
std::tm tm_local = {};
|
||||
#ifdef _MSC_VER
|
||||
localtime_s(&tm_local, &sd.ModificationTime);
|
||||
#else
|
||||
localtime_r(&sd.ModificationTime, &tm_local);
|
||||
#endif
|
||||
li->summary = fmt::format(TRANSLATE_FS("ImGuiOverlays", DATE_TIME_FORMAT), tm_local);
|
||||
li->filename = Path::GetFileName(path);
|
||||
|
||||
u32 screenshot_width, screenshot_height;
|
||||
@@ -1268,8 +1280,15 @@ void SaveStateSelectorUI::ShowSlotOSDMessage()
|
||||
const std::string filename = VMManager::GetSaveStateFileName(serial.c_str(), crc, slot);
|
||||
FILESYSTEM_STAT_DATA sd;
|
||||
std::string date;
|
||||
|
||||
std::tm tm_local = {};
|
||||
#ifdef _MSC_VER
|
||||
localtime_s(&tm_local, &sd.ModificationTime);
|
||||
#else
|
||||
localtime_r(&sd.ModificationTime, &tm_local);
|
||||
#endif
|
||||
if (!filename.empty() && FileSystem::StatFile(filename.c_str(), &sd))
|
||||
date = fmt::format(TRANSLATE_FS("ImGuiOverlays", DATE_TIME_FORMAT), fmt::localtime(sd.ModificationTime));
|
||||
date = fmt::format(TRANSLATE_FS("ImGuiOverlays", DATE_TIME_FORMAT), tm_local);
|
||||
else
|
||||
date = TRANSLATE_STR("ImGuiOverlays", "no save yet");
|
||||
|
||||
|
||||
@@ -951,11 +951,11 @@ namespace R3000A
|
||||
char tmp[max_len], tmp2[max_len];
|
||||
char* ptmp = tmp;
|
||||
unsigned int printed_bytes = 0;
|
||||
int remaining_buf = max_len - 1;
|
||||
unsigned int n = 1, i = 0, j = 0;
|
||||
|
||||
while (fmt[i])
|
||||
while (fmt[i] && ptmp < std::end(tmp) - 1)
|
||||
{
|
||||
const int remaining_buf = static_cast<int>(std::end(tmp) - 1 - ptmp);
|
||||
switch (fmt[i])
|
||||
{
|
||||
case '%':
|
||||
@@ -996,7 +996,6 @@ namespace R3000A
|
||||
case 'f':
|
||||
case 'F':
|
||||
printed_bytes = std::min(remaining_buf, snprintf(ptmp, remaining_buf, tmp2, (float)iopMemRead32(sp + n * 4)));
|
||||
remaining_buf -= printed_bytes;
|
||||
ptmp += printed_bytes;
|
||||
n++;
|
||||
break;
|
||||
@@ -1008,7 +1007,6 @@ namespace R3000A
|
||||
case 'g':
|
||||
case 'G':
|
||||
printed_bytes = std::min(remaining_buf, snprintf(ptmp, remaining_buf, tmp2, (double)iopMemRead32(sp + n * 4)));
|
||||
remaining_buf -= printed_bytes;
|
||||
ptmp += printed_bytes;
|
||||
n++;
|
||||
break;
|
||||
@@ -1024,14 +1022,12 @@ namespace R3000A
|
||||
case 'u':
|
||||
case 'U':
|
||||
printed_bytes = std::min(remaining_buf, snprintf(ptmp, remaining_buf, tmp2, (u32)iopMemRead32(sp + n * 4)));
|
||||
remaining_buf -= printed_bytes;
|
||||
ptmp += printed_bytes;
|
||||
n++;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printed_bytes = std::min(remaining_buf, snprintf(ptmp, remaining_buf, tmp2, (u8)iopMemRead32(sp + n * 4)));
|
||||
remaining_buf -= printed_bytes;
|
||||
ptmp += printed_bytes;
|
||||
n++;
|
||||
break;
|
||||
@@ -1040,7 +1036,6 @@ namespace R3000A
|
||||
{
|
||||
std::string s = iopMemReadString(iopMemRead32(sp + n * 4));
|
||||
printed_bytes = std::min(remaining_buf, snprintf(ptmp, remaining_buf, tmp2, s.data()));
|
||||
remaining_buf -= printed_bytes;
|
||||
ptmp += printed_bytes;
|
||||
n++;
|
||||
}
|
||||
@@ -1061,6 +1056,7 @@ namespace R3000A
|
||||
break;
|
||||
}
|
||||
}
|
||||
pxAssertRel(ptmp >= tmp && ptmp < std::end(tmp), "Overflowed tmp buffer");
|
||||
*ptmp = 0;
|
||||
iopConLog(ShiftJIS_ConvertString(tmp, 1023));
|
||||
|
||||
|
||||
@@ -850,6 +850,7 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
|
||||
OpEqu(ShadeBoost_Brightness) &&
|
||||
OpEqu(ShadeBoost_Contrast) &&
|
||||
OpEqu(ShadeBoost_Saturation) &&
|
||||
OpEqu(ShadeBoost_Gamma) &&
|
||||
OpEqu(PNGCompressionLevel) &&
|
||||
OpEqu(SaveDrawStart) &&
|
||||
OpEqu(SaveDrawCount) &&
|
||||
@@ -920,6 +921,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||
SettingsWrapIntEnumEx(ScreenshotSize, "ScreenshotSize");
|
||||
SettingsWrapIntEnumEx(ScreenshotFormat, "ScreenshotFormat");
|
||||
SettingsWrapEntry(ScreenshotQuality);
|
||||
SettingsWrapBitBool(OrganizeScreenshotsByGame);
|
||||
SettingsWrapEntry(StretchY);
|
||||
SettingsWrapEntryEx(Crop[0], "CropLeft");
|
||||
SettingsWrapEntryEx(Crop[1], "CropTop");
|
||||
@@ -1041,6 +1043,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||
SettingsWrapBitfield(ShadeBoost_Brightness);
|
||||
SettingsWrapBitfield(ShadeBoost_Contrast);
|
||||
SettingsWrapBitfield(ShadeBoost_Saturation);
|
||||
SettingsWrapBitfield(ShadeBoost_Gamma);
|
||||
SettingsWrapBitfield(ExclusiveFullscreenControl);
|
||||
SettingsWrapBitfieldEx(PNGCompressionLevel, "png_compression_level");
|
||||
SettingsWrapBitfieldEx(SaveDrawStart, "SaveDrawStart");
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
||||
/// shaders change, to invalidate the cache.
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 69;
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 70;
|
||||
|
||||
@@ -2516,10 +2516,11 @@ void VMManager::LogCPUCapabilities()
|
||||
GetPhysicalMemory() / _1mb,
|
||||
static_cast<double>(GetPhysicalMemory()) / static_cast<double>(_1gb));
|
||||
|
||||
Console.WriteLnFmt(" Processor = {}", cpuinfo_get_package(0)->name);
|
||||
Console.WriteLnFmt(" Core Count = {} cores", cpuinfo_get_cores_count());
|
||||
Console.WriteLnFmt(" Thread Count = {} threads", cpuinfo_get_processors_count());
|
||||
Console.WriteLnFmt(" Cluster Count = {} clusters", cpuinfo_get_clusters_count());
|
||||
const CPUInfo& cpuinfo = GetCPUInfo();
|
||||
Console.WriteLnFmt(" Processor = {}", cpuinfo.name);
|
||||
Console.WriteLnFmt(" Core Count = {} cores", cpuinfo.num_big_cores + cpuinfo.num_small_cores);
|
||||
Console.WriteLnFmt(" Thread Count = {} threads", cpuinfo.num_threads);
|
||||
Console.WriteLnFmt(" Cluster Count = {} clusters", cpuinfo.num_clusters);
|
||||
#ifdef _WIN32
|
||||
LogUserPowerPlan();
|
||||
#endif
|
||||
|
||||
@@ -25,31 +25,50 @@ for token in ["FSUI_STR", "FSUI_CSTR", "FSUI_FSTR", "FSUI_NSTR", "FSUI_VSTR", "F
|
||||
|
||||
if full_source[last_pos + token_len] == '(':
|
||||
start_pos = last_pos + token_len + 1
|
||||
end_pos = full_source.find("\")", start_pos)
|
||||
s = full_source[start_pos:end_pos+1]
|
||||
end_pos = full_source.find(")", start_pos)
|
||||
s = full_source[start_pos:end_pos]
|
||||
|
||||
# remove "
|
||||
# Split into sting arguments, removing "
|
||||
string_args = [""]
|
||||
arg = 0;
|
||||
cpos = s.find(',')
|
||||
pos = s.find('"')
|
||||
new_s = ""
|
||||
while pos >= 0:
|
||||
if pos == 0 or s[pos - 1] != '\\':
|
||||
while pos >= 0 or cpos >= 0:
|
||||
assert pos == 0 or s[pos - 1] != '\\'
|
||||
if cpos == -1 or pos < cpos:
|
||||
epos = pos
|
||||
while True:
|
||||
epos = s.find('"', epos + 1)
|
||||
assert epos > pos
|
||||
# found ')' in string, extend s to next ')'
|
||||
if epos == -1:
|
||||
end_pos = full_source.find(")", end_pos + 1)
|
||||
s = full_source[start_pos:end_pos]
|
||||
epos = pos
|
||||
continue
|
||||
|
||||
if s[epos - 1] == '\\':
|
||||
continue
|
||||
else:
|
||||
break
|
||||
|
||||
assert epos > pos
|
||||
new_s += s[pos+1:epos]
|
||||
string_args[arg] += s[pos+1:epos]
|
||||
cpos = s.find(',', epos + 1)
|
||||
pos = s.find('"', epos + 1)
|
||||
if cpos >= 0 and pos >= 0 and cpos < pos:
|
||||
break
|
||||
else:
|
||||
pos = s.find('"', pos + 1)
|
||||
arg += 1
|
||||
string_args.append("")
|
||||
cpos = s.find(',', cpos + 1)
|
||||
|
||||
print(string_args)
|
||||
|
||||
# FSUI_ICONSTR and FSUI_ICONSTR_S need to translate the only the second argument
|
||||
# other defines take only a single argument
|
||||
if len(string_args) >= 2:
|
||||
new_s = string_args[1]
|
||||
else:
|
||||
new_s = string_args[0]
|
||||
|
||||
assert len(new_s) > 0
|
||||
|
||||
#assert (end_pos - start_pos) < 300
|
||||
|
||||
Reference in New Issue
Block a user