Compare commits

...

77 Commits

Author SHA1 Message Date
TheLastRar
e987eac545 CI/Appimage: Simplify how we bundle Wayland plugins 2025-06-29 16:44:07 -04:00
Florin9doi
6b9781fee6 USB: Throttle the Buzz data packets 2025-06-29 16:43:37 -04:00
TJnotJT
181ceb38cc GS: Put psm_str in the GSUtil struct. 2025-06-29 16:43:09 -04:00
chaoticgd
595ce0ea19 Qt: Add security warning to setup wizard 2025-06-29 16:41:56 -04:00
TheLastRar
b624330155 Deps: Update Pluto(S)VG
PlutoVG is updated to v1.1.0
PlutoSVG is updated to v0.0.7
2025-06-29 16:41:19 -04:00
JordanTheToaster
380c316869 Deps: Update SDL3 3.2.16 2025-06-29 16:40:27 -04:00
Florin9doi
31dacc2d21 Update Negcon to support Wipeout Fusion 2025-06-29 16:40:17 -04:00
Ty
b557a82009 [ci skip] 2.5.x Development Cycle 2025-06-29 16:34:51 -04:00
Ty
e4af1c4244 [ci-skip] 2.4 Release 2025-06-29 15:47:12 -04:00
JordanTheToaster
7c26ac5578 GameDB: Various fixes 2025-06-29 21:07:07 +02:00
JordanTheToaster
2948d50b0d GameDB: Shadow Hearts fixes 2025-06-29 10:32:13 +02:00
lightningterror
48fefddcb2 GS/HW: Fix -Wunused-variable warnings. 2025-06-29 10:17:57 +02:00
lightningterror
f4d8af2f0d GS/GL: Don't re enable blend after SetupDATE.
Redundant calls, blending will be enabled if needed.
2025-06-29 10:17:57 +02:00
lightningterror
afa3108623 GS/DX11: Adjust blend/depth stencil state.
OMSetDepthStencilState:
If state is nullptr, new state is also nullptr but stencil ref changes no need to set a new OMSetDepthStencilState.

OMSetBlendState:
If state is nullptr, new state is also nullptr but blend factor changes no need to set a new OMSetBlendState.
2025-06-29 10:17:57 +02:00
lightningterror
6fcfddf19a GS/GL/DX11: Resolve potential rtv/srv conflict for primid date.
primid_texture texture was already bound to rtv, so we either need to unbind it first from rtv, or we can bind it to srv after rtv bind has been changed.

Note: DX11 is fine since gpu state will be updated when DrawIndexedPrimitive is executed but it's nice to keep code parity and visual a visual state
what the pipeline order should do.
2025-06-29 10:17:57 +02:00
lightningterror
6d2f442cbd GS/DX11: Backports the avoid framebuffer optimization from GL.
Unlike OpenGL, we don't need to worry about adding extra barriers here
since we already do fb copies so rt tex won't be bound as an rtv and srv
at the same time, we also check for conflicts beforehand.
2025-06-29 10:17:57 +02:00
PCSX2 Bot
e8260e7191 [ci skip] Qt: Update Base Translation. 2025-06-28 20:04:49 -04:00
Ty
48a4367a2c New translations pcsx2-qt_en.ts (Spanish, Latin America)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
edd3540f34 New translations pcsx2-qt_en.ts (Guarani)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
111c32c5ed New translations pcsx2-qt_en.ts (Quechua)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
af22ca3ae0 New translations pcsx2-qt_en.ts (Hindi)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
5e2caa326c New translations pcsx2-qt_en.ts (Latvian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
50f9f60341 New translations pcsx2-qt_en.ts (Croatian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
65f61b143a New translations pcsx2-qt_en.ts (Persian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
10f4892b7e New translations pcsx2-qt_en.ts (Indonesian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
f71d518f75 New translations pcsx2-qt_en.ts (Portuguese, Brazilian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
c5b11fe484 New translations pcsx2-qt_en.ts (Vietnamese)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
068fd04f15 New translations pcsx2-qt_en.ts (Chinese Traditional)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
a461750b55 New translations pcsx2-qt_en.ts (Chinese Simplified)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
291df6a0e4 New translations pcsx2-qt_en.ts (Ukrainian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
8afeb4ea61 New translations pcsx2-qt_en.ts (Turkish)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
b30f246900 New translations pcsx2-qt_en.ts (Swedish)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
7fd042b197 New translations pcsx2-qt_en.ts (Serbian (Cyrillic))
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
b6b3e364f2 New translations pcsx2-qt_en.ts (Russian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
70e5f18971 New translations pcsx2-qt_en.ts (Portuguese)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
1fb35593d5 New translations pcsx2-qt_en.ts (Polish)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
b1b9c32644 New translations pcsx2-qt_en.ts (Norwegian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
8eeed7d42c New translations pcsx2-qt_en.ts (Dutch)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
584493d945 New translations pcsx2-qt_en.ts (Lithuanian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
da8e551e77 New translations pcsx2-qt_en.ts (Korean)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
a717930d5a New translations pcsx2-qt_en.ts (Georgian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
abc000f614 New translations pcsx2-qt_en.ts (Japanese)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
cd51f1def3 New translations pcsx2-qt_en.ts (Italian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
f5573cf0ab New translations pcsx2-qt_en.ts (Hungarian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
1d036a4897 New translations pcsx2-qt_en.ts (Hebrew)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
f9eced6244 New translations pcsx2-qt_en.ts (Finnish)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
90a7253c66 New translations pcsx2-qt_en.ts (Greek)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
31e065f83a New translations pcsx2-qt_en.ts (German)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
571f443339 New translations pcsx2-qt_en.ts (Danish)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
4a4157919c New translations pcsx2-qt_en.ts (Czech)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
e73aa0e81b New translations pcsx2-qt_en.ts (Catalan)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
2343246315 New translations pcsx2-qt_en.ts (Bulgarian)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
e5f41ce175 New translations pcsx2-qt_en.ts (Arabic)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
8184f2eaa9 New translations pcsx2-qt_en.ts (Afrikaans)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
e0bb465945 New translations pcsx2-qt_en.ts (Spanish)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
55749a63eb New translations pcsx2-qt_en.ts (French)
[ci skip]
2025-06-28 13:31:32 -04:00
Ty
aa1b8db3ea New translations pcsx2-qt_en.ts (Romanian)
[ci skip]
2025-06-28 13:31:32 -04:00
JordanTheToaster
023713fd67 GameDB: The Mummy fixes 2025-06-28 13:05:00 -04:00
refractionpcsx2
35093c3e37 GS/HW: Avoid single pixel overlap on lookups + improve buffer splitting 2025-06-27 18:04:29 +02:00
refractionpcsx2
4e5dac3e25 GameDB: Add fixes for MLB 11 and Toro to Kyuujitsu 2025-06-27 18:03:48 +02:00
refractionpcsx2
c52e84ac41 GS/HW: Add ability to detect 16bit clears with 32bit draw 2025-06-27 18:03:48 +02:00
refractionpcsx2
7f8488771d GS/TC: Improve heuristics for sequenced draws inside targets 2025-06-27 18:03:48 +02:00
refractionpcsx2
57ff271f4b GS/HW: Fix up offset Z behaviours and copy ranges 2025-06-27 18:03:48 +02:00
refractionpcsx2
43703755f8 GS/HW: Improve double half clear detection heuristics 2025-06-27 18:03:48 +02:00
refractionpcsx2
17b6cc00ab GS/HW: When expanding a target for display, expand valid area 2025-06-27 18:03:19 +02:00
JordanTheToaster
a03563b366 GameDB: The Golden Compass fixes 2025-06-26 13:44:29 +02:00
lightningterror
ff9da17498 GS/DX11: Allow to pick whenever to update sr or ss, and some reordering.
No need to call sampler update when updating conflicting srvs.
2025-06-26 13:43:51 +02:00
lightningterror
722bc94270 GS/DX11: Cache shader resource and sampler.
Might help speed things up, requires srv and rtv conflicts to be resolved.
2025-06-26 13:43:51 +02:00
lightningterror
d51a5db5b1 GS/GL: Add missing texture barrier count. 2025-06-26 09:20:54 +02:00
PCSX2 Bot
04541ae2ab [ci skip] Qt: Update Base Translation. 2025-06-25 07:15:25 +02:00
JordanTheToaster
c58a67815b GameDB: Stuart Little 3 loading screen fix 2025-06-25 00:03:28 +02:00
JordanTheToaster
085f964cd9 CI/Linux: Link ffmpeg for the appimage 2025-06-24 06:18:38 +02:00
Mrlinkwii
a8b6e448eb GameDB: remove reference to old GSC 2025-06-24 06:13:14 +02:00
PCSX2 Bot
78ab8381d9 [ci skip] PAD: Update to latest controller database. 2025-06-24 06:12:26 +02:00
PCSX2 Bot
49a5d82086 [ci skip] Qt: Update Base Translation. 2025-06-24 06:12:04 +02:00
TheLastRar
4ed129ccac FSUI: Improve layout scaling in games list selected preview 2025-06-24 06:11:49 +02:00
lightningterror
ed09dca17e GS/DX11: Also check DrawMultiStretchRects copy for srv conflicts with rtv.
Also adjust the naming.
2025-06-23 15:09:03 +02:00
73 changed files with 174685 additions and 133398 deletions

View File

@@ -144,6 +144,7 @@ jobs:
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DENABLE_SETCAP=OFF \
-DDISABLE_ADVANCE_SIMD=TRUE \
-DUSE_LINKED_FFMPEG=ON \
-DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON \
$ADDITIONAL_CMAKE_ARGS

View File

@@ -45,16 +45,6 @@ declare -a MANUAL_LIBS=(
"libshaderc_shared.so.1"
)
declare -a MANUAL_QT_LIBS=(
"libQt6WaylandEglClientHwIntegration.so.6"
)
declare -a MANUAL_QT_PLUGINS=(
"wayland-decoration-client"
"wayland-graphics-integration-client"
"wayland-shell-integration"
)
declare -a REMOVE_LIBS=(
'libwayland-client.so*'
'libwayland-cursor.so*'
@@ -66,7 +56,6 @@ set -e
LINUXDEPLOY=./linuxdeploy-x86_64.AppImage
LINUXDEPLOY_PLUGIN_QT=./linuxdeploy-plugin-qt-x86_64.AppImage
APPIMAGETOOL=./appimagetool-x86_64.AppImage
PATCHELF=patchelf
if [ ! -f "$LINUXDEPLOY" ]; then
"$PCSX2DIR/tools/retry.sh" wget -O "$LINUXDEPLOY" https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
@@ -125,7 +114,10 @@ cp "$PCSX2DIR/.github/workflows/scripts/linux/pcsx2-qt.desktop" "net.pcsx2.PCSX2
cp "$PCSX2DIR/bin/resources/icons/AppIconLarge.png" "PCSX2.png"
echo "Running linuxdeploy to create AppDir..."
EXTRA_QT_PLUGINS="core;gui;svg;waylandclient;widgets;xcbqpa" \
# The wayland platform plugin requires the plugins deployed for the waylandcompositor module
# Interestingly, specifying the module doesn't copy the module, only the required plugins for it
# https://github.com/linuxdeploy/linuxdeploy-plugin-qt/issues/160#issuecomment-2655543893
EXTRA_QT_MODULES="core;gui;svg;waylandclient;waylandcompositor;widgets;xcbqpa" \
EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so" \
DEPLOY_PLATFORM_THEMES="1" \
QMAKE="$DEPSDIR/bin/qmake" \
@@ -136,34 +128,6 @@ $LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/pcsx2-qt
echo "Copying resources into AppDir..."
cp -a "$BUILDDIR/bin/resources" "$OUTDIR/usr/bin"
# LinuxDeploy's Qt plugin doesn't include Wayland support. So manually copy in the additional Wayland libraries.
echo "Copying Qt Wayland libraries..."
for lib in "${MANUAL_QT_LIBS[@]}"; do
srcpath="$DEPSDIR/lib/$lib"
dstpath="$OUTDIR/usr/lib/$lib"
echo " $srcpath -> $dstpath"
cp "$srcpath" "$dstpath"
$PATCHELF --set-rpath '$ORIGIN' "$dstpath"
done
# .. and plugins.
echo "Copying Qt Wayland plugins..."
for GROUP in "${MANUAL_QT_PLUGINS[@]}"; do
srcpath="$DEPSDIR/plugins/$GROUP"
dstpath="$OUTDIR/usr/plugins/$GROUP"
echo " $srcpath -> $dstpath"
mkdir -p "$dstpath"
for srcsopath in $(find "$DEPSDIR/plugins/$GROUP" -iname '*.so'); do
# This is ../../ because it's usually plugins/group/name.so
soname=$(basename "$srcsopath")
dstsopath="$dstpath/$soname"
echo " $srcsopath -> $dstsopath"
cp "$srcsopath" "$dstsopath"
$PATCHELF --set-rpath '$ORIGIN/../../lib:$ORIGIN' "$dstsopath"
done
done
# Why do we have to manually remove these libs? Because the linuxdeploy Qt plugin
# copies them, not the "main" linuxdeploy binary, and plugins don't inherit the
# include list...

View File

@@ -18,13 +18,13 @@ LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
LIBJPEGTURBO=3.1.0
LIBPNG=1.6.48
LIBWEBP=1.5.0
SDL=SDL3-3.2.14
SDL=SDL3-3.2.16
QT=6.9.0
LZ4=1.10.0
ZSTD=1.5.7
KDDOCKWIDGETS=2.2.3
PLUTOVG=0.0.13
PLUTOSVG=0.0.6
PLUTOVG=1.1.0
PLUTOSVG=0.0.7
SHADERC=2024.1
SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
@@ -39,7 +39,7 @@ fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
6340e58879b2d15830c8460d2f589a385c444d1faa2a4828a9626c7322562be8 $SDL.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
c1800c2ea835801af04a05d4a32321d79a93954ee3ae2172bbeacf13d1f0598c qtbase-everywhere-src-$QT.tar.xz
@@ -53,8 +53,8 @@ aa27e4454ce631c5a17924ce0624eac736da19fc6f5a2ab15a6c58da7b36950f shaderc-glslan
5d866ce34a4b6908e262e5ebfffc0a5e11dd411640b5f24c85a80ad44c0d4697 shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
03ee1a2c06f3b61008478f4abe9423454e53e580b9488b47c8071547c6a9db47 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
f49d62709d6bf1808ddc9b8f71e22a755484f75c7bbb0fb368f7fb2ffc7cf645 plutovg-$PLUTOVG.tar.gz
01f8aee511bd587a602a166642a96522cc9522efd1e38c2d00e4fbc0aa22d7a0 plutosvg-$PLUTOSVG.tar.gz
8aa9860519c407890668c29998e8bb88896ef6a2e6d7ce5ac1e57f18d79e1525 plutovg-$PLUTOVG.tar.gz
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
EOF
curl -L \

View File

@@ -14,8 +14,8 @@
"sources": [
{
"type": "archive",
"url": "https://libsdl.org/release/SDL3-3.2.14.tar.gz",
"sha256": "b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f"
"url": "https://libsdl.org/release/SDL3-3.2.16.tar.gz",
"sha256": "6340e58879b2d15830c8460d2f589a385c444d1faa2a4828a9626c7322562be8"
}
],
"cleanup": [

View File

@@ -13,7 +13,8 @@
{
"type": "git",
"url": "https://github.com/sammycage/plutovg.git",
"tag": "v0.0.13"
"tag": "v1.1.0",
"commit": "1a8412d0574c4345dd7ef8a91ce7b58c7dcfe253"
}
],
"cleanup": [

View File

@@ -14,7 +14,8 @@
{
"type": "git",
"url": "https://github.com/sammycage/plutosvg.git",
"tag": "v0.0.6"
"tag": "v0.0.7",
"commit": "31f7d2675416cd777c8e86220b035364873b2a8b"
}
],
"cleanup": [

View File

@@ -40,7 +40,7 @@ fi
FREETYPE=2.13.3
HARFBUZZ=11.2.0
SDL=SDL3-3.2.14
SDL=SDL3-3.2.16
ZSTD=1.5.7
LZ4=1.10.0
LIBPNG=1.6.48
@@ -50,8 +50,8 @@ FFMPEG=6.0
MOLTENVK=1.2.9
QT=6.7.3
KDDOCKWIDGETS=2.2.3
PLUTOVG=0.0.13
PLUTOSVG=0.0.6
PLUTOVG=1.1.0
PLUTOSVG=0.0.7
SHADERC=2024.1
SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
@@ -79,7 +79,7 @@ CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
cat > SHASUMS <<EOF
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
6340e58879b2d15830c8460d2f589a385c444d1faa2a4828a9626c7322562be8 $SDL.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
@@ -97,8 +97,8 @@ aa27e4454ce631c5a17924ce0624eac736da19fc6f5a2ab15a6c58da7b36950f shaderc-glslan
5d866ce34a4b6908e262e5ebfffc0a5e11dd411640b5f24c85a80ad44c0d4697 shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
03ee1a2c06f3b61008478f4abe9423454e53e580b9488b47c8071547c6a9db47 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
f49d62709d6bf1808ddc9b8f71e22a755484f75c7bbb0fb368f7fb2ffc7cf645 plutovg-$PLUTOVG.tar.gz
01f8aee511bd587a602a166642a96522cc9522efd1e38c2d00e4fbc0aa22d7a0 plutosvg-$PLUTOSVG.tar.gz
8aa9860519c407890668c29998e8bb88896ef6a2e6d7ce5ac1e57f18d79e1525 plutovg-$PLUTOVG.tar.gz
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
EOF
curl -C - -L \

View File

@@ -22,7 +22,7 @@ fi
FREETYPE=2.13.3
HARFBUZZ=11.2.0
SDL=SDL3-3.2.14
SDL=SDL3-3.2.16
ZSTD=1.5.7
LZ4=1.10.0
LIBPNG=1.6.48
@@ -32,8 +32,8 @@ FFMPEG=6.0
MOLTENVK=1.2.9
QT=6.7.3
KDDOCKWIDGETS=2.2.3
PLUTOVG=0.0.13
PLUTOSVG=0.0.6
PLUTOVG=1.1.0
PLUTOSVG=0.0.7
SHADERC=2024.1
SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
@@ -59,7 +59,7 @@ CMAKE_COMMON=(
cat > SHASUMS <<EOF
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
6340e58879b2d15830c8460d2f589a385c444d1faa2a4828a9626c7322562be8 $SDL.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
@@ -77,8 +77,8 @@ aa27e4454ce631c5a17924ce0624eac736da19fc6f5a2ab15a6c58da7b36950f shaderc-glslan
5d866ce34a4b6908e262e5ebfffc0a5e11dd411640b5f24c85a80ad44c0d4697 shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
03ee1a2c06f3b61008478f4abe9423454e53e580b9488b47c8071547c6a9db47 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
b8529755b2d54205341766ae168e83177c6120660539f9afba71af6bca4b81ec KDDockWidgets-$KDDOCKWIDGETS.tar.gz
f49d62709d6bf1808ddc9b8f71e22a755484f75c7bbb0fb368f7fb2ffc7cf645 plutovg-$PLUTOVG.tar.gz
01f8aee511bd587a602a166642a96522cc9522efd1e38c2d00e4fbc0aa22d7a0 plutosvg-$PLUTOSVG.tar.gz
8aa9860519c407890668c29998e8bb88896ef6a2e6d7ce5ac1e57f18d79e1525 plutovg-$PLUTOVG.tar.gz
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
EOF
curl -L \

View File

@@ -46,7 +46,7 @@ set FREETYPE=2.13.3
set HARFBUZZ=11.2.0
set LIBJPEGTURBO=3.1.0
set LIBPNG=1648
set SDL=SDL3-3.2.14
set SDL=SDL3-3.2.16
set QT=6.9.0
set QTMINOR=6.9
set LZ4=1.10.0
@@ -55,8 +55,8 @@ set ZLIB=1.3.1
set ZLIBSHORT=131
set ZSTD=1.5.7
set KDDOCKWIDGETS=2.2.3
set PLUTOVG=0.0.13
set PLUTOSVG=0.0.6
set PLUTOVG=1.1.0
set PLUTOSVG=0.0.7
set SHADERC=2024.1
set SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
@@ -68,7 +68,7 @@ call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuz
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1648.zip 2e5f080360f77376eb2bfa9e2ed773b9c7728159aba47b638ad53ca839379040 || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || 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" 46a17d3ea71fe2580a7f43ca7da286c5b9106dd761e2fd5533bb113e5d86b633 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 0cc7430fb827c1f843e31b8b26ba7f083b1eeb8f6315a65d3744fd4d25b6c373 || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 513df15a6365a40f6230ec9463ad8c71b824e181d4b661dac9707e103b24ae0c || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" d428fd17a0d3f92c48a30f1d23806bf20352fbce2e80e5bbee27fa80576480ee || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 54bf06afeb67035f1c6afcd00beec755c0d776626b4cce9ab56992a55215ba69 || goto error
@@ -78,8 +78,8 @@ 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" e313baaa7c934503ef601c909661a84e5b795dfa12f0354721cac7a9c27be47e || goto error
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 24826a70d0b168a66eb16ec9d7eeeba0d4ca9d4babc1199889d374918008426e || goto error
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 83b2cd6230909a8d586518f49e79e4a1b1e9fab3847db6a678ec9d2dacab052a || 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" 6c9f42ed6bf42750f5369b089909abfdcf0101488b4a1f41116d5159d00af8e7 || goto error
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 03ad8a6fa987af4653d0cfe6bdaed41bcf617f1366a151fb1574da75950cd3e8 || goto error

View File

@@ -44,7 +44,7 @@ set FREETYPE=2.13.3
set HARFBUZZ=11.2.0
set LIBJPEGTURBO=3.1.0
set LIBPNG=1648
set SDL=SDL3-3.2.14
set SDL=SDL3-3.2.16
set QT=6.9.0
set QTMINOR=6.9
set LZ4=1.10.0
@@ -53,8 +53,8 @@ set ZLIB=1.3.1
set ZLIBSHORT=131
set ZSTD=1.5.7
set KDDOCKWIDGETS=2.2.3
set PLUTOVG=0.0.13
set PLUTOSVG=0.0.6
set PLUTOVG=1.1.0
set PLUTOSVG=0.0.7
set SHADERC=2024.1
set SHADERC_GLSLANG=142052fa30f9eca191aa9dcf65359fcaed09eeec
@@ -66,7 +66,7 @@ call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuz
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1648.zip 2e5f080360f77376eb2bfa9e2ed773b9c7728159aba47b638ad53ca839379040 || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 || 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" 46a17d3ea71fe2580a7f43ca7da286c5b9106dd761e2fd5533bb113e5d86b633 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 0cc7430fb827c1f843e31b8b26ba7f083b1eeb8f6315a65d3744fd4d25b6c373 || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 513df15a6365a40f6230ec9463ad8c71b824e181d4b661dac9707e103b24ae0c || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" d428fd17a0d3f92c48a30f1d23806bf20352fbce2e80e5bbee27fa80576480ee || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 54bf06afeb67035f1c6afcd00beec755c0d776626b4cce9ab56992a55215ba69 || goto error
@@ -76,8 +76,8 @@ 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" e313baaa7c934503ef601c909661a84e5b795dfa12f0354721cac7a9c27be47e || goto error
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 24826a70d0b168a66eb16ec9d7eeeba0d4ca9d4babc1199889d374918008426e || goto error
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 83b2cd6230909a8d586518f49e79e4a1b1e9fab3847db6a678ec9d2dacab052a || 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" 6c9f42ed6bf42750f5369b089909abfdcf0101488b4a1f41116d5159d00af8e7 || goto error
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 03ad8a6fa987af4653d0cfe6bdaed41bcf617f1366a151fb1574da75950cd3e8 || goto error

View File

@@ -905,6 +905,8 @@ PCPX-96323:
name-sort: "とろときゅうじつ [でも]"
name-en: "Toro to Kyuujitsu [Demo Movie]"
region: "NTSC-J"
gsHWFixes:
textureInsideRT: 1 # Fixes depth shadow stenciling effects.
PCPX-96324:
name: "デュアルハーツ [体験版]"
name-sort: "でゅあるはーつ [たいけんばん]"
@@ -6074,6 +6076,8 @@ SCES-53409:
SCES-53422:
name: "Stuart Little 3 - Big Photo Adventure"
region: "PAL-M9"
gameFixes:
- InstantDMAHack # Fixes loading screen corruption.
gsHWFixes:
autoFlush: 2 # Fixes missing effects.
SCES-53449:
@@ -7551,8 +7555,11 @@ SCKA-20066:
name: "EyeToy - Play 3"
region: "NTSC-K"
SCKA-20067:
name: "Stuart Little 3 - Big Photo Adventure"
name: "스튜어트 리틀 3 - 빅 포토 어드벤처"
name-en: "Stuart Little 3 - Big Photo Adventure"
region: "NTSC-K"
gameFixes:
- InstantDMAHack # Fixes loading screen corruption.
gsHWFixes:
autoFlush: 2 # Fixes missing effects.
SCKA-20068:
@@ -7940,6 +7947,7 @@ SCKA-20142:
region: "NTSC-K"
gsHWFixes:
textureInsideRT: 1 # Needed for mipmapping to function correctly.
mipmap: 0 # Currently causes texture corruption.
SCKA-20171:
name: "Let's Bravo Music"
region: "NTSC-K"
@@ -8455,6 +8463,8 @@ SCPS-15015:
name-en: "Toro to Kyuujitsu"
region: "NTSC-J"
compat: 5
gsHWFixes:
textureInsideRT: 1 # Fixes depth shadow stenciling effects.
SCPS-15016:
name: "みんなのGOLF 3"
name-sort: "みんなのごるふ 3"
@@ -12799,6 +12809,7 @@ SCUS-97657:
compat: 5
gsHWFixes:
textureInsideRT: 1 # Needed for mipmapping to function correctly.
mipmap: 0 # Currently causes texture corruption.
SCUS-97660:
name: "SingStar - Latino"
region: "NTSC-U"
@@ -20725,6 +20736,9 @@ SLES-52676:
SLES-52678:
name: "Viewtiful Joe"
region: "PAL-M5"
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 2 # Aligns post processing.
SLES-52680:
name: "Intellivision Lives - The History of Video Gaming"
region: "PAL-E"
@@ -21195,6 +21209,10 @@ SLES-52835:
name: "The Mummy"
name-sort: "Mummy, The"
region: "PAL-M6"
gsHWFixes:
halfPixelOffset: 5 # Aligns post processing.
autoFlush: 1 # Fixes light penetrating objects and intensity.
nativeScaling: 1 # Aligns post processing.
SLES-52836:
name: "Knight Rider 2"
region: "PAL-M6"
@@ -21812,7 +21830,6 @@ SLES-53028:
halfPixelOffset: 5 # Fixes alignment of shuffles and post-processing.
autoFlush: 1 # Fixes sun intensity.
textureInsideRT: 1 # Fixes post-processing.
getSkipCount: "GSC_HitmanBloodMoney"
SLES-53029:
name: "Hitman - Blood Money"
region: "PAL-F"
@@ -21823,7 +21840,6 @@ SLES-53029:
halfPixelOffset: 5 # Fixes alignment of shuffles and post-processing.
autoFlush: 1 # Fixes sun intensity.
textureInsideRT: 1 # Fixes post-processing.
getSkipCount: "GSC_HitmanBloodMoney"
SLES-53030:
name: "Hitman - Blood Money"
region: "PAL-G"
@@ -21834,7 +21850,6 @@ SLES-53030:
halfPixelOffset: 5 # Fixes alignment of shuffles and post-processing.
autoFlush: 1 # Fixes sun intensity.
textureInsideRT: 1 # Fixes post-processing.
getSkipCount: "GSC_HitmanBloodMoney"
SLES-53031:
name: "Hitman - Blood Money"
region: "PAL-I"
@@ -21845,7 +21860,6 @@ SLES-53031:
halfPixelOffset: 5 # Fixes alignment of shuffles and post-processing.
autoFlush: 1 # Fixes sun intensity.
textureInsideRT: 1 # Fixes post-processing.
getSkipCount: "GSC_HitmanBloodMoney"
SLES-53032:
name: "Hitman - Blood Money"
region: "PAL-S"
@@ -21856,7 +21870,6 @@ SLES-53032:
halfPixelOffset: 5 # Fixes alignment of shuffles and post-processing.
autoFlush: 1 # Fixes sun intensity.
textureInsideRT: 1 # Fixes post-processing.
getSkipCount: "GSC_HitmanBloodMoney"
SLES-53035:
name: "Masters of the Universe - He-Man - Defender of Greyskull"
region: "PAL-E"
@@ -22964,6 +22977,9 @@ SLES-53452:
SLES-53457:
name: "Evil Dead - Regeneration"
region: "PAL-E"
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 1 # Aligns post processing.
SLES-53458:
name: "Shin Megami Tensei - Digital Devil Saga"
region: "PAL-E"
@@ -26229,20 +26245,35 @@ SLES-54448:
name: "World Series of Poker - Tournament of Champions"
region: "PAL-E"
SLES-54449:
name: "Chicken Little - Ace in Action"
name: "Disney's Chicken Little - Ace in Action"
region: "PAL-E"
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 1 # Aligns post processing.
SLES-54450:
name: "Chicken Little - Aventures Intergalactiques"
name: "Disney Chicken Little - Aventures Intergalactiques"
region: "PAL-F"
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 1 # Aligns post processing.
SLES-54451:
name: "Himmel und Huhn - Ace in Action"
name: "Disneys Himmel und Huhn - Ace in Action"
region: "PAL-G"
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 1 # Aligns post processing.
SLES-54452:
name: "Disney Chicken Little - As en Acción"
region: "PAL-S"
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 1 # Aligns post processing.
SLES-54453:
name: "Chicken Little - Asso Spaziale!"
name: "Disney Chicken Little - Asso Spaziale!"
region: "PAL-I"
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 1 # Aligns post processing.
SLES-54454:
name: "Disgaea 2 - Cursed Memories"
region: "PAL-E"
@@ -27032,7 +27063,8 @@ SLES-54711:
region: "PAL-E"
compat: 5
gsHWFixes:
roundSprite: 2 # Fixes font artifacts and reduces text box artifacts.
halfPixelOffset: 5 # Fixes shadow positioning.
nativeScaling: 2 # Aligns post processing and bloom.
SLES-54712:
name: "Action Man A.T.O.M. - Alpha Teens on Machines"
region: "PAL-PL"
@@ -27980,6 +28012,10 @@ SLES-54996:
name: "The Golden Compass"
name-sort: "Golden Compass, The"
region: "PAL-M5"
gsHWFixes:
halfPixelOffset: 4 # Aligns post processing.
autoFlush: 1 # Fixes light penetrating objects and intensity.
nativeScaling: 2 # Aligns post processing.
SLES-54997:
name: "Mercenaries 2 - World in Flames"
region: "PAL-E"
@@ -28187,7 +28223,11 @@ SLES-55011:
SLES-55012:
name: "The Golden Compass"
name-sort: "Golden Compass, The"
region: "PAL-M5"
region: "PAL-SC"
gsHWFixes:
halfPixelOffset: 4 # Aligns post processing.
autoFlush: 1 # Fixes light penetrating objects and intensity.
nativeScaling: 2 # Aligns post processing.
SLES-55013:
name: "Iridium Runners"
region: "PAL-M5"
@@ -30111,14 +30151,16 @@ SLES-82030:
name: "Shadow Hearts - Covenant [Disc 1 of 2]"
region: "PAL-M3"
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
SLES-82031:
name: "Shadow Hearts - Covenant [Disc 2 of 2]"
region: "PAL-M3"
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
memcardFilters:
- "SLES-82030"
SLES-82032:
@@ -31376,8 +31418,12 @@ SLKA-25219:
gsHWFixes:
maximumBlendingLevel: 0 # Fixes unnecessary load on the GPU.
SLKA-25220:
name: "Viewtiful Joe - A New Hope"
name: "뷰티플 죠 새로운 희망"
name-en: "Viewtiful Joe - A New Hope"
region: "NTSC-K"
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 2 # Aligns post processing.
SLKA-25221:
name: "Busin 0 - Wizardry Alternative Neo"
region: "NTSC-K"
@@ -31750,8 +31796,12 @@ SLKA-25305:
name: "Taito Memories - Gekan"
region: "NTSC-K"
SLKA-25306:
name: "Evil Dead - Regeneration"
name: "이블데드 - 리제너레이션"
name-en: "Evil Dead - Regeneration"
region: "NTSC-K"
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 1 # Aligns post processing.
SLKA-25307:
name: "Dragon Ball Z - Sparking!"
region: "NTSC-K"
@@ -32421,8 +32471,12 @@ SLKA-25451:
name: "WWE SmackDown! vs. Raw 2008"
region: "NTSC-K"
SLKA-25452:
name: "Viewtiful Joe - A New Hope"
name: "뷰티플 죠 새로운 희망"
name-en: "Viewtiful Joe - A New Hope [BigHit Series]"
region: "NTSC-K"
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 2 # Aligns post processing.
SLKA-25453:
name: "Shin Onimusha - Dawn of Dreams [Disc 1 of 2]"
region: "NTSC-K"
@@ -34633,8 +34687,9 @@ SLPM-60214:
name-en: "Shadow Hearts II [Trial]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
SLPM-60215:
name: "電撃PS2 / 電撃PlayStation D63"
name-sort: "でんげき PS2 でんげきPlayStation D63"
@@ -34667,8 +34722,9 @@ SLPM-60219:
name-en: "Shadow Hearts II [Appendix Version]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
SLPM-60220:
name: "はじめの一歩2 VICTORIOUS ROAD [体験版]"
name-sort: "はじめのいっぽ2 VICTORIOUS ROAD [たいけんばん]"
@@ -34685,8 +34741,9 @@ SLPM-60226:
name-en: "Shadow Hearts II [Trial]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
SLPM-60228:
name: "街道バトル2 CHAIN REACTION [体験版]"
name-sort: "かいどうばとる2 CHAIN REACTION [たいけんばん]"
@@ -34866,6 +34923,9 @@ SLPM-60264:
name-sort: "しゃどうはーつ ふろむ・ざ・にゅー・わーるど [たいけんばん]"
name-en: "Shadow Hearts - From the New World [Trial]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes shadow positioning.
nativeScaling: 2 # Aligns post processing and bloom.
SLPM-60265:
name: "スチームボーイ [体験版]"
name-sort: "すちーむぼーい [たいけんばん]"
@@ -43925,6 +43985,9 @@ SLPM-65699:
name-en: "Viewtiful Joe - Aratanaru Kibo"
region: "NTSC-J"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 2 # Aligns post processing.
SLPM-65700:
name: "剣豪3"
name-sort: "けんごう3"
@@ -46082,7 +46145,8 @@ SLPM-66070:
name-en: "Shadow Hearts - From the New World [PREMIUM BOX]"
region: "NTSC-J"
gsHWFixes:
roundSprite: 2 # Fixes font artifacts and reduces text box artifacts.
halfPixelOffset: 5 # Fixes shadow positioning.
nativeScaling: 2 # Aligns post processing and bloom.
SLPM-66071:
name: "シャドウハーツ フロム・ザ・ニュー・ワールド"
name-sort: "しゃどうはーつ ふろむ・ざ・にゅー・わーるど"
@@ -46090,7 +46154,8 @@ SLPM-66071:
region: "NTSC-J"
compat: 5
gsHWFixes:
roundSprite: 2 # Fixes font artifacts and reduces text box artifacts.
halfPixelOffset: 5 # Fixes shadow positioning.
nativeScaling: 2 # Aligns post processing and bloom.
SLPM-66072:
name: "ファイトナイト ラウンド2"
name-sort: "ふぁいとないと らうんど2"
@@ -57599,16 +57664,18 @@ SLPS-25317:
name-en: "Shadow Hearts II [Deluxe Pack] [Disc 1 of 2]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
SLPS-25318:
name: "シャドウハーツⅡ [DXパック] [ディスク2/2]"
name-sort: "しゃどうはーつ2 [DXぱっく] [でぃすく2/2]"
name-en: "Shadow Hearts II [Deluxe Pack] [Disc 2 of 2]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
memcardFilters:
- "SLPS-25317"
SLPS-25319:
@@ -57686,16 +57753,18 @@ SLPS-25334:
name-en: "Shadow Hearts II [Standard Edition] [Disc 1 of 2]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
SLPS-25335:
name: "シャドウハーツⅡ [通常版] [ディスク2/2]"
name-sort: "しゃどうはーつ2 [つうじょうばん] [でぃすく2/2]"
name-en: "Shadow Hearts II [Standard Edition] [Disc 2 of 2]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
memcardFilters:
- "SLPS-25334"
SLPS-25336:
@@ -61962,16 +62031,18 @@ SLPS-73214:
name-en: "Shadow Hearts II [Director's Cut] [PlayStation2 the Best] [Disc 1 of 2]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
SLPS-73215:
name: "シャドウハーツⅡ ディレクターズカット [PlayStation2 the Best] [ディスク2/2]"
name-sort: "しゃどうはーつ2 でぃれくたーずかっと [PlayStation2 the Best] [でぃすく2/2]"
name-en: "Shadow Hearts II [Director's Cut] [PlayStation2 the Best] [Disc 2 of 2]"
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
memcardFilters:
- "SLPS-73214"
SLPS-73216:
@@ -67451,6 +67522,9 @@ SLUS-20951:
name: "Viewtiful Joe"
region: "NTSC-U"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 2 # Aligns post processing.
SLUS-20952:
name: "Tak 2 - The Staff of Dreams"
region: "NTSC-U"
@@ -68059,8 +68133,9 @@ SLUS-21041:
region: "NTSC-U"
compat: 5
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
SLUS-21042:
name: "Darkwatch"
region: "NTSC-U"
@@ -68076,8 +68151,9 @@ SLUS-21044:
region: "NTSC-U"
compat: 5
gsHWFixes:
halfPixelOffset: 4 # Fixes shadow positioning.
halfPixelOffset: 5 # Fixes shadow positioning.
autoFlush: 2 # Makes the shadow monsters appear.
nativeScaling: 2 # Aligns post processing and bloom.
memcardFilters:
- "SLUS-21041"
SLUS-21045:
@@ -68098,6 +68174,9 @@ SLUS-21048:
name: "Evil Dead - Regeneration"
region: "NTSC-U"
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 1 # Aligns post processing.
SLUS-21049:
name: "Outlaw Volleyball Remixed"
region: "NTSC-U"
@@ -68432,7 +68511,6 @@ SLUS-21108:
halfPixelOffset: 5 # Fixes alignment of shuffles and post-processing.
autoFlush: 1 # Fixes sun intensity.
textureInsideRT: 1 # Fixes post-processing.
getSkipCount: "GSC_HitmanBloodMoney"
SLUS-21109:
name: "Drive to Survive"
region: "NTSC-U"
@@ -69904,7 +69982,8 @@ SLUS-21326:
region: "NTSC-U"
compat: 5
gsHWFixes:
roundSprite: 2 # Fixes font artifacts and reduces text box artifacts.
halfPixelOffset: 5 # Fixes shadow positioning.
nativeScaling: 2 # Aligns post processing and bloom.
SLUS-21327:
name: "Atelier Iris 2 - The Azoth of Destiny"
region: "NTSC-U"
@@ -69996,6 +70075,8 @@ SLUS-21341:
name: "Stuart Little 3 - Big Photo Adventure"
region: "NTSC-U"
compat: 5
gameFixes:
- InstantDMAHack # Fixes loading screen corruption.
gsHWFixes:
autoFlush: 2 # Fixes missing effects.
SLUS-21342:
@@ -70576,6 +70657,9 @@ SLUS-21419:
SLUS-21420:
name: "Disney's Chicken Little - Ace in Action"
region: "NTSC-U"
gsHWFixes:
halfPixelOffset: 5 # Fixes post processing alignment.
nativeScaling: 1 # Aligns post processing.
SLUS-21421:
name: "Spy Hunter - Nowhere to Run"
region: "NTSC-U"
@@ -71944,6 +72028,10 @@ SLUS-21677:
name-sort: "Golden Compass, The"
region: "NTSC-U"
compat: 5
gsHWFixes:
halfPixelOffset: 4 # Aligns post processing.
autoFlush: 1 # Fixes light penetrating objects and intensity.
nativeScaling: 2 # Aligns post processing.
SLUS-21678:
name: "Dragon Ball Z - Budokai Tenkaichi 3"
region: "NTSC-U"
@@ -74353,8 +74441,8 @@ SLUS-29191:
vuClampMode: 0 # Fixes bump mapping issues
gsHWFixes:
textureInsideRT: 1 # Fixes post-processing.
autoFlush: 1 # Fixes sun intensity in Hitman.
halfPixelOffset: 5 # Fixes alignment of shuffles and post-processing in Hitman.
getSkipCount: "GSC_HitmanBloodMoney"
SLUS-29192:
name: "Test Drive Unlimited [Public Beta Vol.1.0]"
region: "NTSC-U"

View File

@@ -329,6 +329,7 @@
030000000d0f0000ee00000000000000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f0000c100000000000000,Horipad Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f0000f600000000000000,Horipad Nintendo Switch Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000000d0f00000202000000000000,Horipad O Nintendo Switch 2 Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,misc2:b14,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Windows,
030000000d0f00006700000000000000,Horipad One,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,
030000000d0f00009601000000000000,Horipad Steam,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:b8,leftx:a0,lefty:a1,misc2:b2,paddle1:b5,paddle2:b15,paddle3:b18,paddle4:b19,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
030000000d0f0000dc00000000000000,Horipad Switch,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,

View File

@@ -19,8 +19,8 @@ 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(plutovg REQUIRED) # v0.0.13 is needed for building plutosvg, but we can support v1.0.0
find_package(plutosvg 0.0.6 REQUIRED)
find_package(plutovg 1.1.0 REQUIRED)
find_package(plutosvg 0.0.7 REQUIRED)
if(USE_VULKAN)
find_package(Shaderc REQUIRED)

View File

@@ -629,7 +629,7 @@
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;h1 style=&quot; margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:xx-large; font-weight:700;&quot;&gt;Setup Complete!&lt;/span&gt;&lt;/h1&gt;&lt;p&gt;You are now ready to run games.&lt;/p&gt;&lt;p&gt;Further options are available under the settings menu. You can also use the Big Picture UI for navigation entirely with a gamepad.&lt;/p&gt;&lt;p&gt;We hope you enjoy using PCSX2.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;h1 style=&quot; margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-size:xx-large; font-weight:700;&quot;&gt;Setup Complete!&lt;/span&gt;&lt;/h1&gt;&lt;p&gt;You are now ready to run games.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:700;&quot;&gt;Warning: Do not run untrusted programs in PCSX2. It is not a sandbox and cannot protect your computer from malicious software.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Further options are available under the settings menu. You can also use the Big Picture UI for navigation entirely with a gamepad.&lt;/p&gt;&lt;p&gt;We hope you enjoy using PCSX2.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -449,7 +449,7 @@ void GSClut::Read32(const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA)
if (dst)
{
GL_PUSH("Update GPU CLUT [CBP=%04X, CPSM=%s, CBW=%u, CSA=%u, Offset=(%d,%d)]",
TEX0.CBP, psm_str(TEX0.CPSM), CBW, TEX0.CSA, offset.x, offset.y);
TEX0.CBP, GSUtil::GetPSMName(TEX0.CPSM), CBW, TEX0.CSA, offset.x, offset.y);
g_gs_device->UpdateCLUTTexture(src, scale, offset.x, offset.y, dst, dOffset, dst_size);
m_current_gpu_clut = dst;
}

View File

@@ -1977,7 +1977,7 @@ void GSState::Write(const u8* mem, int len)
}
GL_CACHE("Write! %u ... => 0x%x W:%d F:%s (DIR %d%d), dPos(%d %d) size(%d %d) draw %d", s_transfer_n,
blit.DBP, blit.DBW, psm_str(blit.DPSM),
blit.DBP, blit.DBW, GSUtil::GetPSMName(blit.DPSM),
m_tr.m_pos.DIRX, m_tr.m_pos.DIRY,
m_tr.x, m_tr.y, m_tr.w, m_tr.h, s_n);
@@ -2107,8 +2107,8 @@ void GSState::Move()
const int h = m_env.TRXREG.RRH;
GL_CACHE("Move! 0x%x W:%d F:%s => 0x%x W:%d F:%s (DIR %d%d), sPos(%d %d) dPos(%d %d) size(%d %d)",
m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW, psm_str(m_env.BITBLTBUF.SPSM),
m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, psm_str(m_env.BITBLTBUF.DPSM),
m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW, GSUtil::GetPSMName(m_env.BITBLTBUF.SPSM),
m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, GSUtil::GetPSMName(m_env.BITBLTBUF.DPSM),
m_env.TRXPOS.DIRX, m_env.TRXPOS.DIRY,
sx, sy, dx, dy, w, h);

View File

@@ -235,7 +235,7 @@ GSRendererType GSUtil::GetPreferredRenderer()
return preferred_renderer;
}
const char* psm_str(int psm)
const char* GSUtil::GetPSMName(int psm)
{
switch (psm)
{

View File

@@ -11,6 +11,7 @@ class GSUtil
public:
static const char* GetATSTName(u32 atst);
static const char* GetAFAILName(u32 afail);
static const char* GetPSMName(int psm);
static GS_PRIM_CLASS GetPrimClass(u32 prim);
static int GetVertexCount(u32 prim);
@@ -27,5 +28,3 @@ public:
static GSRendererType GetPreferredRenderer();
};
const char* psm_str(int psm);

View File

@@ -551,9 +551,18 @@ void GSDevice11::Destroy()
m_rs.reset();
if (m_state.rt_view)
{
m_state.rt_view->Release();
m_state.rt_view = nullptr;
}
m_state.cached_rt_view = nullptr;
if (m_state.dsv)
{
m_state.dsv->Release();
m_state.dsv = nullptr;
}
m_state.cached_dsv = nullptr;
m_shader_cache.Close();
@@ -950,11 +959,13 @@ GSDevice::PresentResult GSDevice11::BeginPresent(bool frame_skip)
m_state.rt_view->Release();
m_state.rt_view = m_swap_chain_rtv.get();
m_state.rt_view->AddRef();
m_state.cached_rt_view = nullptr;
if (m_state.dsv)
{
m_state.dsv->Release();
m_state.dsv = nullptr;
}
m_state.cached_dsv = nullptr;
g_perfmon.Put(GSPerfMon::RenderPasses, 1);
@@ -1105,14 +1116,14 @@ float GSDevice11::GetAndResetAccumulatedGPUTime()
void GSDevice11::DrawPrimitive()
{
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
PSUpdateShaderState();
PSUpdateShaderState(true, true);
m_ctx->Draw(m_vertex.count, m_vertex.start);
}
void GSDevice11::DrawIndexedPrimitive()
{
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
PSUpdateShaderState();
PSUpdateShaderState(true, true);
m_ctx->DrawIndexed(m_index.count, m_index.start, m_vertex.start);
}
@@ -1120,7 +1131,7 @@ void GSDevice11::DrawIndexedPrimitive(int offset, int count)
{
pxAssert(offset + count <= (int)m_index.count);
g_perfmon.Put(GSPerfMon::DrawCalls, 1);
PSUpdateShaderState();
PSUpdateShaderState(true, true);
m_ctx->DrawIndexed(count, m_index.start + offset, m_vertex.start);
}
@@ -1280,8 +1291,10 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
GSVector2i ds;
if (dTex)
{
// ps unbind conflicting srvs
PSUnbindConflictingSRVs(dTex);
ds = dTex->GetSize();
PSUnbindConflictingSRVs(dTex, nullptr);
if (draw_in_depth)
OMSetRenderTargets(nullptr, dTex);
else
@@ -1293,6 +1306,7 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
}
// om
if (draw_in_depth)
OMSetDepthStencilState(m_convert.dss_write.get(), 0);
else
@@ -1342,6 +1356,9 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
GSVector2i ds;
if (dTex)
{
// ps unbind conflicting srvs
PSUnbindConflictingSRVs(dTex);
ds = dTex->GetSize();
OMSetRenderTargets(dTex, nullptr);
}
@@ -1357,6 +1374,7 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
m_ctx->UpdateSubresource(m_present.ps_cb.get(), 0, nullptr, &cb, 0, 0);
// om
OMSetDepthStencilState(m_convert.dss.get(), 0);
OMSetBlendState(m_convert.bs[D3D11_COLOR_WRITE_ENABLE_ALL].get(), 0);
@@ -1455,6 +1473,7 @@ void GSDevice11::DrawMultiStretchRects(const MultiStretchRect* rects, u32 num_re
VSSetShader(m_convert.vs.get(), nullptr);
PSSetShader(m_convert.ps[static_cast<int>(shader)].get(), nullptr);
PSUnbindConflictingSRVs(dTex);
OMSetDepthStencilState(dTex->IsRenderTarget() ? m_convert.dss.get() : m_convert.dss_write.get(), 0);
OMSetRenderTargets(dTex->IsRenderTarget() ? dTex : nullptr, dTex->IsDepthStencil() ? dTex : nullptr);
@@ -2111,7 +2130,7 @@ void GSDevice11::RenderImGui()
// Since we don't have the GSTexture...
m_state.ps_sr_views[0] = reinterpret_cast<ID3D11ShaderResourceView*>(pcmd->GetTexID());
PSUpdateShaderState();
PSUpdateShaderState(true, true);
m_ctx->DrawIndexed(pcmd->ElemCount, m_index.start + pcmd->IdxOffset, vertex_offset + pcmd->VtxOffset);
}
@@ -2131,6 +2150,10 @@ void GSDevice11::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vert
m_ctx->ClearDepthStencilView(*static_cast<GSTexture11*>(ds), D3D11_CLEAR_STENCIL, 0.0f, 0);
// ps unbind conflicting srvs
PSUnbindConflictingSRVs(ds);
// om
OMSetDepthStencilState(m_date.dss.get(), 1);
@@ -2359,19 +2382,55 @@ void GSDevice11::PSSetShader(ID3D11PixelShader* ps, ID3D11Buffer* ps_cb)
}
}
void GSDevice11::PSUpdateShaderState()
void GSDevice11::PSUpdateShaderState(const bool sr_update, const bool ss_update)
{
m_ctx->PSSetShaderResources(0, m_state.ps_sr_views.size(), m_state.ps_sr_views.data());
m_ctx->PSSetSamplers(0, m_state.ps_ss.size(), m_state.ps_ss.data());
// Shader resource caching requires srv/rtv hazards to be resolved, ensure PSUnbindConflictingSRVs handle.
if (sr_update)
{
bool sr_changed = false;
for (size_t i = 0; i < m_state.ps_sr_views.size(); ++i)
{
if (m_state.ps_cached_sr_views[i] != m_state.ps_sr_views[i])
{
sr_changed = true;
break;
}
}
if (sr_changed)
{
m_state.ps_cached_sr_views = m_state.ps_sr_views;
m_ctx->PSSetShaderResources(0, m_state.ps_sr_views.size(), m_state.ps_sr_views.data());
}
}
if (ss_update)
{
bool ss_changed = false;
for (size_t i = 0; i < m_state.ps_ss.size(); ++i)
{
if (m_state.ps_cached_ss[i] != m_state.ps_ss[i])
{
ss_changed = true;
break;
}
}
if (ss_changed)
{
m_state.ps_cached_ss = m_state.ps_ss;
m_ctx->PSSetSamplers(0, m_state.ps_ss.size(), m_state.ps_ss.data());
}
}
}
void GSDevice11::PSUnbindConflictingSRVs(GSTexture* rt, GSTexture* ds)
void GSDevice11::PSUnbindConflictingSRVs(GSTexture* tex1, GSTexture* tex2)
{
// Make sure no SRVs are bound using the same texture before binding it to a RTV.
bool changed = false;
for (size_t i = 0; i < m_state.ps_sr_views.size(); i++)
{
if ((rt && m_state.ps_sr_views[i] == *(GSTexture11*)rt) || (ds && m_state.ps_sr_views[i] == *(GSTexture11*)ds))
if ((tex1 && m_state.ps_sr_views[i] == *(GSTexture11*)tex1) || (tex2 && m_state.ps_sr_views[i] == *(GSTexture11*)tex2))
{
m_state.ps_sr_views[i] = nullptr;
changed = true;
@@ -2379,12 +2438,12 @@ void GSDevice11::PSUnbindConflictingSRVs(GSTexture* rt, GSTexture* ds)
}
if (changed)
PSUpdateShaderState();
PSUpdateShaderState(true, false);
}
void GSDevice11::OMSetDepthStencilState(ID3D11DepthStencilState* dss, u8 sref)
{
if (m_state.dss != dss || m_state.sref != sref)
if (m_state.dss != dss || (dss && m_state.sref != sref))
{
m_state.dss = dss;
m_state.sref = sref;
@@ -2395,7 +2454,7 @@ void GSDevice11::OMSetDepthStencilState(ID3D11DepthStencilState* dss, u8 sref)
void GSDevice11::OMSetBlendState(ID3D11BlendState* bs, u8 bf)
{
if (m_state.bs != bs || m_state.bf != bf)
if (m_state.bs != bs || (bs && m_state.bf != bf))
{
m_state.bs = bs;
m_state.bf = bf;
@@ -2432,6 +2491,7 @@ void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector
if (rtv)
rtv->AddRef();
m_state.rt_view = rtv;
m_state.cached_rt_view = rt;
}
if (m_state.dsv != dsv)
{
@@ -2440,6 +2500,7 @@ void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector
if (dsv)
dsv->AddRef();
m_state.dsv = dsv;
m_state.cached_dsv = ds;
}
if (changed)
m_ctx->OMSetRenderTargets(1, &rtv, dsv);
@@ -2680,11 +2741,31 @@ void GSDevice11::RenderHW(GSHWDrawConfig& config)
config.ps.date = 3;
config.alpha_second_pass.ps.date = 3;
SetupPS(config.ps, nullptr, config.sampler);
PSSetShaderResource(3, primid_texture);
}
// Avoid changing framebuffer just to switch from rt+depth to rt and vice versa.
GSTexture* draw_rt = colclip_rt ? colclip_rt : config.rt;
GSTexture* draw_ds = config.ds;
// Make sure no tex is bound as both rtv and srv at the same time.
// All conflicts should've been taken care of by PSUnbindConflictingSRVs.
// It is fine to do the optimiation when on slot 0 tex is fb, tex is ds, and slot 2 sw blend as they are copies bound to srv.
if (!draw_rt && draw_ds && m_state.rt_view && m_state.cached_rt_view && m_state.rt_view == *(GSTexture11*)m_state.cached_rt_view &&
m_state.cached_dsv == draw_ds && config.tex != m_state.cached_rt_view && m_state.cached_rt_view->GetSize() == draw_ds->GetSize())
{
draw_rt = m_state.cached_rt_view;
}
else if (!draw_ds && draw_rt && m_state.dsv && m_state.cached_dsv && m_state.dsv == *(GSTexture11*)m_state.cached_dsv &&
m_state.cached_rt_view == draw_rt && config.tex != m_state.cached_dsv && m_state.cached_dsv->GetSize() == draw_rt->GetSize())
{
draw_ds = m_state.cached_dsv;
}
OMSetRenderTargets(draw_rt, draw_ds, &config.scissor);
if (primid_texture)
PSSetShaderResource(3, primid_texture);
SetupOM(config.depth, OMBlendSelector(config.colormask, config.blend), config.blend.constant);
OMSetRenderTargets(colclip_rt ? colclip_rt : config.rt, config.ds, &config.scissor);
DrawIndexedPrimitive();
if (config.blend_multi_pass.enable)

View File

@@ -145,9 +145,11 @@ private:
ID3D11VertexShader* vs;
ID3D11Buffer* vs_cb;
std::array<ID3D11ShaderResourceView*, MAX_TEXTURES> ps_sr_views;
std::array<ID3D11ShaderResourceView*, MAX_TEXTURES> ps_cached_sr_views;
ID3D11PixelShader* ps;
ID3D11Buffer* ps_cb;
std::array<ID3D11SamplerState*, MAX_SAMPLERS> ps_ss;
std::array<ID3D11SamplerState*, MAX_SAMPLERS> ps_cached_ss;
GSVector2i viewport;
GSVector4i scissor;
u32 vb_stride;
@@ -157,6 +159,8 @@ private:
u8 bf;
ID3D11RenderTargetView* rt_view;
ID3D11DepthStencilView* dsv;
GSTexture* cached_rt_view;
GSTexture* cached_dsv;
} m_state;
std::array<std::array<wil::com_ptr_nothrow<ID3D11Query>, 3>, NUM_TIMESTAMP_QUERIES> m_timestamp_queries = {};
@@ -324,8 +328,8 @@ public:
void PSSetShaderResource(int i, GSTexture* sr);
void PSSetShader(ID3D11PixelShader* ps, ID3D11Buffer* ps_cb);
void PSUpdateShaderState();
void PSUnbindConflictingSRVs(GSTexture* rt, GSTexture* ds);
void PSUpdateShaderState(const bool sr_update, const bool ss_update);
void PSUnbindConflictingSRVs(GSTexture* tex1 = nullptr, GSTexture* tex2 = nullptr);
void PSSetSamplerState(ID3D11SamplerState* ss0);
void OMSetDepthStencilState(ID3D11DepthStencilState* dss, u8 sref);

View File

@@ -637,7 +637,7 @@ bool GSHwHack::GSC_PolyphonyDigitalGames(GSRendererHW& r, int& skip)
constexpr u32 base = 0;
GL_PUSH("GSC_PolyphonyDigitalGames(): HLE Gran Turismo A channel shuffle");
GL_INS("Src: %x %s TBW %u, Dst: %x, %x, %x", src->m_TEX0.TBP0, psm_str(src->m_TEX0.PSM), src->m_TEX0.TBW,
GL_INS("Src: %x %s TBW %u, Dst: %x, %x, %x", src->m_TEX0.TBP0, GSUtil::GetPSMName(src->m_TEX0.PSM), src->m_TEX0.TBW,
base, base + page_offset, base + page_offset * 2);
GL_INS("Rect: %d,%d => %d,%d", src->m_drawn_since_read.x, src->m_drawn_since_read.y,
src->m_drawn_since_read.z, src->m_drawn_since_read.w);

View File

@@ -180,7 +180,7 @@ GSTexture* GSRendererHW::GetOutput(int i, float& scale, int& y_offset)
if (GSConfig.SaveFrame && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
{
t->Save(GetDrawDumpPath("%05d_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), i, static_cast<int>(TEX0.TBP0), psm_str(TEX0.PSM)));
t->Save(GetDrawDumpPath("%05d_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), i, static_cast<int>(TEX0.TBP0), GSUtil::GetPSMName(TEX0.PSM)));
}
}
@@ -206,7 +206,7 @@ GSTexture* GSRendererHW::GetFeedbackOutput(float& scale)
scale = rt->m_scale;
if (GSConfig.SaveFrame && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
t->Save(GetDrawDumpPath("%05d_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), 3, static_cast<int>(TEX0.TBP0), psm_str(TEX0.PSM)));
t->Save(GetDrawDumpPath("%05d_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), 3, static_cast<int>(TEX0.TBP0), GSUtil::GetPSMName(TEX0.PSM)));
return t;
}
@@ -1055,7 +1055,7 @@ GSVector2i GSRendererHW::GetValidSize(const GSTextureCache::Source* tex, const b
int width = std::min(std::max<int>(m_cached_ctx.FRAME.FBW, 1) * 64, m_context->scissor.in.z);
if (m_cached_ctx.FRAME.FBW == 0 && m_r.w > frame_psm.pgs.y)
{
GL_INS("HW: FBW=0 when drawing more than 1 page in height (PSM %s, PGS %dx%d).", psm_str(m_cached_ctx.FRAME.PSM),
GL_INS("HW: FBW=0 when drawing more than 1 page in height (PSM %s, PGS %dx%d).", GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM),
frame_psm.pgs.x, frame_psm.pgs.y);
}
@@ -1440,7 +1440,7 @@ bool GSRendererHW::TryToResolveSinglePageFramebuffer(GIFRegFRAME& FRAME, bool on
if (tgt && ((start_bp + (m_split_clear_pages * BLOCKS_PER_PAGE)) - 1) <= tgt->m_end_block)
{
GL_INS("HW: TryToResolveSinglePageWidth(): Using FBW of %u and PSM %s from existing target",
tgt->m_TEX0.PSM, psm_str(tgt->m_TEX0.PSM));
tgt->m_TEX0.PSM, GSUtil::GetPSMName(tgt->m_TEX0.PSM));
new_bw = tgt->m_TEX0.TBW;
new_psm = tgt->m_TEX0.PSM;
}
@@ -1495,7 +1495,7 @@ bool GSRendererHW::IsStartingSplitClear()
m_split_clear_color = GetConstantDirectWriteMemClearColor();
GL_INS("HW: Starting split clear at FBP %x FBW %u PSM %s with %dx%d rect covering %u pages",
m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, psm_str(m_cached_ctx.FRAME.PSM),
m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM),
m_r.width(), m_r.height(), pages_covered);
// Remove any targets which are directly at the start.
@@ -1581,7 +1581,7 @@ bool GSRendererHW::CheckNextDrawForSplitClear(const GSVector4i& r, u32* pages_co
void GSRendererHW::FinishSplitClear()
{
GL_INS("HW: FinishSplitClear(): Start %x FBW %u PSM %s, %u pages, %08X color", m_split_clear_start.Block(),
m_split_clear_start.FBW, psm_str(m_split_clear_start.PSM), m_split_clear_pages, m_split_clear_color);
m_split_clear_start.FBW, GSUtil::GetPSMName(m_split_clear_start.PSM), m_split_clear_pages, m_split_clear_color);
// If this was a tall single-page draw, try to get a better BW from somewhere.
if (m_split_clear_start.FBW <= 1 && m_split_clear_pages >= 16) // 1024 high
@@ -1592,7 +1592,7 @@ void GSRendererHW::FinishSplitClear()
ReplaceVerticesWithSprite(
GetDrawRectForPages(m_split_clear_start.FBW, m_split_clear_start.PSM, m_split_clear_pages), GSVector2i(1, 1));
GL_INS("HW: FinishSplitClear(): New draw rect is (%d,%d=>%d,%d) with FBW %u and PSM %s", m_r.x, m_r.y, m_r.z, m_r.w,
m_split_clear_start.FBW, psm_str(m_split_clear_start.PSM));
m_split_clear_start.FBW, GSUtil::GetPSMName(m_split_clear_start.PSM));
m_split_clear_start.U64 = 0;
m_split_clear_start_Z.U64 = 0;
m_split_clear_pages = 0;
@@ -1809,8 +1809,8 @@ void GSRendererHW::Move()
const int w = m_env.TRXREG.RRW;
const int h = m_env.TRXREG.RRH;
GL_CACHE("HW: Starting Move! 0x%x W:%d F:%s => 0x%x W:%d F:%s (DIR %d%d), sPos(%d %d) dPos(%d %d) size(%d %d) draw %d",
m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW, psm_str(m_env.BITBLTBUF.SPSM),
m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, psm_str(m_env.BITBLTBUF.DPSM),
m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW, GSUtil::GetPSMName(m_env.BITBLTBUF.SPSM),
m_env.BITBLTBUF.DBP, m_env.BITBLTBUF.DBW, GSUtil::GetPSMName(m_env.BITBLTBUF.DPSM),
m_env.TRXPOS.DIRX, m_env.TRXPOS.DIRY,
sx, sy, dx, dy, w, h, s_n);
if (g_texture_cache->Move(m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW, m_env.BITBLTBUF.SPSM, sx, sy,
@@ -1908,7 +1908,7 @@ void GSRendererHW::SwSpriteRender()
const int w = trxreg.RRW;
const int h = trxreg.RRH;
GL_INS("HW: SwSpriteRender: Dest 0x%x W:%d F:%s, size(%d %d)", m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, psm_str(m_cached_ctx.FRAME.PSM), w, h);
GL_INS("HW: SwSpriteRender: Dest 0x%x W:%d F:%s, size(%d %d)", m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM), w, h);
const GSOffset spo = m_mem.GetOffset(m_context->TEX0.TBP0, m_context->TEX0.TBW, m_context->TEX0.PSM);
const GSOffset& dpo = m_context->offset.fb;
@@ -2230,6 +2230,7 @@ void GSRendererHW::Draw()
// We mess with this state as an optimization, so take a copy and use that instead.
const GSDrawingContext* context = m_context;
m_cached_ctx.TEX0 = context->TEX0;
m_cached_ctx.TEXA = m_draw_env->TEXA;
m_cached_ctx.CLAMP = context->CLAMP;
m_cached_ctx.TEST = context->TEST;
m_cached_ctx.FRAME = context->FRAME;
@@ -2308,7 +2309,7 @@ void GSRendererHW::Draw()
{
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, psm_str(m_cached_ctx.FRAME.PSM));
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);
}
@@ -2359,11 +2360,10 @@ void GSRendererHW::Draw()
const u32 fm_mask = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk;
// Note required to compute TryAlphaTest below. So do it now.
const GSDrawingEnvironment& env = *m_draw_env;
const GSLocalMemory::psm_t& tex_psm = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM];
if (PRIM->TME && tex_psm.pal > 0)
{
m_mem.m_clut.Read32(m_cached_ctx.TEX0, env.TEXA);
m_mem.m_clut.Read32(m_cached_ctx.TEX0, m_cached_ctx.TEXA);
if (m_mem.m_clut.GetGPUTexture())
{
CalcAlphaMinMax(0, 255);
@@ -2672,6 +2672,48 @@ void GSRendererHW::Draw()
GSVector2i(1, 1));
height_invalid = false;
}
const u32 vert_index = (m_vt.m_primclass == GS_TRIANGLE_CLASS) ? 2 : 1;
u32 const_color = m_vertex.buff[m_index.buff[vert_index]].RGBAQ.U32[0];
u32 fb_mask = m_cached_ctx.FRAME.FBMSK;
// If we could just check the colour, it would be great, but Echo Night decided it's going to set the alpha and green to 128, for some reason, and actually be 32bit, so it ruined my day.
GSTextureCache::Target* rt_tgt = g_texture_cache->GetExactTarget(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, GSTextureCache::RenderTarget, m_cached_ctx.FRAME.Block() + 1);
const bool clear_16bit_likely = !(context->FRAME.PSM & 0x2) && ((rt_tgt && (rt_tgt->m_TEX0.PSM & 2)) || (!rt_tgt && ((static_cast<int>(context->FRAME.FBW) * 64) <= (PCRTCDisplays.GetResolution().x >> 1) || m_r.height() <= (PCRTCDisplays.GetResolution().y >> 1))));
rt_tgt = nullptr;
if (clear_16bit_likely && ((const_color != 0 && (const_color >> 16) == (const_color & 0xFFFF) && ((const_color >> 8) & 0xFF) != (const_color & 0xFF)) ||
(fb_mask != 0 && (fb_mask >> 16) == (fb_mask & 0xFFFF) && ((fb_mask >> 8) & 0xFF) != (fb_mask & 0xFF))))
{
const int get_next_ctx = m_env.PRIM.CTXT;
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
GL_CACHE("Clear 16bit with 32bit %d", s_n);
// May have already been resized through the split draw checks.
if (!(m_cached_ctx.FRAME.PSM & 2))
{
if (next_ctx.FRAME.FBW == (m_cached_ctx.FRAME.FBW * 2))
{
m_cached_ctx.FRAME.FBW *= 2;
m_r.z *= 2;
}
else
{
m_r.w *= 2;
}
}
// Convert colour and masks to 16bit and set a custom TEXA for this draw.
const_color = ((const_color & 0x1F) << 3) | ((const_color & 0x3E0) << 6) | ((const_color & 0x7C00) << 9) | ((const_color & 0x8000) << 16);
m_cached_ctx.FRAME.FBMSK = ((fb_mask & 0x1F) << 3) | ((fb_mask & 0x3E0) << 6) | ((fb_mask & 0x7C00) << 9) | ((fb_mask & 0x8000) << 16);
m_cached_ctx.TEXA.AEM = 0;
m_cached_ctx.TEXA.TA0 = 0;
m_cached_ctx.TEXA.TA1 = 128;
m_cached_ctx.FRAME.PSM = (m_cached_ctx.FRAME.PSM & 2) ? m_cached_ctx.FRAME.PSM : PSMCT16;
m_vertex.buff[m_index.buff[1]].RGBAQ.U32[0] = const_color;
ReplaceVerticesWithSprite(m_r, GSVector2i(m_r.width(), m_r.height()));
}
// Be careful of being 1 pixel from filled.
const bool page_aligned = (m_r.w % pgs.y) == (pgs.y - 1) || (m_r.w % pgs.y) == 0;
@@ -2936,7 +2978,7 @@ void GSRendererHW::Draw()
}
possible_shuffle = !no_rt && (((shuffle_target /*&& GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16*/) /*|| (m_cached_ctx.FRAME.Block() == m_cached_ctx.TEX0.TBP0 && ((m_cached_ctx.TEX0.PSM & 0x6) || m_cached_ctx.FRAME.PSM != m_cached_ctx.TEX0.PSM))*/) || IsPossibleChannelShuffle());
const bool need_aem_color = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp <= 24 && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].pal == 0 && ((NeedsBlending() && m_context->ALPHA.C == 0) || IsDiscardingDstAlpha()) && m_draw_env->TEXA.AEM;
const bool need_aem_color = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp <= 24 && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].pal == 0 && ((NeedsBlending() && m_context->ALPHA.C == 0) || IsDiscardingDstAlpha()) && m_cached_ctx.TEXA.AEM;
const u32 color_mask = (m_vt.m_max.c > GSVector4i::zero()).mask();
const bool texture_function_color = m_cached_ctx.TEX0.TFX == TFX_DECAL || (color_mask & 0xFFF) || (m_cached_ctx.TEX0.TFX > TFX_DECAL && (color_mask & 0xF000));
const bool texture_function_alpha = m_cached_ctx.TEX0.TFX != TFX_MODULATE || (color_mask & 0xF000);
@@ -2953,8 +2995,8 @@ void GSRendererHW::Draw()
}
else
{
src = tex_psm.depth ? g_texture_cache->LookupDepthSource(true, TEX0, env.TEXA, MIP_CLAMP, tmm.coverage, possible_shuffle, m_vt.IsLinear(), m_cached_ctx.FRAME, req_color, req_alpha) :
g_texture_cache->LookupSource(true, TEX0, env.TEXA, MIP_CLAMP, tmm.coverage, (GSConfig.HWMipmap || GSConfig.TriFilter == TriFiltering::Forced) ? &hash_lod_range : nullptr,
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]]
@@ -3603,17 +3645,18 @@ void GSRendererHW::Draw()
if (ds && rt && (m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) != (m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0))
{
m_using_temp_z = true;
const int page_offset = (static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32);
const int z_vertical_offset = (page_offset / std::max(ds->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.y;
const int z_horizontal_offset = (page_offset % std::max(ds->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.x;
const int page_offset = static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32;
const int rt_page_offset = static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) / 32;
const int z_vertical_offset = (page_offset / std::max(static_cast<int>(ds->m_TEX0.TBW), 1)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.y;
const int z_horizontal_offset = (page_offset % std::max(static_cast<int>(ds->m_TEX0.TBW), 1)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.x;
if (g_texture_cache->GetTemporaryZ() != nullptr)
{
GSTextureCache::TempZAddress z_address_info = g_texture_cache->GetTemporaryZInfo();
const int old_z_vertical_offset = (page_offset / std::max(ds->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.y;
const int old_z_horizontal_offset = (page_offset % std::max(ds->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.x;
const int old_z_vertical_offset = (z_address_info.offset / std::max(static_cast<int>(ds->m_TEX0.TBW), 1)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.y;
const int old_z_horizontal_offset = (z_address_info.offset % std::max(static_cast<int>(ds->m_TEX0.TBW), 1)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.x;
if (ds->m_TEX0.TBP0 != z_address_info.ZBP || z_address_info.offset != page_offset)
if (ds->m_TEX0.TBP0 != z_address_info.ZBP || z_address_info.offset != page_offset || z_address_info.rt_offset != rt_page_offset)
g_texture_cache->InvalidateTemporaryZ();
else if (!m_r.rintersect(z_address_info.rect_since).rempty() && m_cached_ctx.TEST.ZTST > ZTST_ALWAYS)
{
@@ -3633,10 +3676,11 @@ void GSRendererHW::Draw()
if (g_texture_cache->GetTemporaryZ() == nullptr)
{
ds->Update(); // We need to update any dirty bits of Z before the copy
m_temp_z_full_copy = false;
const int get_next_ctx = m_env.PRIM.CTXT;
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
const int rt_page_offset = (static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) / 32);
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;
@@ -3644,36 +3688,19 @@ void GSRendererHW::Draw()
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);
GSVector4i dRect = GSVector4i(horizontal_offset * ds->m_scale, vertical_offset * ds->m_scale, ds->m_unscaled_size.x * ds->m_scale, ds->m_unscaled_size.y * ds->m_scale);
GSVector4i dRect = GSVector4i(horizontal_offset * ds->m_scale, vertical_offset * ds->m_scale, (horizontal_offset + (ds->m_unscaled_size.x - z_horizontal_offset)) * ds->m_scale, (vertical_offset + (ds->m_unscaled_size.y - z_vertical_offset)) * ds->m_scale);
const int new_height = std::max(static_cast<int>(vertical_size * ds->m_scale), dRect.w);
const int new_width = std::max(static_cast<int>(horizontal_size * ds->m_scale), dRect.z);
const int height_diff = new_height - (ds->m_unscaled_size.y * ds->m_scale);
const int width_diff = new_width - (ds->m_unscaled_size.x * ds->m_scale);
// Size here should match whichever is biggest, since that's probably what's going to happen with it further down.
const int new_height = std::min(2048, std::max(t_size.y, static_cast<int>(vertical_size))) * ds->m_scale;
const int new_width = std::min(2048, std::max(t_size.x, static_cast<int>(horizontal_size))) * ds->m_scale;
if (GSTexture* tex = g_gs_device->CreateDepthStencil(new_width, new_height, GSTexture::Format::DepthStencil, true))
{
GSVector4 sRect = GSVector4(static_cast<float>(z_horizontal_offset) / static_cast<float>(ds->m_unscaled_size.x), static_cast<float>(z_vertical_offset) / static_cast<float>(ds->m_unscaled_size.y), 1.0f - (static_cast<float>(horizontal_offset - z_horizontal_offset) / static_cast<float>(ds->m_unscaled_size.x)), 1.0f - (static_cast<float>(vertical_offset - z_vertical_offset) / static_cast<float>(ds->m_unscaled_size.y)));
GSVector4 sRect = GSVector4(static_cast<float>(z_horizontal_offset) / static_cast<float>(ds->m_unscaled_size.x), static_cast<float>(z_vertical_offset) / static_cast<float>(ds->m_unscaled_size.y), 1.0f , 1.0f);
const bool restricted_copy = !(((next_ctx.ZBUF.ZBP == m_context->ZBUF.ZBP && next_ctx.FRAME.FBP == m_context->FRAME.FBP)) && !(IsPossibleChannelShuffle() && !IsPageCopy()));
if (!restricted_copy)
{
if (height_diff)
{
const int adjust = std::min(height_diff, (vertical_offset - z_vertical_offset));
sRect.w += static_cast<float>(adjust) / static_cast<float>(ds->m_unscaled_size.y);
dRect.w += adjust;
}
if (width_diff)
{
const int adjust = std::min(width_diff, (horizontal_offset - z_horizontal_offset));
sRect.z += static_cast<float>(adjust) / static_cast<float>(ds->m_unscaled_size.x);
dRect.z += adjust;
}
}
else
if (restricted_copy)
{
// m_r already has horizontal_offset (rt offset) applied)
dRect = GSVector4i(m_r.x * ds->m_scale, m_r.y * ds->m_scale, ((1 + m_r.z) * ds->m_scale), ((1 + m_r.w) * ds->m_scale));
@@ -3686,10 +3713,13 @@ void GSRendererHW::Draw()
GL_CACHE("HW: RT in RT Z copy on draw %d z_vert_offset %d", s_n, page_offset);
g_gs_device->StretchRect(ds->m_texture, sRect, tex, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
if (m_cached_ctx.TEST.ZTST > ZTST_ALWAYS || !dRect.rintersect(GSVector4i(GSVector4(m_r) * ds->m_scale)).eq(dRect))
{
g_gs_device->StretchRect(ds->m_texture, sRect, tex, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
}
g_texture_cache->SetTemporaryZ(tex);
g_texture_cache->SetTemporaryZInfo(ds->m_TEX0.TBP0, page_offset);
g_texture_cache->SetTemporaryZInfo(ds->m_TEX0.TBP0, page_offset, rt_page_offset);
t_size.y = std::max(static_cast<int>(new_height / ds->m_scale), t_size.y);
}
else
@@ -4328,7 +4358,10 @@ void GSRendererHW::Draw()
const GSLocalMemory::psm_t& z_psm = GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM];
const int vertical_offset = ((static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) / 32) / std::max(static_cast<int>(rt->m_TEX0.TBW), 1)) * frame_psm.pgs.y;
const int z_vertical_offset = ((static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32) / std::max(static_cast<int>(ds->m_TEX0.TBW), 1)) * z_psm.pgs.y;
const GSVector4i ds_rect = m_r - GSVector4i(vertical_offset - z_vertical_offset);
const int z_horizontal_offset = ((static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32) % std::max(rt->m_TEX0.TBW, 1U)) * z_psm.pgs.x;
const int horizontal_offset = ((static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) / 32) % std::max(static_cast<int>(rt->m_TEX0.TBW), 1)) * frame_psm.pgs.x;
const GSVector4i ds_rect = m_r - GSVector4i(horizontal_offset - z_horizontal_offset, vertical_offset - z_vertical_offset).xyxy();
ds->UpdateValidity(ds_rect, z_update && (can_update_size || (ds_rect.w <= (resolution.y * 2) && !m_texture_shuffle)));
ds->UpdateDrawn(ds_rect, z_update && (can_update_size || (ds_rect.w <= (resolution.y * 2) && !m_texture_shuffle)));
}
@@ -4437,7 +4470,7 @@ void GSRendererHW::Draw()
if (GSConfig.SaveTexture && src)
{
s = GetDrawDumpPath("%05d_f%05lld_itex_%s_%05x(%05x)_%s_%d%d_%02x_%02x_%02x_%02x.dds",
s_n, frame, (src->m_from_target ? "tgt" : "gs"), static_cast<int>(m_cached_ctx.TEX0.TBP0), (src->m_from_target ? src->m_from_target->m_TEX0.TBP0 : src->m_TEX0.TBP0), psm_str(m_cached_ctx.TEX0.PSM),
s_n, frame, (src->m_from_target ? "tgt" : "gs"), static_cast<int>(m_cached_ctx.TEX0.TBP0), (src->m_from_target ? src->m_from_target->m_TEX0.TBP0 : src->m_TEX0.TBP0), GSUtil::GetPSMName(m_cached_ctx.TEX0.PSM),
static_cast<int>(m_cached_ctx.CLAMP.WMS), static_cast<int>(m_cached_ctx.CLAMP.WMT),
static_cast<int>(m_cached_ctx.CLAMP.MINU), static_cast<int>(m_cached_ctx.CLAMP.MAXU),
static_cast<int>(m_cached_ctx.CLAMP.MINV), static_cast<int>(m_cached_ctx.CLAMP.MAXV));
@@ -4446,7 +4479,7 @@ void GSRendererHW::Draw()
if (src->m_palette)
{
s = GetDrawDumpPath("%05d_f%05lld_itpx_%05x_%s.dds", s_n, frame, m_cached_ctx.TEX0.CBP, psm_str(m_cached_ctx.TEX0.CPSM));
s = GetDrawDumpPath("%05d_f%05lld_itpx_%05x_%s.dds", s_n, frame, m_cached_ctx.TEX0.CBP, GSUtil::GetPSMName(m_cached_ctx.TEX0.CPSM));
src->m_palette->Save(s);
}
@@ -4454,7 +4487,7 @@ void GSRendererHW::Draw()
if (rt && GSConfig.SaveRT)
{
s = GetDrawDumpPath("%05d_f%05lld_rt0_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.FRAME.Block(), rt->m_TEX0.TBP0, psm_str(m_cached_ctx.FRAME.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rt0_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.FRAME.Block(), rt->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM));
if (rt->m_texture)
rt->m_texture->Save(s);
@@ -4462,7 +4495,7 @@ void GSRendererHW::Draw()
if (ds && GSConfig.SaveDepth)
{
s = GetDrawDumpPath("%05d_f%05lld_rz0_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.ZBUF.Block(), ds->m_TEX0.TBP0, psm_str(m_cached_ctx.ZBUF.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rz0_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.ZBUF.Block(), ds->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.ZBUF.PSM));
if (m_using_temp_z)
g_texture_cache->GetTemporaryZ()->Save(s);
@@ -4573,14 +4606,14 @@ void GSRendererHW::Draw()
{
const int get_next_ctx = m_env.PRIM.CTXT;
const GSDrawingContext& next_ctx = m_env.CTXT[get_next_ctx];
const int z_vertical_offset = ((static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32) / std::max(rt->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.y;
const int z_horizontal_offset = ((static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32) % std::max(rt->m_TEX0.TBW, 1U)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.x;
const int z_vertical_offset = ((static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32) / std::max(static_cast<int>(rt->m_TEX0.TBW), 1)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.y;
const int z_horizontal_offset = ((static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0) / 32) % std::max(static_cast<int>(rt->m_TEX0.TBW), 1)) * GSLocalMemory::m_psm[m_cached_ctx.ZBUF.PSM].pgs.x;
const int vertical_offset = ((static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) / 32) / std::max(static_cast<int>(rt->m_TEX0.TBW), 1)) * frame_psm.pgs.y;
const int horizontal_offset = ((static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) / 32) % std::max(static_cast<int>(rt->m_TEX0.TBW), 1)) * frame_psm.pgs.x;
if (was_written)
{
const GSVector4i ds_real_rect = real_rect - GSVector4i(vertical_offset - z_vertical_offset);
const GSVector4i ds_real_rect = real_rect - GSVector4i(horizontal_offset - z_horizontal_offset, vertical_offset - z_vertical_offset).xyxy();
ds->UpdateValidity(ds_real_rect, !z_masked && (can_update_size || (ds_real_rect.w <= (resolution.y * 2) && !m_texture_shuffle)));
}
@@ -4647,14 +4680,14 @@ void GSRendererHW::Draw()
if (rt && GSConfig.SaveRT && !m_last_rt)
{
s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.FRAME.Block(), rt->m_TEX0.TBP0, psm_str(m_cached_ctx.FRAME.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_(%05x)_%s.bmp", s_n, frame, m_cached_ctx.FRAME.Block(), rt->m_TEX0.TBP0, GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM));
rt->m_texture->Save(s);
}
if (ds && GSConfig.SaveDepth)
{
s = GetDrawDumpPath("%05d_f%05lld_rz1_%05x_%s.bmp", s_n, frame, m_cached_ctx.ZBUF.Block(), psm_str(m_cached_ctx.ZBUF.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rz1_%05x_%s.bmp", s_n, frame, m_cached_ctx.ZBUF.Block(), GSUtil::GetPSMName(m_cached_ctx.ZBUF.PSM));
ds->m_texture->Save(s);
}
@@ -6344,7 +6377,7 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
// 2/ Only keep aem when it is useful (avoid useless shader permutation)
if (m_conf.ps.shuffle)
{
const GIFRegTEXA& TEXA = m_draw_env->TEXA;
const GIFRegTEXA& TEXA = m_cached_ctx.TEXA;
// Force a 32 bits access (normally shuffle is done on 16 bits)
// m_ps_sel.tex_fmt = 0; // removed as an optimization
@@ -6398,7 +6431,7 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
}
else if (tex->m_target)
{
const GIFRegTEXA& TEXA = m_draw_env->TEXA;
const GIFRegTEXA& TEXA = m_cached_ctx.TEXA;
// Use an old target. AEM and index aren't resolved it must be done
// on the GPU
@@ -7235,13 +7268,13 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
const GSVector4i shuffle_rect = GSVector4i(m_vt.m_min.p.x, m_vt.m_min.p.y, m_vt.m_max.p.x, m_vt.m_max.p.y);
if (!rt->m_valid.rintersect(shuffle_rect).eq(rt->m_valid) || (m_cached_ctx.FRAME.FBMSK & 0xFFFC0000))
{
rt_new_alpha_max = std::max(static_cast<int>((std::max(m_draw_env->TEXA.TA1, m_draw_env->TEXA.TA0) & 0x80) + 127), rt_new_alpha_max) | fba_value;
rt_new_alpha_min = std::min(static_cast<int>(std::min(m_draw_env->TEXA.TA1, m_draw_env->TEXA.TA0) & 0x80), rt_new_alpha_min);
rt_new_alpha_max = std::max(static_cast<int>((std::max(m_cached_ctx.TEXA.TA1, m_cached_ctx.TEXA.TA0) & 0x80) + 127), rt_new_alpha_max) | fba_value;
rt_new_alpha_min = std::min(static_cast<int>(std::min(m_cached_ctx.TEXA.TA1, m_cached_ctx.TEXA.TA0) & 0x80), rt_new_alpha_min);
}
else
{
rt_new_alpha_max = (std::max(m_draw_env->TEXA.TA1, m_draw_env->TEXA.TA0) & 0x80) + 127 | fba_value;
rt_new_alpha_min = (std::min(m_draw_env->TEXA.TA1, m_draw_env->TEXA.TA0) & 0x80) | fba_value;
rt_new_alpha_max = (std::max(m_cached_ctx.TEXA.TA1, m_cached_ctx.TEXA.TA0) & 0x80) + 127 | fba_value;
rt_new_alpha_min = (std::min(m_cached_ctx.TEXA.TA1, m_cached_ctx.TEXA.TA0) & 0x80) | fba_value;
}
rt->m_alpha_range = true;
}
@@ -8156,7 +8189,7 @@ bool GSRendererHW::CanUseSwPrimRender(bool no_rt, bool no_ds, bool draw_sprite_t
return false;
}
const bool need_aem_color = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp <= 24 && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].pal == 0 && ((NeedsBlending() && m_context->ALPHA.C == 0) || IsDiscardingDstAlpha()) && m_draw_env->TEXA.AEM;
const bool need_aem_color = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp <= 24 && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].pal == 0 && ((NeedsBlending() && m_context->ALPHA.C == 0) || IsDiscardingDstAlpha()) && m_cached_ctx.TEXA.AEM;
const u32 color_mask = (m_vt.m_max.c > GSVector4i::zero()).mask();
const bool texture_function_color = m_cached_ctx.TEX0.TFX == TFX_DECAL || (color_mask & 0xFFF) || (m_cached_ctx.TEX0.TFX > TFX_DECAL && (color_mask & 0xF000));
const bool texture_function_alpha = m_cached_ctx.TEX0.TFX != TFX_MODULATE || (color_mask & 0xF000);
@@ -8336,8 +8369,8 @@ bool GSRendererHW::DetectDoubleHalfClear(bool& no_rt, bool& no_ds)
return false;
}
// Z and color must be constant and the same
if (m_vt.m_eq.rgba != 0xFFFF || !m_vt.m_eq.z)
// Z and color must be constant and the same and both are enabled.
if (m_vt.m_eq.rgba != 0xFFFF || !m_vt.m_eq.z || (no_ds != no_rt))
return false;
const u32 write_color = GetConstantDirectWriteMemClearColor();
@@ -8376,7 +8409,7 @@ bool GSRendererHW::DetectDoubleHalfClear(bool& no_rt, bool& no_ds)
!GSUtil::HasCompatibleBits(m_cached_ctx.FRAME.PSM & ~0x30, m_cached_ctx.ZBUF.PSM & ~0x30)) // Bit depth is not the same (i.e. 32bit + 16bit).
{
GL_INS("HW: DetectDoubleHalfClear(): Inconsistent FRAME [%s, %08x] and ZBUF [%s] formats, not using double-half clear.",
psm_str(m_cached_ctx.FRAME.PSM), m_cached_ctx.FRAME.FBMSK, psm_str(m_cached_ctx.ZBUF.PSM));
GSUtil::GetPSMName(m_cached_ctx.FRAME.PSM), m_cached_ctx.FRAME.FBMSK, GSUtil::GetPSMName(m_cached_ctx.ZBUF.PSM));
// Spiderman: Web of Shadows clears its depth buffer with 32-bit FRAME and 24-bit Z. So the upper 8 bits of half
// the depth buffer are not cleared, yay. We can't turn this into a 32-bit clear, because then it'll zero out
@@ -8416,7 +8449,7 @@ bool GSRendererHW::DetectDoubleHalfClear(bool& no_rt, bool& no_ds)
// bang up next to each other, or a double half clear. The two are really difficult to differentiate.
// Have to check both contexts, because God of War 2 likes to do this in-between setting TRXDIR, which
// causes a flush, and we don't have the next context backed up index set.
bool horizontal = false;
bool horizontal = std::abs(static_cast<int>(m_cached_ctx.FRAME.FBP) - static_cast<int>(m_cached_ctx.ZBUF.ZBP)) == (m_cached_ctx.FRAME.FBW >> 1);
const bool possible_next_clear = !m_env.PRIM.TME && !(m_env.SCANMSK.MSK & 2) && !m_env.CTXT[next_ctx].TEST.ATE && !m_env.CTXT[next_ctx].TEST.DATE &&
(!m_env.CTXT[next_ctx].TEST.ZTE || m_env.CTXT[next_ctx].TEST.ZTST == ZTST_ALWAYS);
@@ -8499,6 +8532,14 @@ bool GSRendererHW::DetectDoubleHalfClear(bool& no_rt, bool& no_ds)
else
{
const int height = m_r.height();
// We don't want to double half clear already full sized targets, making them double the size, this could be very bad.
// This gets triggered by Monster Lab which clears the Z and FRAME in one go, butted up against each other.
// It's highly unlikely that it will actually require a > 600 high framebuffer, but check with the display height first.
const int display_height = PCRTCDisplays.GetResolution().y;
if ((display_height != 0 && height >= (display_height - 1)) || height > 300)
return false;
m_r.w = ((half - base) / m_cached_ctx.FRAME.FBW) * frame_psm.pgs.y;
m_r.w += m_r.y + height;
}
@@ -8703,7 +8744,7 @@ bool GSRendererHW::TryGSMemClear(bool no_rt, bool preserve_rt, bool invalidate_r
void GSRendererHW::ClearGSLocalMemory(const GSOffset& off, const GSVector4i& r, u32 vert_color)
{
GL_INS("HW: ClearGSLocalMemory(): %08X %d,%d => %d,%d @ BP %x BW %u %s", vert_color, r.x, r.y, r.z, r.w, off.bp(),
off.bw(), psm_str(off.psm()));
off.bw(), GSUtil::GetPSMName(off.psm()));
const u32 psm = (off.psm() == PSMCT32 && m_cached_ctx.FRAME.FBMSK == 0xFF000000u) ? PSMCT24 : off.psm();
const int format = GSLocalMemory::m_psm[psm].fmt;

View File

@@ -140,6 +140,7 @@ private:
struct HWCachedCtx
{
GIFRegTEX0 TEX0;
GIFRegTEXA TEXA;
GIFRegCLAMP CLAMP;
GIFRegTEST TEST;
GIFRegFRAME FRAME;

View File

@@ -627,7 +627,7 @@ void GSTextureCache::DirtyRectByPage(u32 sbp, u32 spsm, u32 sbw, Target* t, GSVe
const u32 start_bp = GSLocalMemory::GetStartBlockAddress(sbp, sbw, spsm, src_r);
const u32 end_bp = GSLocalMemory::GetEndBlockAddress(sbp, sbw, spsm, src_r);
GL_INS("TC: Invalidating BP: 0x%x (%x -> %x) BW: %d PSM %s Target BP: 0x%x BW %x PSM %s", sbp, start_bp, end_bp, sbw, psm_str(spsm), t->m_TEX0.TBP0, t->m_TEX0.TBW, psm_str(t->m_TEX0.PSM));
GL_INS("TC: Invalidating BP: 0x%x (%x -> %x) BW: %d PSM %s Target BP: 0x%x BW %x PSM %s", sbp, start_bp, end_bp, sbw, GSUtil::GetPSMName(spsm), t->m_TEX0.TBP0, t->m_TEX0.TBW, GSUtil::GetPSMName(t->m_TEX0.PSM));
// If the whole thing is covered, just invalidate the whole rect.
if (start_bp <= t->m_TEX0.TBP0 && end_bp >= t->UnwrappedEndBlock())
@@ -1047,7 +1047,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, c
}
GL_CACHE("TC: Lookup Depth Source <%d,%d => %d,%d> (0x%x, %s, BW: %u, CBP: 0x%x, TW: %d, TH: %d)", r.x, r.y, r.z,
r.w, TEX0.TBP0, psm_str(TEX0.PSM), TEX0.TBW, TEX0.CBP, 1 << TEX0.TW, 1 << TEX0.TH);
r.w, TEX0.TBP0, GSUtil::GetPSMName(TEX0.PSM), TEX0.TBW, TEX0.CBP, 1 << TEX0.TW, 1 << TEX0.TH);
const SourceRegion region = SourceRegion::Create(TEX0, CLAMP);
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
@@ -1058,7 +1058,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, c
region.IsFixedTEX0(TEX0), m_src.m_map[TEX0.TBP0 >> 5]);
if (src)
{
GL_CACHE("TC: src hit: (0x%x, %s)", TEX0.TBP0, psm_str(TEX0.PSM));
GL_CACHE("TC: src hit: (0x%x, %s)", TEX0.TBP0, GSUtil::GetPSMName(TEX0.PSM));
src->Update(r);
return src;
}
@@ -1180,7 +1180,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, c
if (dst)
{
GL_CACHE("TC: depth: dst %s hit: (0x%x, %s)", to_string(dst->m_type),
TEX0.TBP0, psm_str(psm));
TEX0.TBP0, GSUtil::GetPSMName(psm));
// Create a shared texture source
src = new Source(TEX0, TEXA);
@@ -1232,7 +1232,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, c
GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const GSVector2i* lod, const bool possible_shuffle, const bool linear, const GIFRegFRAME& frame, bool req_color, bool req_alpha)
{
GL_CACHE("TC: Lookup Source <%d,%d => %d,%d> (0x%x, %s, BW: %u, CBP: 0x%x, TW: %d, TH: %d)", r.x, r.y, r.z, r.w, TEX0.TBP0, psm_str(TEX0.PSM), TEX0.TBW, TEX0.CBP, 1 << TEX0.TW, 1 << TEX0.TH);
GL_CACHE("TC: Lookup Source <%d,%d => %d,%d> (0x%x, %s, BW: %u, CBP: 0x%x, TW: %d, TH: %d)", r.x, r.y, r.z, r.w, TEX0.TBP0, GSUtil::GetPSMName(TEX0.PSM), TEX0.TBW, TEX0.CBP, 1 << TEX0.TW, 1 << TEX0.TH);
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
//const GSLocalMemory::psm_t& cpsm = psm.pal > 0 ? GSLocalMemory::m_psm[TEX0.CPSM] : psm;
@@ -1792,7 +1792,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
//rect = rect.rintersect(t->m_valid);
if (rect.rintersect(t->m_valid).rempty())
if (rect.rintersect(t->m_valid - GSVector4i(0, 1).xyxy()).rempty())
continue;
if (!t->m_dirty.empty())
@@ -2028,11 +2028,11 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
x_offset,
y_offset,
TEX0.TBP0,
psm_str(TEX0.PSM));
GSUtil::GetPSMName(TEX0.PSM));
}
else
{
GL_CACHE("TC: src miss (0x%x, 0x%x, %s)", TEX0.TBP0, psm_s.pal > 0 ? TEX0.CBP : 0, psm_str(TEX0.PSM));
GL_CACHE("TC: src miss (0x%x, 0x%x, %s)", TEX0.TBP0, psm_s.pal > 0 ? TEX0.CBP : 0, GSUtil::GetPSMName(TEX0.PSM));
}
#endif
// This is for the condition where the target doesn't exist on a shuffle and it needs to load from memory.
@@ -2097,7 +2097,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
{
GL_CACHE("TC: src hit: (0x%x, 0x%x, %s)",
TEX0.TBP0, psm_s.pal > 0 ? TEX0.CBP : 0,
psm_str(TEX0.PSM));
GSUtil::GetPSMName(TEX0.PSM));
// If it's an old source made from target make sure it isn't a palette,
// alphas need to be used from the palette then.
@@ -2371,7 +2371,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
}
else if (!(src && src->m_from_target == t))
{
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s due to change in target", t->m_TEX0.TBP0, t->m_TEX0.TBW, psm_str(t->m_TEX0.PSM));
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s due to change in target", t->m_TEX0.TBP0, t->m_TEX0.TBW, GSUtil::GetPSMName(t->m_TEX0.PSM));
InvalidateSourcesFromTarget(t);
i = list.erase(i);
delete t;
@@ -2382,6 +2382,15 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
// Probably pointing to half way through the target
else if (!min_rect.rempty() && GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets)
{
// Some games misuse the scissor so it ends up valid 1 pixel over, which causes hell for us. So check if it still overlaps without the extra pixel.
const GSVector4i adjusted_valid = GSVector4i(t->m_valid.x, t->m_valid.y, std::min(t->m_valid.z, static_cast<int>(t->m_TEX0.TBW) * 64), t->m_valid.w - 1);
const u32 adjusted_endblock = GSLocalMemory::GetEndBlockAddress(t->m_TEX0.TBP0, t->m_TEX0.TBW, t->m_TEX0.PSM, adjusted_valid);
if (adjusted_endblock <= bp)
{
i++;
continue;
}
const u32 widthpage_offset = (std::abs(static_cast<int>(bp - t->m_TEX0.TBP0)) >> 5) % std::max(t->m_TEX0.TBW, 1U);
const bool is_aligned_ok = widthpage_offset == 0 || ((min_rect.width() <= static_cast<int>((t->m_TEX0.TBW - widthpage_offset) * 64) && (t->m_TEX0.TBW == TEX0.TBW || TEX0.TBW == 1)) && bp >= t->m_TEX0.TBP0);
const bool no_target_or_newer = (!dst || ((GSState::s_n - dst->m_last_draw) < (GSState::s_n - t->m_last_draw)));
@@ -2389,10 +2398,11 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
const bool ds_offset = !ds || offset != 0;
const bool is_double_buffer = TEX0.TBP0 == ((((t->m_end_block + 1) - t->m_TEX0.TBP0) / 2) + t->m_TEX0.TBP0);
const bool source_match = src && src->m_TEX0.TBP0 == bp && src->m_TEX0.TBW == TEX0.TBW && src->m_from_target && src->m_from_target == t;
const bool was_used_last_draw = t->m_last_draw == (GSState::s_n - 1);
// if it's a shuffle, some games tend to offset back by a page, such as Tomb Raider, for no disernable reason, but it then causes problems.
// This can also happen horizontally (Catwoman moves everything one page left with shuffles), but this is too messy to deal with right now.
const bool overlaps = t->Overlaps(bp, TEX0.TBW, TEX0.PSM, min_rect) || (is_shuffle && src && GSLocalMemory::m_psm[src->m_TEX0.PSM].bpp == 8 && t->Overlaps(bp, TEX0.TBW, TEX0.PSM, min_rect + GSVector4i(0, 0, 0, 32)));
if (source_match || (no_target_or_newer && is_aligned_ok && width_match && overlaps && (is_shuffle || ds_offset || is_double_buffer)))
if (source_match || (no_target_or_newer && is_aligned_ok && width_match && overlaps && (is_shuffle || ds_offset || is_double_buffer || was_used_last_draw)))
{
const GSLocalMemory::psm_t& s_psm = GSLocalMemory::m_psm[TEX0.PSM];
@@ -2400,15 +2410,16 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
// 896 is just 448 * 2,just gives the buffer chance to be larger than normal, in case they do something like 640x640, or something ridiculous.
if (!is_shuffle && (ds && offset == 0 && (t->m_valid.w >= 896) && ((((t->m_end_block + 1) - t->m_TEX0.TBP0) >> 1) + t->m_TEX0.TBP0) <= bp))
{
t->m_valid.w /= 2;
t->m_end_block = ((((t->m_end_block + 1) - t->m_TEX0.TBP0) >> 1) + t->m_TEX0.TBP0) - 1;
continue;
u32 offset = (((bp - t->m_TEX0.TBP0) >> 5) / std::max(t->m_TEX0.TBW, 1U)) * s_psm.pgs.y;
dst = CreateTarget(TEX0, GSVector2i(t->m_valid.z, t->m_valid.w - offset), GSVector2i(t->m_valid.z, t->m_valid.w - offset), scale, type, true, fbmask, false, false, preserve_rgb || preserve_alpha, GSVector4i::zero(), src);
dst->m_32_bits_fmt |= (psm_s.bpp != 16);
break;
}
// I know what you're thinking, and I hate the guy who wrote it too (me). Project Snowblind, Tomb Raider etc decide to offset where they're drawing using a channel shuffle, and this gets messy, so best just to kill the old target.
if (is_shuffle && src && src->m_TEX0.PSM == PSMT8 && GSRendererHW::GetInstance()->m_context->FRAME.FBW == 1 && t->m_last_draw != (GSState::s_n - 1) && src->m_from_target && (src->m_from_target->m_TEX0.TBP0 == src->m_TEX0.TBP0 || (((src->m_TEX0.TBP0 - src->m_from_target->m_TEX0.TBP0) >> 5) % std::max(src->m_from_target->m_TEX0.TBW, 1U) == 0)) && widthpage_offset && src->m_from_target != t)
{
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s offset overwrite shuffle", t->m_TEX0.TBP0, t->m_TEX0.TBW, psm_str(t->m_TEX0.PSM));
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s offset overwrite shuffle", t->m_TEX0.TBP0, t->m_TEX0.TBW, GSUtil::GetPSMName(t->m_TEX0.PSM));
InvalidateSourcesFromTarget(t);
i = list.erase(i);
delete t;
@@ -2419,7 +2430,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
if (!is_shuffle && (!GSUtil::HasSameSwizzleBits(t->m_TEX0.PSM, TEX0.PSM) ||
((widthpage_offset % std::max(t->m_TEX0.TBW, 1U)) != 0 && ((widthpage_offset + (min_rect.width() + (s_psm.pgs.x - 1)) / s_psm.pgs.x)) > t->m_TEX0.TBW)))
{
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s due to change in target", t->m_TEX0.TBP0, t->m_TEX0.TBW, psm_str(t->m_TEX0.PSM));
GL_INS("TC: Deleting RT BP 0x%x BW %d PSM %s due to change in target", t->m_TEX0.TBP0, t->m_TEX0.TBW, GSUtil::GetPSMName(t->m_TEX0.PSM));
InvalidateSourcesFromTarget(t);
i = list.erase(i);
delete t;
@@ -2439,7 +2450,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
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, psm_str(t->m_TEX0.PSM));
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));
InvalidateSourcesFromTarget(t);
i = list.erase(i);
delete t;
@@ -2520,7 +2531,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
}
}
dst = t;
GL_CACHE("TC: Lookup Frame %dx%d, perfect hit: (0x%x -> 0x%x %s)", size.x, size.y, bp, t->m_end_block, psm_str(TEX0.PSM));
GL_CACHE("TC: Lookup Frame %dx%d, perfect hit: (0x%x -> 0x%x %s)", size.x, size.y, bp, t->m_end_block, GSUtil::GetPSMName(TEX0.PSM));
if (size.x > 0 || size.y > 0)
ScaleTargetForDisplay(dst, TEX0, size.x, size.y);
@@ -2554,7 +2565,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
}
dst = t;
GL_CACHE("TC: Lookup Frame %dx%d, inclusive hit: (0x%x, took 0x%x -> 0x%x %s)", size.x, size.y, bp, t->m_TEX0.TBP0, t->m_end_block, psm_str(TEX0.PSM));
GL_CACHE("TC: Lookup Frame %dx%d, inclusive hit: (0x%x, took 0x%x -> 0x%x %s)", size.x, size.y, bp, t->m_TEX0.TBP0, t->m_end_block, GSUtil::GetPSMName(TEX0.PSM));
if (size.x > 0 || size.y > 0)
ScaleTargetForDisplay(dst, TEX0, size.x, size.y);
@@ -2586,7 +2597,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
}
dst = t;
GL_CACHE("TC: Lookup Frame %dx%d, empty hit: (0x%x -> 0x%x %s)", size.x, size.y, bp, t->m_end_block, psm_str(TEX0.PSM));
GL_CACHE("TC: Lookup Frame %dx%d, empty hit: (0x%x -> 0x%x %s)", size.x, size.y, bp, t->m_end_block, GSUtil::GetPSMName(TEX0.PSM));
break;
}
}
@@ -2598,13 +2609,13 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
if (type == DepthStencil)
{
GL_CACHE("TC: Lookup Target(Depth) %dx%d (0x%x, BW:%u, %s) hit (0x%x, BW:%d, %s)", size.x, size.y, bp,
TEX0.TBW, psm_str(TEX0.PSM), dst->m_TEX0.TBP0, dst->m_TEX0.TBW, psm_str(dst->m_TEX0.PSM));
TEX0.TBW, GSUtil::GetPSMName(TEX0.PSM), dst->m_TEX0.TBP0, dst->m_TEX0.TBW, GSUtil::GetPSMName(dst->m_TEX0.PSM));
}
else
{
GL_CACHE("TC: Lookup %s(Color) %dx%d (0x%x, BW:%u, FBMSK %08x, %s) hit (0x%x, BW:%d, %s)",
is_frame ? "Frame" : "Target", size.x, size.y, bp, TEX0.TBW, fbmask, psm_str(TEX0.PSM),
dst->m_TEX0.TBP0, dst->m_TEX0.TBW, psm_str(dst->m_TEX0.PSM));
is_frame ? "Frame" : "Target", size.x, size.y, bp, TEX0.TBW, fbmask, GSUtil::GetPSMName(TEX0.PSM),
dst->m_TEX0.TBP0, dst->m_TEX0.TBW, GSUtil::GetPSMName(dst->m_TEX0.PSM));
}
if (dst->m_scale != scale && (!preserve_scale || is_shuffle || !dst->m_downscaled || TEX0.TBW != dst->m_TEX0.TBW))
@@ -3051,14 +3062,14 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
if (type == DepthStencil)
{
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, psm_str(TEX0.PSM), psm_str(dst_match->m_TEX0.PSM));
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);
}
else
{
GL_CACHE("TC: Lookup Target(Color) %dx%d, hit Depth (0x%x, TBW %d, FBMSK %0x, %s was %s)", new_size.x,
new_size.y, bp, TEX0.TBW, fbmask, psm_str(TEX0.PSM), psm_str(dst_match->m_TEX0.PSM));
new_size.y, bp, TEX0.TBW, fbmask, GSUtil::GetPSMName(TEX0.PSM), GSUtil::GetPSMName(dst_match->m_TEX0.PSM));
shader = (fmt_16_bits) ? ShaderConvert::FLOAT16_TO_RGB5A1 : ShaderConvert::FLOAT32_TO_RGBA8;
}
@@ -3132,12 +3143,12 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(GIFRegTEX0 TEX0, const GSVe
if (type == DepthStencil)
{
GL_CACHE("TC: Lookup Target(Depth) %dx%d, miss (0x%x, TBW %d, %s) draw %d", size.x, size.y, TEX0.TBP0,
TEX0.TBW, psm_str(TEX0.PSM), g_gs_renderer->s_n);
TEX0.TBW, GSUtil::GetPSMName(TEX0.PSM), g_gs_renderer->s_n);
}
else
{
GL_CACHE("TC: Lookup %s(Color) %dx%d FBMSK %08x, miss (0x%x, TBW %d, %s) draw %d", is_frame ? "Frame" : "Target",
size.x, size.y, fbmask, TEX0.TBP0, TEX0.TBW, psm_str(TEX0.PSM), g_gs_renderer->s_n);
size.x, size.y, fbmask, TEX0.TBP0, TEX0.TBW, GSUtil::GetPSMName(TEX0.PSM), g_gs_renderer->s_n);
}
// Avoid making garbage targets (usually PCRTC).
if (GSVector4i::loadh(size).rempty())
@@ -3404,7 +3415,7 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
Target* t = *j;
if (dst != t && t->m_TEX0.PSM == dst->m_TEX0.PSM && t->Overlaps(dst->m_TEX0.TBP0, dst->m_TEX0.TBW, dst->m_TEX0.PSM, dst_valid) &&
static_cast<int>(((t->m_TEX0.TBP0 - dst->m_TEX0.TBP0) / 32) % std::max(dst->m_TEX0.TBW, 1U)) <= std::max(0, static_cast<int>(dst->m_TEX0.TBW - t->m_TEX0.TBW)))
((std::abs(static_cast<int>(t->m_TEX0.TBP0 - dst->m_TEX0.TBP0)) >> 5) % std::max(static_cast<int>(dst->m_TEX0.TBW), 1)) <= std::max(0, static_cast<int>(dst->m_TEX0.TBW - t->m_TEX0.TBW)))
{
const u32 buffer_width = std::max(1U, dst->m_TEX0.TBW);
@@ -3427,7 +3438,7 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
}
// If the two targets are misaligned, it's likely a relocation, so we can just kill the old target.
// Kill targets that are overlapping new targets, but ignore the copy if the old target is dirty because we favour GS memory.
if (((((t->m_TEX0.TBP0 - dst->m_TEX0.TBP0) >> 5) % buffer_width) != 0) && !t->m_dirty.empty())
if (((std::abs(static_cast<int>(t->m_TEX0.TBP0 - dst->m_TEX0.TBP0) >> 5) % buffer_width) != 0) && !t->m_dirty.empty())
{
InvalidateSourcesFromTarget(t);
i = list.erase(j);
@@ -3441,6 +3452,23 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
{
GSVector4i new_valid = t->m_valid;
new_valid.w /= 2;
if (preserve_target && t->m_scale == dst->m_scale && dst->m_type == t->m_type && dst->m_dirty.empty() && !t->m_drawn_since_read.rintersect(new_valid).eq(t->m_drawn_since_read))
{
// Clamp the copy inside the source and destination.
const GSVector4i copy_rect = GSVector4i(GSVector4((new_valid + GSVector4i(0, new_valid.w).xyxy()).rintersect(t->m_drawn_since_read).rintersect(GSVector4i(0, 0, dst->m_unscaled_size.x, new_valid.w + dst->m_unscaled_size.y))) * dst->m_scale);
// Copy over the double buffer data, in case we need it.
// Clear the dirty first
t->Update();
dst->m_valid_rgb = t->m_valid_rgb;
dst->m_valid_alpha_low = t->m_valid_alpha_low;
dst->m_valid_alpha_high = t->m_valid_alpha_high;
dst->m_alpha_max = t->m_alpha_max;
dst->m_alpha_min = t->m_alpha_min;
dst->m_rt_alpha_scale = t->m_rt_alpha_scale;
g_gs_device->CopyRect(t->m_texture, dst->m_texture, copy_rect, 0, 0);
}
GL_INS("TC: RT resize buffer for FBP 0x%x, %dx%d => %d,%d", t->m_TEX0.TBP0, t->m_valid.width(), t->m_valid.height(), new_valid.width(), new_valid.height());
t->ResizeValidity(new_valid);
return hw_clear.value_or(false);
@@ -3850,6 +3878,9 @@ void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb,
{
const GSVector4i right(old_width, 0, preload_width, needed_height);
const GSVector4i bottom(0, old_height, old_width, needed_height);
t->UpdateValidity(right.rintersect(bottom));
AddDirtyRectTarget(t, right, t->m_TEX0.PSM, t->m_TEX0.TBW, rgba);
AddDirtyRectTarget(t, bottom, t->m_TEX0.PSM, t->m_TEX0.TBW, rgba);
}
@@ -3858,6 +3889,9 @@ void GSTextureCache::ScaleTargetForDisplay(Target* t, const GIFRegTEX0& dispfb,
const GSVector4i newrect = GSVector4i((old_height < new_height) ? 0 : old_width,
(old_width < preload_width) ? 0 : old_height,
preload_width, needed_height);
t->UpdateValidity(newrect);
AddDirtyRectTarget(t, newrect, t->m_TEX0.PSM, t->m_TEX0.TBW, rgba);
}
@@ -3913,8 +3947,8 @@ bool GSTextureCache::CopyRGBFromDepthToColor(Target* dst, Target* depth_src)
{
GL_CACHE("TC: Copy RGB from %dx%d %s[%x, %s] to %dx%d %s[%x, %s]", depth_src->GetUnscaledWidth(),
depth_src->GetUnscaledHeight(), to_string(depth_src->m_type), depth_src->m_TEX0.TBP0,
psm_str(depth_src->m_TEX0.PSM), dst->GetUnscaledWidth(), dst->GetUnscaledHeight(), to_string(dst->m_type),
dst->m_TEX0.TBP0, psm_str(dst->m_TEX0.PSM));
GSUtil::GetPSMName(depth_src->m_TEX0.PSM), dst->GetUnscaledWidth(), dst->GetUnscaledHeight(), to_string(dst->m_type),
dst->m_TEX0.TBP0, GSUtil::GetPSMName(dst->m_TEX0.PSM));
// The depth target might be larger (Driv3r).
const GSVector2i new_size = dst->GetUnscaledSize().max(GSVector2i(depth_src->m_valid.z, depth_src->m_valid.w));
@@ -3945,7 +3979,7 @@ bool GSTextureCache::CopyRGBFromDepthToColor(Target* dst, Target* depth_src)
if ((dr.rgba._u32 &= ~0x7) == 0)
{
GL_CACHE("TC: Remove dirty rect (%d,%d=>%d,%d) from %s[%x, %s] due to incoming depth.", drc.left,
drc.top, drc.right, drc.bottom, to_string(dst->m_type), dst->m_TEX0.TBP0, psm_str(dst->m_TEX0.PSM));
drc.top, drc.right, drc.bottom, to_string(dst->m_type), dst->m_TEX0.TBP0, GSUtil::GetPSMName(dst->m_TEX0.PSM));
dst->m_dirty.erase(dst->m_dirty.begin() + i);
}
}
@@ -4062,13 +4096,13 @@ bool GSTextureCache::PrepareDownloadTexture(u32 width, u32 height, GSTexture::Fo
++j;
}
GL_CACHE("TC: InvalidateContainedTargets: Remove Target %s[%x, %s]", to_string(type), t->m_TEX0.TBP0, psm_str(t->m_TEX0.PSM));
GL_CACHE("TC: InvalidateContainedTargets: Remove Target %s[%x, %s]", to_string(type), t->m_TEX0.TBP0, GSUtil::GetPSMName(t->m_TEX0.PSM));
i = list.erase(i);
delete t;
continue;
}
GL_CACHE("TC: InvalidateContainedTargets: Clear RGB valid on %s[%x, %s]", to_string(type), t->m_TEX0.TBP0, psm_str(t->m_TEX0.PSM));
GL_CACHE("TC: InvalidateContainedTargets: Clear RGB valid on %s[%x, %s]", to_string(type), t->m_TEX0.TBP0, GSUtil::GetPSMName(t->m_TEX0.PSM));
++i;
}
}
@@ -4152,13 +4186,13 @@ void GSTextureCache::InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 wr
++j;
}
GL_CACHE("TC: InvalidateContainedTargets: Remove Target %s[%x, %s]", to_string(type), t->m_TEX0.TBP0, psm_str(t->m_TEX0.PSM));
GL_CACHE("TC: InvalidateContainedTargets: Remove Target %s[%x, %s]", to_string(type), t->m_TEX0.TBP0, GSUtil::GetPSMName(t->m_TEX0.PSM));
i = list.erase(i);
delete t;
continue;
}
GL_CACHE("TC: InvalidateContainedTargets: Clear RGB valid on %s[%x, %s]", to_string(type), t->m_TEX0.TBP0, psm_str(t->m_TEX0.PSM));
GL_CACHE("TC: InvalidateContainedTargets: Clear RGB valid on %s[%x, %s]", to_string(type), t->m_TEX0.TBP0, GSUtil::GetPSMName(t->m_TEX0.PSM));
++i;
}
}
@@ -4446,7 +4480,7 @@ void GSTextureCache::InvalidateLocalMem(const GSOffset& off, const GSVector4i& r
GL_CACHE("TC: InvalidateLocalMem off(0x%x, %u, %s) r(%d, %d => %d, %d)",
bp,
bw,
psm_str(psm),
GSUtil::GetPSMName(psm),
r.x,
r.y,
r.z,
@@ -4784,7 +4818,7 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u
const GSLocalMemory::psm_t& dpsm_s = GSLocalMemory::m_psm[DPSM];
if (GSLocalMemory::m_psm[SPSM].bpp != GSLocalMemory::m_psm[DPSM].bpp || ((spsm_s.pal + dpsm_s.pal) != 0 && !alpha_only))
{
GL_CACHE("TC: Skipping HW move from 0x%X to 0x%X with SPSM=%s DPSM=%s", SBP, DBP, psm_str(SPSM), psm_str(DPSM));
GL_CACHE("TC: Skipping HW move from 0x%X to 0x%X with SPSM=%s DPSM=%s", SBP, DBP, GSUtil::GetPSMName(SPSM), GSUtil::GetPSMName(DPSM));
return false;
}
@@ -4961,7 +4995,7 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u
if ((scaled_dx + scaled_w) > dst->m_texture->GetWidth() || (scaled_dy + scaled_h) > dst->m_texture->GetHeight())
return false;
GL_CACHE("TC: HW Move after draw %d 0x%x[BW:%u PSM:%s] to 0x%x[BW:%u PSM:%s] <%d,%d->%d,%d> -> <%d,%d->%d,%d>", GSState::s_n, SBP, SBW,
psm_str(SPSM), DBP, DBW, psm_str(DPSM), sx, sy, sx + w, sy + h, dx, dy, dx + w, dy + h);
GSUtil::GetPSMName(SPSM), DBP, DBW, GSUtil::GetPSMName(DPSM), sx, sy, sx + w, sy + h, dx, dy, dx + w, dy + h);
const bool cover_whole_target = dst->m_type == RenderTarget && GSVector4i(dx, dy, dx + w, dy + h).rintersect(dst->m_valid).eq(dst->m_valid);
if (!cover_whole_target)
@@ -5759,12 +5793,12 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
if (psm.pal > 0)
{
src->m_texture->SetDebugName(TinyString::from_format("Offset {},{} from 0x{:X} {} CBP 0x{:X}", x_offset, y_offset,
static_cast<u32>(TEX0.TBP0), psm_str(TEX0.PSM), static_cast<u32>(TEX0.CBP)));
static_cast<u32>(TEX0.TBP0), GSUtil::GetPSMName(TEX0.PSM), static_cast<u32>(TEX0.CBP)));
}
else
{
src->m_texture->SetDebugName(TinyString::from_format("Offset {},{} from 0x{:X} {} ", x_offset, y_offset,
static_cast<u32>(TEX0.TBP0), psm_str(TEX0.PSM), static_cast<u32>(TEX0.CBP)));
static_cast<u32>(TEX0.TBP0), GSUtil::GetPSMName(TEX0.PSM), static_cast<u32>(TEX0.CBP)));
}
}
#endif
@@ -6004,7 +6038,7 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
if (GSConfig.UseDebugDevice)
{
src->m_texture->SetDebugName(TinyString::from_format("{}x{} copy of 0x{:X} {}", new_size.x, new_size.y,
static_cast<u32>(TEX0.TBP0), psm_str(TEX0.PSM)));
static_cast<u32>(TEX0.TBP0), GSUtil::GetPSMName(TEX0.PSM)));
}
#endif
}
@@ -6052,12 +6086,12 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
if (psm.pal > 0)
{
src->m_texture->SetDebugName(TinyString::from_format("Reinterpret 0x{:X} from {} to {} CBP 0x{:X}",
static_cast<u32>(TEX0.TBP0), psm_str(dst->m_TEX0.PSM), psm_str(TEX0.PSM), static_cast<u32>(TEX0.CBP)));
static_cast<u32>(TEX0.TBP0), GSUtil::GetPSMName(dst->m_TEX0.PSM), GSUtil::GetPSMName(TEX0.PSM), static_cast<u32>(TEX0.CBP)));
}
else
{
src->m_texture->SetDebugName(TinyString::from_format("Reinterpret 0x{:X} from {} to {}",
static_cast<u32>(TEX0.TBP0), psm_str(dst->m_TEX0.PSM), psm_str(TEX0.PSM)));
static_cast<u32>(TEX0.TBP0), GSUtil::GetPSMName(dst->m_TEX0.PSM), GSUtil::GetPSMName(TEX0.PSM)));
}
}
#endif
@@ -6154,13 +6188,13 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
if (psm.pal > 0)
{
src->m_texture->SetDebugName(TinyString::from_format("{}x{} {} @ 0x{:X} TBW={} CBP=0x{:X}",
tw, th, psm_str(TEX0.PSM), static_cast<u32>(TEX0.TBP0), static_cast<u32>(TEX0.TBW),
tw, th, GSUtil::GetPSMName(TEX0.PSM), static_cast<u32>(TEX0.TBP0), static_cast<u32>(TEX0.TBW),
static_cast<u32>(TEX0.CBP)));
}
else
{
src->m_texture->SetDebugName(TinyString::from_format("{}x{} {} @ 0x{:X} TBW={}",
tw, th, psm_str(TEX0.PSM), static_cast<u32>(TEX0.TBP0), static_cast<u32>(TEX0.TBW)));
tw, th, GSUtil::GetPSMName(TEX0.PSM), static_cast<u32>(TEX0.TBP0), static_cast<u32>(TEX0.TBW)));
}
}
#endif
@@ -6858,7 +6892,7 @@ void GSTextureCache::Read(Target* t, const GSVector4i& r)
const u32 write_mask = (t->m_valid_rgb ? 0x00FFFFFFu : 0) | (t->m_valid_alpha_low ? 0x0F000000u : 0) | (t->m_valid_alpha_high ? 0xF0000000u : 0);
if (write_mask == 0)
{
DbgCon.Warning("Not reading back target %x PSM %s due to no write mask", TEX0.TBP0, psm_str(TEX0.PSM));
DbgCon.Warning("Not reading back target %x PSM %s due to no write mask", TEX0.TBP0, GSUtil::GetPSMName(TEX0.PSM));
return;
}
@@ -7759,7 +7793,7 @@ void GSTextureCache::Target::UpdateTextureDebugName()
if (GSConfig.UseDebugDevice)
{
m_texture->SetDebugName(SmallString::from_format("{} 0x{:X} {} BW={} {}x{}",
m_type ? "DS" : "RT", static_cast<u32>(m_TEX0.TBP0), psm_str(m_TEX0.PSM), static_cast<u32>(m_TEX0.TBW),
m_type ? "DS" : "RT", static_cast<u32>(m_TEX0.TBP0), GSUtil::GetPSMName(m_TEX0.PSM), static_cast<u32>(m_TEX0.TBW),
m_unscaled_size.x, m_unscaled_size.y));
}
#endif
@@ -7813,7 +7847,7 @@ void GSTextureCache::SourceMap::RemoveAt(Source* s)
m_surfaces.erase(s);
GL_CACHE("TC: Remove Src Texture: 0x%x TBW %u PSM %s",
s->m_TEX0.TBP0, s->m_TEX0.TBW, psm_str(s->m_TEX0.PSM));
s->m_TEX0.TBP0, s->m_TEX0.TBW, GSUtil::GetPSMName(s->m_TEX0.PSM));
s->m_pages.loopPages([this, s](u32 page) {
m_map[page].EraseIndex(s->m_erase_it[page]);
@@ -8030,14 +8064,14 @@ GSTextureCache::SurfaceOffset GSTextureCache::ComputeSurfaceOffset(const Surface
if (so.is_valid)
{
GL_CACHE("TC: ComputeSurfaceOffset - Cached HIT element (size %d), [B] BW %d, PSM %s, BP 0x%x (END 0x%x) + OFF <%d,%d => %d,%d> ---> [A] BP 0x%x (END: 0x%x).",
m_surface_offset_cache.size(), b_el.bw, psm_str(b_el.psm), b_el.bp, b_bp_end,
m_surface_offset_cache.size(), b_el.bw, GSUtil::GetPSMName(b_el.psm), b_el.bp, b_bp_end,
so.b2a_offset.x, so.b2a_offset.y, so.b2a_offset.z, so.b2a_offset.w,
a_el.bp, a_bp_end);
}
else
{
GL_CACHE("TC: ComputeSurfaceOffset - Cached MISS element (size %d), [B] BW %d, PSM %s, BP 0x%x (END 0x%x) -/-> [A] BP 0x%x (END: 0x%x).",
m_surface_offset_cache.size(), b_el.bw, psm_str(b_el.psm), b_el.bp, b_bp_end,
m_surface_offset_cache.size(), b_el.bw, GSUtil::GetPSMName(b_el.psm), b_el.bp, b_bp_end,
a_el.bp, a_bp_end);
}
return so;
@@ -8057,10 +8091,11 @@ GSTextureCache::TempZAddress GSTextureCache::GetTemporaryZInfo()
return m_temporary_z_info;
}
void GSTextureCache::SetTemporaryZInfo(u32 address, u32 offset)
void GSTextureCache::SetTemporaryZInfo(u32 address, u32 offset, u32 rt_offset)
{
m_temporary_z_info.ZBP = address;
m_temporary_z_info.offset = offset;
m_temporary_z_info.rt_offset = rt_offset;
m_temporary_z_info.rect_since = GSVector4i::zero();
}
void GSTextureCache::SetTemporaryZInfo(TempZAddress address_info)

View File

@@ -213,6 +213,7 @@ public:
{
u32 ZBP;
int offset;
int rt_offset;
GSVector4i rect_since;
};
@@ -567,7 +568,7 @@ public:
void SetTemporaryZ(GSTexture* temp_z);
GSTexture* GetTemporaryZ();
TempZAddress GetTemporaryZInfo();
void SetTemporaryZInfo(u32 address, u32 offset);
void SetTemporaryZInfo(u32 address, u32 offset, u32 rt_offset);
void SetTemporaryZInfo(TempZAddress address_info);
/// Invalidates a temporary Z, a partial copy only created from the current DS for the current draw when Z is not offset but RT is.
void InvalidateTemporaryZ();

View File

@@ -1911,7 +1911,7 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
OMSetRenderTargets(nullptr, ds, &GLState::scissor);
{
const GLint clear_color = 0;
constexpr GLint clear_color = 0;
glClearBufferiv(GL_STENCIL, 0, &clear_color);
}
m_convert.ps[SetDATMShader(datm)].Bind();
@@ -1919,10 +1919,8 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
// om
OMSetDepthStencilState(m_date.dss);
if (GLState::blend)
{
glDisable(GL_BLEND);
}
OMSetBlendState(false);
OMSetColorMaskState();
// ia
@@ -1930,18 +1928,12 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
IASetVertexBuffer(vertices, 4);
IASetPrimitiveTopology(GL_TRIANGLE_STRIP);
// Texture
PSSetShaderResource(0, rt);
PSSetSamplerState(m_convert.pt);
DrawPrimitive();
if (GLState::blend)
{
glEnable(GL_BLEND);
}
}
void GSDeviceOGL::IASetVAO(GLuint vao)
@@ -2585,6 +2577,7 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
{
// Ensure all depth writes are finished before sampling
GL_INS("GL: Texture barrier to flush depth or rt before reading");
g_perfmon.Put(GSPerfMon::Barriers, 1);
glTextureBarrier();
}
// additional non-pipeline config stuff
@@ -2627,7 +2620,6 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
psel.ps.date = 3;
config.alpha_second_pass.ps.date = 3;
SetupPipeline(psel);
PSSetShaderResource(3, primid_texture);
}
if (config.blend.IsEffective(config.colormask))
@@ -2657,6 +2649,10 @@ void GSDeviceOGL::RenderHW(GSHWDrawConfig& config)
}
OMSetRenderTargets(draw_rt, draw_ds, &config.scissor);
if (primid_texture)
PSSetShaderResource(3, primid_texture);
OMSetColorMaskState(config.colormask);
SetupOM(config.depth);

View File

@@ -181,7 +181,7 @@ GSTexture* GSRendererSW::GetOutput(int i, float& scale, int& y_offset)
if (GSConfig.SaveFrame && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
{
m_texture[index]->Save(GetDrawDumpPath("%05d_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), i, (int)curFramebuffer.Block(), psm_str(curFramebuffer.PSM)));
m_texture[index]->Save(GetDrawDumpPath("%05d_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), i, (int)curFramebuffer.Block(), GSUtil::GetPSMName(curFramebuffer.PSM)));
}
}
@@ -445,7 +445,7 @@ void GSRendererSW::Draw()
m_mem.SaveBMP(s, m_context->TEX0.TBP0, m_context->TEX0.TBW, 0, 1 << m_context->TEX0.TW, 1 << m_context->TEX0.TH);
}
s = GetDrawDumpPath("%05d_f%05lld_itexraw_%05x_%s.bmp", s_n, frame, (int)m_context->TEX0.TBP0, psm_str(m_context->TEX0.PSM));
s = GetDrawDumpPath("%05d_f%05lld_itexraw_%05x_%s.bmp", s_n, frame, (int)m_context->TEX0.TBP0, GSUtil::GetPSMName(m_context->TEX0.PSM));
m_mem.SaveBMP(s, m_context->TEX0.TBP0, m_context->TEX0.TBW, m_context->TEX0.PSM, 1 << m_context->TEX0.TW, 1 << m_context->TEX0.TH);
}
@@ -459,13 +459,13 @@ void GSRendererSW::Draw()
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, 0, r.z, r.w);
}
s = GetDrawDumpPath("%05d_f%05lld_rt0_%05x_%s.bmp", s_n, frame, m_context->FRAME.Block(), psm_str(m_context->FRAME.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rt0_%05x_%s.bmp", s_n, frame, m_context->FRAME.Block(), GSUtil::GetPSMName(m_context->FRAME.PSM));
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, r.z, r.w);
}
if (GSConfig.SaveDepth)
{
s = GetDrawDumpPath("%05d_f%05lld_rz0_%05x_%s.bmp", s_n, frame, m_context->ZBUF.Block(), psm_str(m_context->ZBUF.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rz0_%05x_%s.bmp", s_n, frame, m_context->ZBUF.Block(), GSUtil::GetPSMName(m_context->ZBUF.PSM));
m_mem.SaveBMP(s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, r.z, r.w);
}
@@ -483,13 +483,13 @@ void GSRendererSW::Draw()
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, 0, r.z, r.w);
}
s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_%s.bmp", s_n, frame, m_context->FRAME.Block(), psm_str(m_context->FRAME.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_%s.bmp", s_n, frame, m_context->FRAME.Block(), GSUtil::GetPSMName(m_context->FRAME.PSM));
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, r.z, r.w);
}
if (GSConfig.SaveDepth)
{
s = GetDrawDumpPath("%05d_f%05lld_rz1_%05x_%s.bmp", s_n, frame, m_context->ZBUF.Block(), psm_str(m_context->ZBUF.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rz1_%05x_%s.bmp", s_n, frame, m_context->ZBUF.Block(), GSUtil::GetPSMName(m_context->ZBUF.PSM));
m_mem.SaveBMP(s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, r.z, r.w);
}
@@ -572,14 +572,14 @@ void GSRendererSW::Sync(int reason)
if (GSConfig.SaveRT)
{
s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), m_context->FRAME.Block(), psm_str(m_context->FRAME.PSM));
s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), m_context->FRAME.Block(), GSUtil::GetPSMName(m_context->FRAME.PSM));
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, PCRTCDisplays.GetFramebufferRect(-1).width(), 512);
}
if (GSConfig.SaveDepth)
{
s = GetDrawDumpPath("%05d_f%05lld_zb1_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), m_context->ZBUF.Block(), psm_str(m_context->ZBUF.PSM));
s = GetDrawDumpPath("%05d_f%05lld_zb1_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), m_context->ZBUF.Block(), GSUtil::GetPSMName(m_context->ZBUF.PSM));
m_mem.SaveBMP(s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, PCRTCDisplays.GetFramebufferRect(-1).width(), 512);
}
@@ -1543,14 +1543,14 @@ void GSRendererSW::SharedData::UpdateSource()
{
const GIFRegTEX0& TEX0 = g_gs_renderer->GetTex0Layer(i);
s = GetDrawDumpPath("%05d_f%05lld_itex%d_%05x_%s.bmp", g_gs_renderer->s_n, frame, i, TEX0.TBP0, psm_str(TEX0.PSM));
s = GetDrawDumpPath("%05d_f%05lld_itex%d_%05x_%s.bmp", g_gs_renderer->s_n, frame, i, TEX0.TBP0, GSUtil::GetPSMName(TEX0.PSM));
m_tex[i].t->Save(s);
}
if (global.clut)
{
s = GetDrawDumpPath("%05d_f%05lld_itexp_%05x_%s.bmp", g_gs_renderer->s_n, frame, (int)g_gs_renderer->m_context->TEX0.CBP, psm_str(g_gs_renderer->m_context->TEX0.CPSM));
s = GetDrawDumpPath("%05d_f%05lld_itexp_%05x_%s.bmp", g_gs_renderer->s_n, frame, (int)g_gs_renderer->m_context->TEX0.CBP, GSUtil::GetPSMName(g_gs_renderer->m_context->TEX0.CPSM));
GSPng::Save((IsDevBuild || GSConfig.SaveAlpha) ? GSPng::RGB_A_PNG : GSPng::RGB_PNG, s, reinterpret_cast<const u8*>(global.clut), 256, 1, sizeof(u32) * 256, GSConfig.PNGCompressionLevel, false);
}
}

View File

@@ -6507,24 +6507,46 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
if (BeginFullscreenColumnWindow(-530.0f, 0.0f, "game_list_info", UIPrimaryDarkColor))
{
const ImVec2 image_size = LayoutScale(ImVec2(275.0f, 400.0f));
ImGui::SetCursorPos(LayoutScale(ImVec2(128.0f, 20.0f)));
const float img_padding_y = LayoutScale(20.0f);
// Spacing between each text item
const float text_spacing_y = LayoutScale(8.0f);
// Space between title/serial and details, is in addition to text_spacing_y
const float title_padding_below_y = LayoutScale(12.0f);
// Estimate how much space is needed for text
// Do this even when nothing is selected, to ensure cover/icon is in a consistant size/position
const float title_detail_height =
LayoutScale(LAYOUT_LARGE_FONT_SIZE) + text_spacing_y + // Title
LayoutScale(LAYOUT_MEDIUM_FONT_SIZE) + text_spacing_y + // Serial
title_padding_below_y +
7.0f * (LayoutScale(LAYOUT_MEDIUM_FONT_SIZE) + text_spacing_y) + // File, CRC, Region, Compat, Time/Last Played, Size
LayoutScale(12.0f); // Extra padding
// Limit cover height to avoid pushing text off the screen
const ImGuiWindow* window = ImGui::GetCurrentWindow();
// Based on ImGui code for WorkRect, with scrolling logic removed
const float window_height = std::trunc(window->InnerRect.GetHeight() - 2.0f * std::max(window->WindowPadding.y, window->WindowBorderSize));
const float free_height = window_height - title_detail_height;
const float img_height = std::min(free_height - 2.0f * img_padding_y, LayoutScale(400.0f));
const ImVec2 image_size = ImVec2(LayoutScale(275.0f), img_height);
ImGui::SetCursorPos(ImVec2(LayoutScale(128.0f), img_padding_y));
if (selected_entry)
DrawGameCover(selected_entry, image_size);
else
DrawFallbackCover(image_size);
const float work_width = ImGui::GetCurrentWindow()->WorkRect.GetWidth();
constexpr float field_margin_y = 10.0f;
constexpr float start_x = 50.0f;
float text_y = 440.0f;
const float work_width = window->WorkRect.GetWidth();
const float start_x = LayoutScale(50.0f);
const float text_y = img_height + 2.0f * img_padding_y;
float text_width;
PushPrimaryColor();
ImGui::SetCursorPos(LayoutScale(start_x, text_y));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, field_margin_y));
ImGui::PushTextWrapPos(LayoutScale(480.0f));
ImGui::SetCursorPos(ImVec2(start_x, text_y));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, text_spacing_y));
ImGui::PushTextWrapPos(LayoutScale(490.0f));
ImGui::BeginGroup();
if (selected_entry)
@@ -6533,6 +6555,8 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
ImGui::PushFont(g_large_font);
const std::string_view title(std::string_view(selected_entry->GetTitle(true)).substr(0, 37));
text_width = ImGui::CalcTextSize(title.data(), title.data() + title.length(), false, work_width).x;
if (title.length() != selected_entry->GetTitle(true).length())
text_width += ImGui::CalcTextSize("...", nullptr, false, -1.0f).x;
ImGui::SetCursorPosX((work_width - text_width) / 2.0f);
ImGui::TextWrapped(
"%.*s%s", static_cast<int>(title.size()), title.data(), (title.length() == selected_entry->GetTitle(true).length()) ? "" : "...");
@@ -6544,7 +6568,7 @@ void FullscreenUI::DrawGameList(const ImVec2& heading_size)
text_width = ImGui::CalcTextSize(selected_entry->serial.c_str(), nullptr, false, work_width).x;
ImGui::SetCursorPosX((work_width - text_width) / 2.0f);
ImGui::TextWrapped("%s", selected_entry->serial.c_str());
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 15.0f);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + title_padding_below_y);
// file tile
ImGui::TextWrapped("%s", SmallString::from_format(FSUI_FSTR("File: {}"), Path::GetFileName(selected_entry->path)).c_str());

View File

@@ -189,16 +189,6 @@ u8 PadNegcon::ModeSwitch(u8 commandByte)
{
case 3:
this->analogLight = commandByte;
if (this->analogLight)
{
this->currentMode = Pad::Mode::ANALOG;
}
else
{
this->currentMode = Pad::Mode::DIGITAL;
}
break;
case 4:
this->analogLocked = (commandByte == 0x03);
@@ -219,7 +209,7 @@ u8 PadNegcon::StatusInfo(u8 commandByte)
case 4:
return 0x02;
case 5:
return this->analogLight;
return 0x01;
case 6:
return 0x02;
case 7:
@@ -500,7 +490,7 @@ u8 PadNegcon::SendCommandByte(u8 commandByte)
Console.Warning("%s(%02X) Config-only command was sent to a pad outside of config mode!", __FUNCTION__, commandByte);
}
ret = this->isInConfig ? static_cast<u8>(Pad::Mode::CONFIG) : static_cast<u8>(this->currentMode);
ret = this->isInConfig ? static_cast<u8>(Pad::Mode::CONFIG) : static_cast<u8>(Pad::Mode::NEGCON);
break;
case 2:
ret = 0x5a;

View File

@@ -154,11 +154,16 @@ namespace usb_pad
static void buzz_handle_data(USBDevice* dev, USBPacket* p)
{
BuzzState* s = USB_CONTAINER_OF(dev, BuzzState, dev);
if (p->ep->nr != 1)
{
goto fail;
}
switch (p->pid)
{
case USB_TOKEN_IN:
if (p->ep->nr == 1)
if (std::memcmp(&s->lastData, &s->data, sizeof(s->data)) != 0)
{
pxAssert(p->buffer_size >= sizeof(s->data));
@@ -166,12 +171,13 @@ namespace usb_pad
s->data.tail = 0xf;
std::memcpy(p->buffer_ptr, &s->data, sizeof(s->data));
std::memcpy(&s->lastData, &s->data, sizeof(s->data));
p->actual_length += sizeof(s->data);
}
else
{
goto fail;
p->status = USB_RET_NAK;
}
break;
case USB_TOKEN_OUT:

View File

@@ -75,7 +75,7 @@ namespace usb_pad
u8 player4_blue : 1;
u8 tail : 4;
} data = {};
} data = {}, lastData = {};
#pragma pack(pop)
};