mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
708931e48b | ||
|
|
81800d2883 | ||
|
|
d0411d7ddf | ||
|
|
70e232cab3 | ||
|
|
f90396bda4 | ||
|
|
ae8808b86e | ||
|
|
8d5b827432 | ||
|
|
cb672697e7 | ||
|
|
0bae9fc29b | ||
|
|
49c8b68700 | ||
|
|
1e2fcd17e0 | ||
|
|
468b9d2655 | ||
|
|
a3305ff791 | ||
|
|
814b0d5873 | ||
|
|
863f3e82ac | ||
|
|
529c756458 | ||
|
|
67b98dbdaa | ||
|
|
a16981cbe5 | ||
|
|
777bf338fa | ||
|
|
3ba8d9ebff | ||
|
|
db5384e19c | ||
|
|
fd3984287b | ||
|
|
31dbea4e0b | ||
|
|
0992e784f1 | ||
|
|
c59cc1fbb7 | ||
|
|
903edc79f7 | ||
|
|
4c94c69f02 | ||
|
|
4c57c214bd | ||
|
|
1cbeea3016 | ||
|
|
0d18738192 | ||
|
|
1e7c7db29b | ||
|
|
7c098a2665 | ||
|
|
3ab539be1e | ||
|
|
b46d5e4efc | ||
|
|
db06e11a7c | ||
|
|
757ed33e4f | ||
|
|
8eb5dfce85 | ||
|
|
f34db72a97 |
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
3
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -6,3 +6,6 @@
|
||||
|
||||
### Suggested Testing Steps
|
||||
<!-- If applicable, including examples you've already tested with / recommendations for how to test further is very helpful! -->
|
||||
|
||||
### Did you use AI to help find, test, or implement this issue or feature?
|
||||
<!-- Answer yes or no. If you answer yes, please provide a brief explanation how. -->
|
||||
|
||||
2
.github/workflows/linux_build_qt.yml
vendored
2
.github/workflows/linux_build_qt.yml
vendored
@@ -140,9 +140,11 @@ jobs:
|
||||
-DCMAKE_CXX_COMPILER=clang++-17 \
|
||||
-DCMAKE_EXE_LINKER_FLAGS_INIT="-fuse-ld=lld" \
|
||||
-DCMAKE_MODULE_LINKER_FLAGS_INIT="-fuse-ld=lld" \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DENABLE_SETCAP=OFF \
|
||||
-DDISABLE_ADVANCE_SIMD=TRUE \
|
||||
-DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON \
|
||||
$ADDITIONAL_CMAKE_ARGS
|
||||
|
||||
- name: Build PCSX2
|
||||
|
||||
@@ -18,7 +18,7 @@ LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.0
|
||||
LIBPNG=1.6.48
|
||||
LIBWEBP=1.5.0
|
||||
SDL=SDL3-3.2.12
|
||||
SDL=SDL3-3.2.14
|
||||
QT=6.9.0
|
||||
LZ4=1.10.0
|
||||
ZSTD=1.5.7
|
||||
@@ -39,7 +39,7 @@ fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.
|
||||
9564c72b1dfd1d6fe6274c5f95a8d989b59854575d4bbee44ade7bc17aa9bc93 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
|
||||
7d6fab70cf844bf6769077bd5d7a74893f8ffd4dfb42861745750c63c2a5c92c libwebp-$LIBWEBP.tar.gz
|
||||
9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96 $SDL.tar.gz
|
||||
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
c1800c2ea835801af04a05d4a32321d79a93954ee3ae2172bbeacf13d1f0598c qtbase-everywhere-src-$QT.tar.xz
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.12.tar.gz",
|
||||
"sha256": "9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96"
|
||||
"url": "https://libsdl.org/release/SDL3-3.2.14.tar.gz",
|
||||
"sha256": "b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f"
|
||||
}
|
||||
],
|
||||
"cleanup": [
|
||||
|
||||
@@ -40,7 +40,7 @@ fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=11.2.0
|
||||
SDL=SDL3-3.2.12
|
||||
SDL=SDL3-3.2.14
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.48
|
||||
@@ -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
|
||||
9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96 $SDL.tar.gz
|
||||
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
|
||||
|
||||
@@ -22,7 +22,7 @@ fi
|
||||
|
||||
FREETYPE=2.13.3
|
||||
HARFBUZZ=11.2.0
|
||||
SDL=SDL3-3.2.12
|
||||
SDL=SDL3-3.2.14
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.48
|
||||
@@ -59,7 +59,7 @@ CMAKE_COMMON=(
|
||||
cat > SHASUMS <<EOF
|
||||
0550350666d427c74daeb85d5ac7bb353acba5f76956395995311a9c6f063289 freetype-$FREETYPE.tar.xz
|
||||
16c0204704f3ebeed057aba100fe7db18d71035505cb10e595ea33d346457fc8 harfbuzz-$HARFBUZZ.tar.gz
|
||||
9734f308e130c64a2b4df6bca5884c5aca577ee6c7c77ab3379474ea85e51f96 $SDL.tar.gz
|
||||
b7e7dc05011b88c69170fe18935487b2559276955e49113f8c1b6b72c9b79c1f $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
46fd06ff37db1db64c0dc288d78a3f5efd23ad9ac41561193f983e20937ece03 libpng-$LIBPNG.tar.xz
|
||||
|
||||
@@ -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.12
|
||||
set SDL=SDL3-3.2.14
|
||||
set QT=6.9.0
|
||||
set QTMINOR=6.9
|
||||
set LZ4=1.10.0
|
||||
@@ -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" ebf1efd71527afbca6bdf2b0310caf726d00cc102c0e59ac86c1f8cd201f9593 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 46a17d3ea71fe2580a7f43ca7da286c5b9106dd761e2fd5533bb113e5d86b633 || 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
|
||||
@@ -246,12 +246,21 @@ cmake --build . --parallel || goto error
|
||||
ninja install || goto error
|
||||
cd ..\.. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
|
||||
) else (
|
||||
rem kddockwidgets slightly changes the name of the dll depending on if CMAKE_BUILD_TYPE or CMAKE_CONFIGURATION_TYPES is used
|
||||
rem The dll name being kddockwidgets-qt62.dll or kddockwidgets-qt62.dll respectively
|
||||
rem Always use CMAKE_CONFIGURATION_TYPES to give consistant naming
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES=Release -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=Release -G "Ninja Multi-Config"
|
||||
)
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rmdir /S /Q "KDDockWidgets-%KDDOCKWIDGETS%"
|
||||
%SEVENZIP% x "KDDockWidgets-%KDDOCKWIDGETS%.zip" || goto error
|
||||
cd "KDDockWidgets-%KDDOCKWIDGETS%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\..\common\kddockwidgets-dodgy-include.patch" || goto error
|
||||
cmake %ARM64TOOLCHAIN% -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja || goto error
|
||||
cmake -B build %ARM64TOOLCHAIN% -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets %KDDOCKWIDGETSBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
@@ -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.12
|
||||
set SDL=SDL3-3.2.14
|
||||
set QT=6.9.0
|
||||
set QTMINOR=6.9
|
||||
set LZ4=1.10.0
|
||||
@@ -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" ebf1efd71527afbca6bdf2b0310caf726d00cc102c0e59ac86c1f8cd201f9593 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 46a17d3ea71fe2580a7f43ca7da286c5b9106dd761e2fd5533bb113e5d86b633 || 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
|
||||
@@ -250,12 +250,21 @@ cmake --build . --parallel || goto error
|
||||
ninja install || goto error
|
||||
cd ..\.. || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES="Release;Debug" -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=all -G "Ninja Multi-Config"
|
||||
) else (
|
||||
rem kddockwidgets slightly changes the name of the dll depending on if CMAKE_BUILD_TYPE or CMAKE_CONFIGURATION_TYPES is used
|
||||
rem The dll name being kddockwidgets-qt62.dll or kddockwidgets-qt62.dll respectively
|
||||
rem Always use CMAKE_CONFIGURATION_TYPES to give consistant naming
|
||||
set KDDOCKWIDGETSBUILDSPEC=-DCMAKE_CONFIGURATION_TYPES=Release -DCMAKE_CROSS_CONFIGS=all -DCMAKE_DEFAULT_BUILD_TYPE=Release -DCMAKE_DEFAULT_CONFIGS=Release -G "Ninja Multi-Config"
|
||||
)
|
||||
|
||||
echo "Building KDDockWidgets..."
|
||||
rmdir /S /Q "KDDockWidgets-%KDDOCKWIDGETS%"
|
||||
%SEVENZIP% x "KDDockWidgets-%KDDOCKWIDGETS%.zip" || goto error
|
||||
cd "KDDockWidgets-%KDDOCKWIDGETS%" || goto error
|
||||
%PATCH% -p1 < "%SCRIPTDIR%\..\common\kddockwidgets-dodgy-include.patch" || goto error
|
||||
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets -B build -G Ninja || goto error
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DKDDockWidgets_QT6=true -DKDDockWidgets_EXAMPLES=false -DKDDockWidgets_FRONTENDS=qtwidgets %KDDOCKWIDGETSBUILDSPEC% || goto error
|
||||
cmake --build build --parallel || goto error
|
||||
ninja -C build install || goto error
|
||||
cd .. || goto error
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1290,6 +1290,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000558500001b06000010010000,GameSir G4 Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000ac0500002d0200001b010000,GameSir G4s,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b33,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000ac0500007a05000011010000,GameSir G5,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,rightshoulder:b7,rightstick:b16,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000373500009710000001020000,GameSir Kaleid Flux,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000bc2000005656000011010000,GameSir T4w,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:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000ac0500001a06000011010000,GameSir-T3 2.02,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
0500000047532047616d657061640000,GameStop Gamepad,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:Linux,
|
||||
|
||||
1
bin/resources/icons/AppBanner.svg
Normal file
1
bin/resources/icons/AppBanner.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg id="PCSX2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 2675 329.6"><g id="vectorized_by_maxihplay"><path id="_2" d="M2181.5,5.7h438.1c27.8,0,50.4,22.6,50.4,50.4v92.5c0,27.8-22.6,50.4-50.4,50.4h-309.5v46.5h359.9v78.6h-488.5v-145.3c0-27.8,22.6-50.4,50.4-50.4h309.5v-50.8h-315l-44.9-71.9h0Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="10" stroke-width="10"/><g id="X"><polygon points="1619.8 5.7 1769.1 5.7 1867.5 102 1961.6 5.9 2115.8 5.9 2115.8 77.2 2039.6 77.2 1954.7 164 2037.1 245.4 2115.8 245.4 2115.8 324.1 1968.4 324.1 1867.8 224 1767.8 324 1619.8 324 1619.8 244.8 1699.3 244.8 1779.3 165.8 1692.8 77.2 1619.8 77.2 1619.8 5.7" fill="#3caeff" stroke-width="0"/><path d="M1623.2,8.7l17.5,17.5v30.1h57c3.1,0,6,1.2,8.2,3.4l93.8,93.4c7.3,7.3,7.2,19.1-.1,26.3l-86,84.2c-3.1,3-7.3,4.8-11.7,4.8h-61.2l-18.5-21.5,77-2.1,80.1-79.1-86.5-88.5h-73V5.7l3.4,3h0Z" fill="#279ff5" stroke-width="0"/><path d="M1623.9,9.7l16.8,16.5h121.8l93.4,93.4c6.7,6.7,17.6,6.7,24.3,0l92.6-92.5h121.8l19.2-19.2-152.1-2-94.1,96.1-98.3-96.3-145.4,4h0Z" fill="#50b6ff" stroke-width="0"/><path d="M2114.7,247.9l-20.2,20.6h-62.1c-3.8,0-7.4-1.5-10-4.1l-85.5-85.5c-7.7-7.6-7.7-20.1,0-27.7l90-90c3.2-3.2,7.5-5,12-5h55.5v-29l20.3-19.9,1.2,70-76.1,1.4-85,85.5,82.4,81.3h78.8l-1.3,2.4Z" fill="#34a2f2" stroke-width="0"/><path d="M1619.8,323.5l1.7-77.8,19.2,22.7v34h115.6c1.1,0,2.1-.4,2.8-1.2l95.2-95.2c7.8-7.8,20.4-7.7,28.1.1l92.9,94.7c.7.7,1.7,1.2,2.8,1.2h116.9l-.5-33.5,22-24.5-.6,80.1h-147.4l-100.6-100.1-100.1,100.1-148-.6h0Z" fill="#43b9f2" stroke-width="0"/><polygon points="1619.8 5.7 1769.1 5.7 1867.5 102 1961.6 5.9 2115.8 5.9 2115.8 77.2 2039.6 77.2 1954.7 164 2037.1 245.4 2115.8 245.4 2115.8 324.1 1968.4 324.1 1867.8 224 1767.8 324 1619.8 324 1619.8 244.8 1699.3 244.8 1779.3 165.8 1692.8 77.2 1619.8 77.2 1619.8 5.7" fill="none" stroke="#5d73cb" stroke-miterlimit="10" stroke-width="11"/></g><path id="S" d="M1554.7,5.7h-434c-27.8,0-50.4,22.6-50.4,50.4v95.9c0,27.9,22.6,50.4,50.4,50.4h302.8v43.3h-353.2v78.4h434c27.8,0,50.4-22.6,50.4-50.4v-97.6c0-27.9-22.6-50.4-50.4-50.4h-303.9v-48.1h306.3l48-71.9Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="10" stroke-width="10"/><path id="C" d="M1008.1,5.1h-395.5c-27.8,0-50.4,22.6-50.4,50.4v217.9c0,28,22.7,50.8,50.8,50.8h385.2v-79.2h-304.3V78.2h263.3l50.9-73.1Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="10" stroke-width="10"/><path id="P" d="M5,55.5C5,27.6,27.6,5,55.5,5h390.3c27.7,0,50.2,22.5,50.2,50.2v139.4c0,27.9-22.6,50.4-50.5,50.4l-284-.6,64.2-71.9h139.8v-95h-225.4v246.5H5V55.5Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="10" stroke-width="10"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -397,7 +397,11 @@ float4 fetch_raw_color(int2 xy)
|
||||
|
||||
float4 fetch_c(int2 uv)
|
||||
{
|
||||
#if PS_TEX_IS_FB == 1
|
||||
return RtTexture.Load(int3(uv, 0));
|
||||
#else
|
||||
return Texture.Load(int3(uv, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -330,7 +330,11 @@ vec4 fetch_raw_color()
|
||||
|
||||
vec4 fetch_c(ivec2 uv)
|
||||
{
|
||||
#if PS_TEX_IS_FB == 1
|
||||
return sample_from_rt();
|
||||
#else
|
||||
return texelFetch(TextureSampler, ivec2(uv), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -64,10 +64,13 @@ set(CMAKE_SHARED_LINKER_FLAGS_DEVEL "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}
|
||||
CACHE STRING "Flags used for linking shared libraries during development builds" FORCE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS_DEVEL "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}"
|
||||
CACHE STRING "Flags used for linking executables during development builds" FORCE)
|
||||
# Exclude Debug from the configurations we can import from
|
||||
set(CMAKE_MAP_IMPORTED_CONFIG_DEVEL "RelWithDebInfo" "Release" "MinSizeRel" "None" "NoConfig" ""
|
||||
CACHE STRING "Configurations used when importing packages for development builds" FORCE)
|
||||
if(CMAKE_CONFIGURATION_TYPES)
|
||||
list(INSERT CMAKE_CONFIGURATION_TYPES 0 Devel)
|
||||
endif()
|
||||
mark_as_advanced(CMAKE_C_FLAGS_DEVEL CMAKE_CXX_FLAGS_DEVEL CMAKE_LINKER_FLAGS_DEVEL CMAKE_SHARED_LINKER_FLAGS_DEVEL CMAKE_EXE_LINKER_FLAGS_DEVEL)
|
||||
mark_as_advanced(CMAKE_C_FLAGS_DEVEL CMAKE_CXX_FLAGS_DEVEL CMAKE_LINKER_FLAGS_DEVEL CMAKE_SHARED_LINKER_FLAGS_DEVEL CMAKE_EXE_LINKER_FLAGS_DEVEL CMAKE_MAP_IMPORTED_CONFIG_DEVEL)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Select the architecture
|
||||
|
||||
@@ -437,7 +437,7 @@ std::unique_ptr<SharedMemoryMappingArea> SharedMemoryMappingArea::Create(size_t
|
||||
{
|
||||
pxAssertRel(Common::IsAlignedPow2(size, __pagesize), "Size is page aligned");
|
||||
|
||||
mach_vm_address_t alloc;
|
||||
mach_vm_address_t alloc = 0;
|
||||
const kern_return_t res =
|
||||
mach_vm_map(mach_task_self(), &alloc, size, 0, VM_FLAGS_ANYWHERE,
|
||||
MEMORY_OBJECT_NULL, 0, false, VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_NONE);
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
<ItemDefinitionGroup>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>$(DepsLibDir);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);freetype.lib;jpeg.lib;libpng16.lib;libwebp.lib;lz4.lib;SDL3.lib;zlib.lib;zstd.lib;kddockwidgets-qt62.lib;plutovg.lib;plutosvg.lib</AdditionalDependencies>
|
||||
</Link>
|
||||
<AdditionalDependencies>%(AdditionalDependencies);freetype.lib;jpeg.lib;libpng16.lib;libwebp.lib;lz4.lib;SDL3.lib;zlib.lib;zstd.lib;plutovg.lib;plutosvg.lib</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="$(Configuration.Contains(Debug))">%(AdditionalDependencies);kddockwidgets-qt6d.lib;</AdditionalDependencies>
|
||||
<AdditionalDependencies Condition="!$(Configuration.Contains(Debug))">%(AdditionalDependencies);kddockwidgets-qt6.lib;</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<DepsDLLs Include="$(DepsBinDir)freetype.dll" />
|
||||
@@ -19,7 +21,8 @@
|
||||
<DepsDLLs Include="$(DepsBinDir)shaderc_shared.dll" />
|
||||
<DepsDLLs Include="$(DepsBinDir)zlib1.dll" />
|
||||
<DepsDLLs Include="$(DepsBinDir)zstd.dll" />
|
||||
<DepsDLLs Include="$(DepsBinDir)kddockwidgets-qt62.dll" />
|
||||
<DepsDLLs Condition="$(Configuration.Contains(Debug))" Include="$(DepsBinDir)kddockwidgets-qt6d.dll" />
|
||||
<DepsDLLs Condition="!$(Configuration.Contains(Debug))" Include="$(DepsBinDir)kddockwidgets-qt6.dll" />
|
||||
<DepsDLLs Include="$(DepsBinDir)plutovg.dll" />
|
||||
<DepsDLLs Include="$(DepsBinDir)plutosvg.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>576</width>
|
||||
<height>294</height>
|
||||
<width>580</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -19,45 +19,42 @@
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Preferred</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="icon">
|
||||
<property name="maximumSize">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>260</width>
|
||||
<height>260</height>
|
||||
<width>1</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="resources/resources.qrc">:/icons/logo.png</pixmap>
|
||||
<pixmap resource="resources/resources.qrc">:/icons/PCSX2logo.svg</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Preferred</enum>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
@@ -69,7 +66,7 @@
|
||||
<string extracomment="SCM= Source Code Management">SCM Version</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -79,7 +76,7 @@
|
||||
<string><html><head/><body><p>PCSX2 is a free and open-source PlayStation 2 (PS2) emulator. Its purpose is to emulate the PS2's hardware, using a combination of MIPS CPU Interpreters, Recompilers and a Virtual Machine which manages hardware states and PS2 system memory. This allows you to play PS2 games on your PC, with many additional features and benefits.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignJustify|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -89,23 +86,31 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="disclaimer">
|
||||
<property name="font">
|
||||
<font>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p>PlayStation 2 and PS2 are registered trademarks of Sony Interactive Entertainment. This application is not affiliated in any way with Sony Interactive Entertainment.</p></body></html></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignJustify|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
@@ -115,12 +120,15 @@
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -131,19 +139,22 @@
|
||||
<string notr="true">TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Minimum</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
@@ -151,7 +162,7 @@
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
<set>QDialogButtonBox::StandardButton::Close</set>
|
||||
</property>
|
||||
<property name="centerButtons">
|
||||
<bool>true</bool>
|
||||
@@ -162,7 +173,6 @@
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="resources/resources.qrc"/>
|
||||
<include location="resources/icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
1
pcsx2-qt/resources/icons/PCSX2logo.svg
Normal file
1
pcsx2-qt/resources/icons/PCSX2logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?><svg id="PCSX2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 280.11 34.51"><g id="vectorized_by_maxihplay"><path id="_2" d="M228.43.6h45.87c2.91,0,5.28,2.37,5.28,5.28v9.69c0,2.91-2.37,5.28-5.28,5.28h-32.41v4.87h37.69v8.23h-51.15v-15.21c0-2.91,2.37-5.28,5.28-5.28h32.41v-5.32h-32.98l-4.7-7.53Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="1.05" stroke-width="1.05"/><g id="X"><polygon id="polygon1" points="221.55 25.7 221.55 33.94 206.12 33.94 195.58 23.46 185.11 33.93 169.61 33.93 169.61 25.63 177.94 25.63 186.32 17.36 177.26 8.08 169.61 8.08 169.61 .6 185.25 .6 195.55 10.68 205.41 .62 221.55 .62 221.55 8.08 213.57 8.08 204.68 17.17 213.31 25.7 221.55 25.7" fill="#3caeff" stroke-width="0"/><path id="path1" d="M169.97.91l1.83,1.83v3.15h5.97c.32,0,.63.13.86.36l9.82,9.78c.76.76.75,2-.01,2.75l-9.01,8.82c-.32.31-.76.5-1.23.5h-6.41l-1.94-2.25,8.06-.22,8.39-8.28-9.06-9.27h-7.64V.6l.36.31Z" fill="#279ff5" stroke-width="0"/><path id="path2" d="M170.04,1.02l1.76,1.73h12.75l9.78,9.78c.7.7,1.84.7,2.54,0l9.7-9.69h12.75l2.01-2.01-15.93-.21-9.85,10.06-10.29-10.08-15.23.42Z" fill="#50b6ff" stroke-width="0"/><path id="path3" d="M221.44,25.96l-2.12,2.16h-6.5c-.4,0-.77-.16-1.05-.43l-8.95-8.95c-.81-.8-.81-2.1,0-2.9l9.42-9.42c.34-.34.79-.52,1.26-.52h5.81v-3.04l2.13-2.08.13,7.33-7.97.15-8.9,8.95,8.63,8.51h8.25l-.14.25Z" fill="#34a2f2" stroke-width="0"/><path id="path4" d="M169.61,33.87l.18-8.15,2.01,2.38v3.56h12.1c.12,0,.22-.04.29-.13l9.97-9.97c.82-.82,2.14-.81,2.94.01l9.73,9.92c.07.07.18.13.29.13h12.24l-.05-3.51,2.3-2.57-.06,8.39h-15.43l-10.53-10.48-10.48,10.48-15.5-.06Z" fill="#43b9f2" stroke-width="0"/><polygon id="polygon4" points="221.55 25.7 221.55 33.94 206.12 33.94 195.58 23.46 185.11 33.93 169.61 33.93 169.61 25.63 177.94 25.63 186.32 17.36 177.26 8.08 169.61 8.08 169.61 .6 185.25 .6 195.55 10.68 205.41 .62 221.55 .62 221.55 8.08 213.57 8.08 204.68 17.17 213.31 25.7 221.55 25.7" fill="none" stroke="#5d73cb" stroke-miterlimit="1.05" stroke-width="1.15"/></g><path id="S" d="M162.8.6h-45.45c-2.91,0-5.28,2.37-5.28,5.28v10.04c0,2.92,2.37,5.28,5.28,5.28h31.71v4.53h-36.98v8.21h45.45c2.91,0,5.28-2.37,5.28-5.28v-10.22c0-2.92-2.37-5.28-5.28-5.28h-31.82v-5.04h32.07l5.03-7.53Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="1.05" stroke-width="1.05"/><path id="C" d="M105.56.53h-41.41c-2.91,0-5.28,2.37-5.28,5.28v22.82c0,2.93,2.38,5.32,5.32,5.32h40.34v-8.29h-31.86V8.19h27.57l5.33-7.65Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="1.05" stroke-width="1.05"/><path id="P" d="M.52,5.81C.52,2.89,2.89.52,5.81.52h40.87c2.9,0,5.26,2.36,5.26,5.26v14.6c0,2.92-2.37,5.28-5.29,5.28l-29.74-.06,6.72-7.53h14.64v-9.95H14.67v25.81H.52V5.81Z" fill="#fff" stroke="#7a7a7a" stroke-miterlimit="1.05" stroke-width="1.05"/></g></svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -103,7 +103,7 @@
|
||||
<file>icons/black/svg/window-2-line.svg</file>
|
||||
<file>icons/black/svg/zoom-in-line.svg</file>
|
||||
<file>icons/black/svg/zoom-out-line.svg</file>
|
||||
<file>icons/logo.png</file>
|
||||
<file>icons/PCSX2logo.svg</file>
|
||||
<file>icons/QT.png</file>
|
||||
<file>icons/update.png</file>
|
||||
<file>icons/white/index.theme</file>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
class Error;
|
||||
|
||||
@@ -1286,7 +1286,11 @@ function(setup_main_executable target)
|
||||
|
||||
# Copy dependency libraries.
|
||||
set(DEPS_BINDIR "${CMAKE_SOURCE_DIR}/deps/bin")
|
||||
set(DEPS_TO_COPY freetype.dll harfbuzz.dll jpeg62.dll libpng16.dll libsharpyuv.dll libwebp.dll lz4.dll SDL3.dll shaderc_shared.dll zlib1.dll zstd.dll kddockwidgets-qt62.dll plutovg.dll plutosvg.dll)
|
||||
set(DEPS_TO_COPY freetype.dll harfbuzz.dll jpeg62.dll libpng16.dll libsharpyuv.dll libwebp.dll lz4.dll SDL3.dll shaderc_shared.dll zlib1.dll zstd.dll plutovg.dll plutosvg.dll)
|
||||
set(DEPS_TO_COPY
|
||||
$<IF:$<CONFIG:Debug>,kddockwidgets-qt6d.dll,kddockwidgets-qt6.dll>
|
||||
${DEPS_TO_COPY}
|
||||
)
|
||||
foreach(DEP_TO_COPY ${DEPS_TO_COPY})
|
||||
install(FILES "${DEPS_BINDIR}/${DEP_TO_COPY}" DESTINATION "${CMAKE_SOURCE_DIR}/bin")
|
||||
endforeach()
|
||||
|
||||
@@ -3996,8 +3996,14 @@ GSState::TextureMinMaxResult GSState::GetTextureMinMax(GIFRegTEX0 TEX0, GIFRegCL
|
||||
// If it's the start of the texture and our little adjustment is all that pushed it over, clamp it to 0.
|
||||
// This stops the border check failing when using repeat but needed less than the full texture
|
||||
// since this was making it take the full texture even though it wasn't needed.
|
||||
if (!clamp_to_tsize && ((m_vt.m_min.t.floor() == GSVector4::zero()).mask() & 0x3) == 0x3)
|
||||
st = st.max(GSVector4::zero());
|
||||
if (!clamp_to_tsize)
|
||||
{
|
||||
const u32 mask = (m_vt.m_min.t.floor() == GSVector4::zero()).mask();
|
||||
if (mask & 1) // X == 0
|
||||
st.x = st.max(GSVector4::zero()).x;
|
||||
if (mask & 2) // Y == 0
|
||||
st.y = st.max(GSVector4::zero()).y;
|
||||
}
|
||||
}
|
||||
|
||||
// draw will get scissored, adjust UVs to suit
|
||||
|
||||
@@ -493,6 +493,7 @@ GSTexture* GSDevice::FetchSurface(GSTexture::Type type, int width, int height, i
|
||||
{
|
||||
ERROR_LOG("GS: Memory allocation failure for {}x{} texture. Purging pool and retrying.", size.x, size.y);
|
||||
PurgePool();
|
||||
t = CreateSurface(type, size.x, size.y, levels, format);
|
||||
if (!t)
|
||||
{
|
||||
ERROR_LOG("GS: Memory allocation failure for {}x{} texture after purging pool.", size.x, size.y);
|
||||
|
||||
@@ -372,6 +372,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
|
||||
// Others ways to fetch the texture
|
||||
u32 channel : 3;
|
||||
u32 channel_fb : 1;
|
||||
|
||||
// Dithering
|
||||
u32 dither : 2;
|
||||
@@ -410,7 +411,7 @@ struct alignas(16) GSHWDrawConfig
|
||||
{
|
||||
const u32 sw_blend_bits = blend_a | blend_b | blend_d;
|
||||
const bool sw_blend_needs_rt = (sw_blend_bits != 0 && ((sw_blend_bits | blend_c) & 1u)) || ((a_masked & blend_c) != 0);
|
||||
return tex_is_fb || fbmask || (date > 0 && date != 3) || sw_blend_needs_rt;
|
||||
return channel_fb || tex_is_fb || fbmask || (date > 0 && date != 3) || sw_blend_needs_rt;
|
||||
}
|
||||
|
||||
/// Disables color output from the pixel shader, this is done when all channels are masked.
|
||||
@@ -934,7 +935,8 @@ public:
|
||||
__fi bool IsPresentThrottleAllowed() const { return m_allow_present_throttle; }
|
||||
|
||||
__fi GSTexture* GetCurrent() const { return m_current; }
|
||||
|
||||
__fi GSTexture* GetMAD() const { return m_mad; }
|
||||
|
||||
void Recycle(GSTexture* t);
|
||||
|
||||
/// Returns true if it's an OpenGL-based renderer.
|
||||
|
||||
@@ -118,6 +118,18 @@ bool GSRenderer::Merge(int field)
|
||||
if (!tex[0] && !tex[1])
|
||||
{
|
||||
m_real_size = GSVector2i(0, 0);
|
||||
|
||||
// Clear out the MAD buffer as some remnants of the previously shown frame came be left over, causing a flash for one frame.
|
||||
if (GSConfig.InterlaceMode == GSInterlaceMode::Automatic || GSConfig.InterlaceMode >= GSInterlaceMode::AdaptiveTFF)
|
||||
{
|
||||
GSTexture* mad_tex = g_gs_device->GetMAD();
|
||||
|
||||
if (mad_tex)
|
||||
{
|
||||
g_gs_device->ClearRenderTarget(mad_tex, 0);
|
||||
mad_tex = nullptr;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1087,7 +1087,14 @@ GSDevice::PresentResult GSDevice12::BeginPresent(bool frame_skip)
|
||||
return PresentResult::DeviceLost;
|
||||
|
||||
if (frame_skip || !m_swap_chain)
|
||||
{
|
||||
if (!m_swap_chain)
|
||||
{
|
||||
ExecuteCommandList(WaitType::None);
|
||||
InvalidateCachedState();
|
||||
}
|
||||
return PresentResult::FrameSkipped;
|
||||
}
|
||||
|
||||
// Check if we lost exclusive fullscreen. If so, notify the host, so it can switch to windowed mode.
|
||||
// This might get called repeatedly if it takes a while to switch back, that's the host's problem.
|
||||
|
||||
@@ -2859,7 +2859,8 @@ void GSRendererHW::Draw()
|
||||
if (!no_rt && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16 && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp >= 16 &&
|
||||
(m_vt.m_primclass == GS_SPRITE_CLASS || (m_vt.m_primclass == GS_TRIANGLE_CLASS && (m_index.tail % 6) == 0 && TrianglesAreQuads(true) && m_index.tail > 6)))
|
||||
{
|
||||
if (GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16)
|
||||
// Tail check is to make sure we have enough strips to go all the way across the page, or if it's using a region clamp could be used to draw strips.
|
||||
if (GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 && (m_index.tail >= (m_cached_ctx.TEX0.TBW * 2) || m_cached_ctx.CLAMP.WMS > CLAMP_CLAMP || m_cached_ctx.CLAMP.WMT > CLAMP_CLAMP))
|
||||
{
|
||||
const GSVertex* v = &m_vertex.buff[0];
|
||||
|
||||
@@ -2919,9 +2920,9 @@ 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.Block(), req_color, req_alpha) :
|
||||
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,
|
||||
possible_shuffle, m_vt.IsLinear(), m_cached_ctx.FRAME.Block(), req_color, req_alpha);
|
||||
possible_shuffle, m_vt.IsLinear(), m_cached_ctx.FRAME, req_color, req_alpha);
|
||||
|
||||
if (!src) [[unlikely]]
|
||||
{
|
||||
@@ -3211,7 +3212,7 @@ void GSRendererHW::Draw()
|
||||
CleanupDraw(true);
|
||||
return;
|
||||
}
|
||||
else if (IsPageCopy() && src->m_from_target && m_cached_ctx.TEX0.TBP0 >= src->m_from_target->m_TEX0.TBP0)
|
||||
else if (IsPageCopy() && src->m_from_target && m_cached_ctx.TEX0.TBP0 >= src->m_from_target->m_TEX0.TBP0 && m_cached_ctx.FRAME.FBW < ((src->m_from_target->m_TEX0.TBW + 1) >> 1))
|
||||
{
|
||||
FRAME_TEX0.TBW = src->m_from_target->m_TEX0.TBW;
|
||||
}
|
||||
@@ -3263,8 +3264,6 @@ void GSRendererHW::Draw()
|
||||
const GSVector4i new_drect = GSVector4i(0, new_offset * rt->m_scale, new_size.x * rt->m_scale, new_size.y * rt->m_scale);
|
||||
rt->ResizeTexture(new_size.x, new_size.y, true, true, new_drect);
|
||||
|
||||
g_texture_cache->CombineAlignedInsideTargets(rt, src);
|
||||
|
||||
if (src && src->m_from_target && src->m_from_target == rt && src->m_target_direct)
|
||||
{
|
||||
src->m_texture = rt->m_texture;
|
||||
@@ -3282,6 +3281,8 @@ void GSRendererHW::Draw()
|
||||
rt->m_drawn_since_read.y += new_offset;
|
||||
rt->m_drawn_since_read.w += new_offset;
|
||||
|
||||
g_texture_cache->CombineAlignedInsideTargets(rt, src);
|
||||
|
||||
if (rt->m_dirty.size())
|
||||
{
|
||||
for (int i = 0; i < static_cast<int>(rt->m_dirty.size()); i++)
|
||||
@@ -3351,6 +3352,7 @@ void GSRendererHW::Draw()
|
||||
// Z isn't offset but RT is, so we need a temp Z to align it, hopefully nothing will ever write to the Z too, right??
|
||||
if (ds && vertical_offset && (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 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;
|
||||
if (g_texture_cache->GetTemporaryZ() != nullptr)
|
||||
{
|
||||
@@ -3372,19 +3374,24 @@ void GSRendererHW::Draw()
|
||||
if (g_texture_cache->GetTemporaryZ() == nullptr)
|
||||
{
|
||||
m_temp_z_full_copy = false;
|
||||
u32 vertical_size = std::max(rt->m_unscaled_size.y, ds->m_unscaled_size.y);
|
||||
GL_CACHE("HW: RT in RT Z copy on draw %d z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset);
|
||||
GSVector4i dRect = GSVector4i(0, vertical_offset * ds->m_scale, ds->m_unscaled_size.x * ds->m_scale, (vertical_offset + ds->m_unscaled_size.y - z_vertical_offset) * ds->m_scale);
|
||||
const u32 vertical_size = std::max(rt->m_unscaled_size.y, ds->m_unscaled_size.y);
|
||||
const GSVector4i dRect = GSVector4i(0, vertical_offset * ds->m_scale, ds->m_unscaled_size.x * 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);
|
||||
GSTexture* tex = g_gs_device->CreateDepthStencil(ds->m_unscaled_size.x * ds->m_scale, new_height, GSTexture::Format::DepthStencil, true);
|
||||
g_gs_device->StretchRect(ds->m_texture, GSVector4(0.0f, z_vertical_offset / static_cast<float>(ds->m_unscaled_size.y), 1.0f, (ds->m_unscaled_size.y - z_vertical_offset) / static_cast<float>(ds->m_unscaled_size.y)), 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, vertical_offset - z_vertical_offset);
|
||||
t_size.y = std::max(new_height, t_size.y);
|
||||
if (GSTexture* tex = g_gs_device->CreateDepthStencil(ds->m_unscaled_size.x * ds->m_scale, new_height, GSTexture::Format::DepthStencil, true))
|
||||
{
|
||||
GL_CACHE("HW: RT in RT Z copy on draw %d z_vert_offset %d z_offset %d", s_n, z_vertical_offset, vertical_offset);
|
||||
g_gs_device->StretchRect(ds->m_texture, GSVector4(0.0f, z_vertical_offset / static_cast<float>(ds->m_unscaled_size.y), 1.0f, (ds->m_unscaled_size.y - z_vertical_offset) / static_cast<float>(ds->m_unscaled_size.y)), 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, vertical_offset - z_vertical_offset);
|
||||
t_size.y = std::max(new_height, t_size.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
DevCon.Warning("HW: Temporary depth buffer creation failed.");
|
||||
m_using_temp_z = false;
|
||||
}
|
||||
}
|
||||
m_using_temp_z = true;
|
||||
|
||||
}
|
||||
}
|
||||
// Don't resize if the BPP don't match.
|
||||
@@ -3686,7 +3693,7 @@ void GSRendererHW::Draw()
|
||||
m_vt.m_min.t *= 0.5f;
|
||||
m_vt.m_max.t *= 0.5f;
|
||||
|
||||
tmm = GetTextureMinMax(MIP_TEX0, MIP_CLAMP, m_vt.IsLinear(), false);
|
||||
tmm = GetTextureMinMax(MIP_TEX0, MIP_CLAMP, m_vt.IsLinear(), true);
|
||||
|
||||
src->UpdateLayer(MIP_TEX0, tmm.coverage, layer - m_lod.x);
|
||||
}
|
||||
@@ -3881,7 +3888,7 @@ void GSRendererHW::Draw()
|
||||
const bool new_rect = rt->m_valid.rempty();
|
||||
const bool new_height = new_h > rt->GetUnscaledHeight();
|
||||
const int old_height = rt->m_texture->GetHeight();
|
||||
|
||||
bool merge_targets = false;
|
||||
pxAssert(rt->GetScale() == target_scale);
|
||||
if (rt->GetUnscaledWidth() != new_w || rt->GetUnscaledHeight() != new_h)
|
||||
GL_INS("HW: Resize RT from %dx%d to %dx%d", rt->GetUnscaledWidth(), rt->GetUnscaledHeight(), new_w, new_h);
|
||||
@@ -3904,7 +3911,10 @@ void GSRendererHW::Draw()
|
||||
g_texture_cache->AddDirtyRectTarget(rt, height_dirty_rect, rt->m_TEX0.PSM, rt->m_TEX0.TBW, mask);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
if ((new_w > rt->m_unscaled_size.x || new_h > rt->m_unscaled_size.y) && GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets)
|
||||
merge_targets = true;
|
||||
|
||||
rt->ResizeTexture(new_w, new_h);
|
||||
|
||||
if (!m_texture_shuffle && !m_channel_shuffle)
|
||||
@@ -3935,6 +3945,8 @@ void GSRendererHW::Draw()
|
||||
rt->UpdateValidity(update_rect, !frame_masked && (rt_update || (m_r.w <= (resolution.y * 2) && !m_texture_shuffle)));
|
||||
rt->UpdateDrawn(update_rect, !frame_masked && (rt_update || (m_r.w <= (resolution.y * 2) && !m_texture_shuffle)));
|
||||
|
||||
if (merge_targets)
|
||||
g_texture_cache->CombineAlignedInsideTargets(rt, src);
|
||||
// Probably changing to double buffering, so invalidate any old target that was next to it.
|
||||
// This resolves an issue where the PCRTC will find the old target in FMV's causing flashing.
|
||||
// Grandia Xtreme, Onimusha Warlord.
|
||||
@@ -3979,13 +3991,16 @@ void GSRendererHW::Draw()
|
||||
|
||||
if (z_width != new_w || z_height != new_h)
|
||||
{
|
||||
GSVector4i dRect = GSVector4i(0, 0, g_texture_cache->GetTemporaryZ()->GetWidth(), g_texture_cache->GetTemporaryZ()->GetHeight());
|
||||
|
||||
GSTexture* tex = g_gs_device->CreateDepthStencil(new_w * ds->m_scale, new_h * ds->m_scale, GSTexture::Format::DepthStencil, true);
|
||||
g_gs_device->StretchRect(g_texture_cache->GetTemporaryZ(), GSVector4(0.0f, 0.0f, 1.0f, 1.0f), tex, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
g_texture_cache->InvalidateTemporaryZ();
|
||||
g_texture_cache->SetTemporaryZ(tex);
|
||||
if (GSTexture* tex = g_gs_device->CreateDepthStencil(new_w * ds->m_scale, new_h * ds->m_scale, GSTexture::Format::DepthStencil, true))
|
||||
{
|
||||
const GSVector4i dRect = GSVector4i(0, 0, g_texture_cache->GetTemporaryZ()->GetWidth(), g_texture_cache->GetTemporaryZ()->GetHeight());
|
||||
g_gs_device->StretchRect(g_texture_cache->GetTemporaryZ(), GSVector4(0.0f, 0.0f, 1.0f, 1.0f), tex, GSVector4(dRect), ShaderConvert::DEPTH_COPY, false);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
g_texture_cache->InvalidateTemporaryZ();
|
||||
g_texture_cache->SetTemporaryZ(tex);
|
||||
}
|
||||
else
|
||||
DevCon.Warning("HW: Temporary depth buffer creation failed.");
|
||||
}
|
||||
}
|
||||
if (!m_texture_shuffle && !m_channel_shuffle)
|
||||
@@ -5015,6 +5030,8 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool
|
||||
// Hitman suffers from this, not sure on the exact scenario at the moment, but we need the barrier.
|
||||
if (PRIM->ABE && m_context->ALPHA.IsCdInBlend())
|
||||
{
|
||||
// Needed to enable IsFeedbackLoop.
|
||||
m_conf.ps.channel_fb = 1;
|
||||
// Assume no overlap when it's a channel shuffle, no need for full barriers.
|
||||
m_conf.require_one_barrier = true;
|
||||
}
|
||||
@@ -5923,9 +5940,6 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
|
||||
|
||||
m_conf.cb_ps.ScaleFactor = GSVector4(scale_factor * (1.0f / 16.0f), 1.0f / scale_factor, scale_rt, 0.0f);
|
||||
|
||||
if ((m_conf.ps.tex_is_fb && rt->m_rt_alpha_scale) || (tex->m_target && tex->m_from_target && tex->m_target_direct && tex->m_from_target->m_rt_alpha_scale))
|
||||
m_conf.ps.rta_source_correction = 1;
|
||||
|
||||
// Warning fetch the texture PSM format rather than the context format. The latter could have been corrected in the texture cache for depth.
|
||||
//const GSLocalMemory::psm_t &psm = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM];
|
||||
const GSLocalMemory::psm_t& psm = GSLocalMemory::m_psm[tex->m_TEX0.PSM];
|
||||
@@ -6296,56 +6310,58 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
|
||||
// Detect framebuffer read that will need special handling
|
||||
const GSTextureCache::Target* src_target = nullptr;
|
||||
|
||||
if (rt && m_conf.tex == m_conf.rt && !(m_channel_shuffle && tex && (tex_diff != frame_diff || target_region)))
|
||||
if (!m_downscale_source || !tex->m_from_target)
|
||||
{
|
||||
// Can we read the framebuffer directly? (i.e. sample location matches up).
|
||||
if (CanUseTexIsFB(rt, tex, tmm))
|
||||
if (rt && m_conf.tex == m_conf.rt && !(m_channel_shuffle && tex && (tex_diff != frame_diff || target_region)))
|
||||
{
|
||||
m_conf.tex = nullptr;
|
||||
m_conf.ps.tex_is_fb = true;
|
||||
if (m_prim_overlap == PRIM_OVERLAP_NO || !g_gs_device->Features().texture_barrier)
|
||||
m_conf.require_one_barrier = true;
|
||||
else
|
||||
m_conf.require_full_barrier = true;
|
||||
// Can we read the framebuffer directly? (i.e. sample location matches up).
|
||||
if (CanUseTexIsFB(rt, tex, tmm))
|
||||
{
|
||||
m_conf.tex = nullptr;
|
||||
m_conf.ps.tex_is_fb = true;
|
||||
if (m_prim_overlap == PRIM_OVERLAP_NO || !g_gs_device->Features().texture_barrier)
|
||||
m_conf.require_one_barrier = true;
|
||||
else
|
||||
m_conf.require_full_barrier = true;
|
||||
|
||||
unscaled_size = rt->GetUnscaledSize();
|
||||
scale = rt->GetScale();
|
||||
unscaled_size = rt->GetUnscaledSize();
|
||||
scale = rt->GetScale();
|
||||
return;
|
||||
}
|
||||
|
||||
GL_CACHE("HW: Source is render target, taking copy.");
|
||||
src_target = rt;
|
||||
}
|
||||
// Be careful of single page channel shuffles where depth is the source but it's not going to the same place, we can't read this directly.
|
||||
else if (ds && m_conf.tex == m_conf.ds && (!m_channel_shuffle || (rt && static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) == static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0))))
|
||||
{
|
||||
// GL, Vulkan (in General layout), not DirectX!
|
||||
const bool can_read_current_depth_buffer = g_gs_device->Features().test_and_sample_depth;
|
||||
|
||||
// If this is our current Z buffer, we might not be able to read it directly if it's being written to.
|
||||
// Rather than leaving the backend to do it, we'll check it here.
|
||||
if (can_read_current_depth_buffer && (m_cached_ctx.ZBUF.ZMSK || m_cached_ctx.TEST.ZTST == ZTST_NEVER))
|
||||
{
|
||||
// Safe to read!
|
||||
GL_CACHE("HW: Source is depth buffer, not writing, safe to read.");
|
||||
unscaled_size = ds->GetUnscaledSize();
|
||||
scale = ds->GetScale();
|
||||
return;
|
||||
}
|
||||
|
||||
// Can't safely read the depth buffer, so we need to take a copy of it.
|
||||
GL_CACHE("HW: Source is depth buffer, unsafe to read, taking copy.");
|
||||
src_target = ds;
|
||||
}
|
||||
else if (m_channel_shuffle && tex->m_from_target && tex_diff != frame_diff)
|
||||
{
|
||||
src_target = tex->m_from_target;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No match.
|
||||
return;
|
||||
}
|
||||
|
||||
GL_CACHE("HW: Source is render target, taking copy.");
|
||||
src_target = rt;
|
||||
}
|
||||
// Be careful of single page channel shuffles where depth is the source but it's not going to the same place, we can't read this directly.
|
||||
else if (ds && m_conf.tex == m_conf.ds && (!m_channel_shuffle || static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0) == static_cast<int>(m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0)))
|
||||
{
|
||||
// GL, Vulkan (in General layout), not DirectX!
|
||||
const bool can_read_current_depth_buffer = g_gs_device->Features().test_and_sample_depth;
|
||||
|
||||
// If this is our current Z buffer, we might not be able to read it directly if it's being written to.
|
||||
// Rather than leaving the backend to do it, we'll check it here.
|
||||
if (can_read_current_depth_buffer && (m_cached_ctx.ZBUF.ZMSK || m_cached_ctx.TEST.ZTST == ZTST_NEVER))
|
||||
{
|
||||
// Safe to read!
|
||||
GL_CACHE("HW: Source is depth buffer, not writing, safe to read.");
|
||||
unscaled_size = ds->GetUnscaledSize();
|
||||
scale = ds->GetScale();
|
||||
return;
|
||||
}
|
||||
|
||||
// Can't safely read the depth buffer, so we need to take a copy of it.
|
||||
GL_CACHE("HW: Source is depth buffer, unsafe to read, taking copy.");
|
||||
src_target = ds;
|
||||
}
|
||||
else if (m_channel_shuffle && tex->m_from_target && tex_diff != frame_diff)
|
||||
{
|
||||
src_target = tex->m_from_target;
|
||||
}
|
||||
else if (!m_downscale_source || !tex->m_from_target)
|
||||
{
|
||||
// No match.
|
||||
return;
|
||||
}
|
||||
else
|
||||
src_target = tex->m_from_target;
|
||||
@@ -6353,10 +6369,9 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
// We need to copy. Try to cut down the source range as much as possible so we don't copy texels we're not reading.
|
||||
const GSVector2i& src_unscaled_size = src_target->GetUnscaledSize();
|
||||
const GSVector4i src_bounds = src_target->GetUnscaledRect();
|
||||
GSVector4i copy_range;
|
||||
GSVector2i copy_size;
|
||||
GSVector2i copy_dst_offset;
|
||||
const bool copied_rt = src_target && !tex->m_shared_texture;
|
||||
GSVector4i copy_range = GSVector4i::zero();
|
||||
GSVector2i copy_size = GSVector2i(0);
|
||||
GSVector2i copy_dst_offset = GSVector2i(0);
|
||||
// Shuffles take the whole target. This should've already been halved.
|
||||
// We can't partially copy depth targets in DirectX, and GL/Vulkan should use the direct read above.
|
||||
// Restricting it also breaks Tom and Jerry...
|
||||
@@ -6480,21 +6495,15 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
|
||||
unscaled_size = copy_size;
|
||||
scale = m_downscale_source ? 1.0f : src_target->GetScale();
|
||||
const float src_scale = src_target->GetScale();
|
||||
GL_CACHE("HW: Copy size: %dx%d, range: %d,%d -> %d,%d (%dx%d) @ %.1f", copy_size.x, copy_size.y, copy_range.x,
|
||||
copy_range.y, copy_range.z, copy_range.w, copy_range.width(), copy_range.height(), scale);
|
||||
|
||||
const GSVector2i scaled_copy_size = GSVector2i(static_cast<int>(std::ceil(static_cast<float>(copy_size.x) * scale)),
|
||||
static_cast<int>(std::ceil(static_cast<float>(copy_size.y) * scale)));
|
||||
const GSVector4i scaled_copy_range = GSVector4i((GSVector4(copy_range) * GSVector4(src_scale)).ceil());
|
||||
const GSVector2i scaled_copy_dst_offset =
|
||||
GSVector2i(static_cast<int>(std::ceil(static_cast<float>(copy_dst_offset.x) * scale)),
|
||||
static_cast<int>(std::ceil(static_cast<float>(copy_dst_offset.y) * scale)));
|
||||
|
||||
src_copy.reset(src_target->m_texture->IsDepthStencil() ?
|
||||
g_gs_device->CreateDepthStencil(scaled_copy_size.x, scaled_copy_size.y, src_target->m_texture->GetFormat(), false) :
|
||||
(m_downscale_source || copied_rt) ? g_gs_device->CreateRenderTarget(scaled_copy_size.x, scaled_copy_size.y, src_target->m_texture->GetFormat(), true, true) :
|
||||
g_gs_device->CreateTexture(scaled_copy_size.x, scaled_copy_size.y, 1, src_target->m_texture->GetFormat(), true));
|
||||
g_gs_device->CreateRenderTarget(scaled_copy_size.x, scaled_copy_size.y, src_target->m_texture->GetFormat(), true, true));
|
||||
if (!src_copy) [[unlikely]]
|
||||
{
|
||||
Console.Error("HW: Failed to allocate %dx%d texture for hazard copy", scaled_copy_size.x, scaled_copy_size.y);
|
||||
@@ -6534,8 +6543,20 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||
}
|
||||
else
|
||||
{
|
||||
g_gs_device->CopyRect(
|
||||
src_target->m_texture, src_copy.get(), scaled_copy_range, scaled_copy_dst_offset.x, scaled_copy_dst_offset.y);
|
||||
g_perfmon.Put(GSPerfMon::TextureCopies, 1);
|
||||
const GSVector4i offset = copy_range - GSVector4i(copy_dst_offset).xyxy();
|
||||
|
||||
// Adjust for bilinear, must be done after calculating offset.
|
||||
copy_range.x -= 1;
|
||||
copy_range.y -= 1;
|
||||
copy_range.z += 1;
|
||||
copy_range.w += 1;
|
||||
copy_range = copy_range.rintersect(src_bounds);
|
||||
|
||||
const GSVector4 src_rect = GSVector4(copy_range) / GSVector4(src_unscaled_size).xyxy();
|
||||
const GSVector4 dst_rect = (GSVector4(copy_range) - GSVector4(offset).xyxy()) * scale;
|
||||
g_gs_device->StretchRect(src_target->m_texture, src_rect, src_copy.get(), dst_rect,
|
||||
src_target->m_texture->IsDepthStencil() ? ShaderConvert::DEPTH_COPY : ShaderConvert::COPY, false);
|
||||
}
|
||||
m_conf.tex = src_copy.get();
|
||||
}
|
||||
@@ -6630,7 +6651,7 @@ bool GSRendererHW::CanUseTexIsFB(const GSTextureCache::Target* rt, const GSTextu
|
||||
const GSLocalMemory::psm_t& rt_psm = GSLocalMemory::m_psm[rt->m_TEX0.PSM];
|
||||
if (tex_psm.pal > 0 && tex_psm.bpp < rt_psm.bpp)
|
||||
{
|
||||
GL_CACHE("HW: Disabling tex-is-fb due to palette conversion.");
|
||||
GL_CACHE("HW: Enabling tex-is-fb for palette conversion.");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -7115,6 +7136,19 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
new_scale_rt_alpha = rt->m_rt_alpha_scale;
|
||||
}
|
||||
|
||||
GSDevice::RecycledTexture tex_copy;
|
||||
if (tex)
|
||||
{
|
||||
EmulateTextureSampler(rt, ds, tex, tmm, tex_copy);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float scale_factor = rt ? rt->GetScale() : ds->GetScale();
|
||||
m_conf.cb_ps.ScaleFactor = GSVector4(scale_factor * (1.0f / 16.0f), 1.0f / scale_factor, scale_factor, 0.0f);
|
||||
|
||||
m_conf.ps.tfx = 4;
|
||||
}
|
||||
|
||||
// AA1: Set alpha source to coverage 128 when there is no alpha blending.
|
||||
m_conf.ps.fixed_one_a = IsCoverageAlpha();
|
||||
|
||||
@@ -7138,6 +7172,9 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_conf.ps.tex_is_fb && rt && rt->m_rt_alpha_scale) || (tex && tex->m_from_target && tex->m_target_direct && tex->m_from_target->m_rt_alpha_scale))
|
||||
m_conf.ps.rta_source_correction = 1;
|
||||
|
||||
if (req_src_update && tex->m_texture != rt->m_texture)
|
||||
tex->m_texture = rt->m_texture;
|
||||
|
||||
@@ -7270,8 +7307,25 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
if (m_conf.destination_alpha >= GSHWDrawConfig::DestinationAlphaMode::Stencil &&
|
||||
m_conf.destination_alpha <= GSHWDrawConfig::DestinationAlphaMode::StencilOne && !m_conf.ds)
|
||||
{
|
||||
temp_ds.reset(g_gs_device->CreateDepthStencil(m_conf.rt->GetWidth(), m_conf.rt->GetHeight(), GSTexture::Format::DepthStencil, false));
|
||||
m_conf.ds = temp_ds.get();
|
||||
const bool is_one_barrier = (m_conf.require_full_barrier && (m_prim_overlap == PRIM_OVERLAP_NO || m_conf.ps.shuffle || m_channel_shuffle));
|
||||
if ((temp_ds.reset(g_gs_device->CreateDepthStencil(m_conf.rt->GetWidth(), m_conf.rt->GetHeight(), GSTexture::Format::DepthStencil, false)), temp_ds))
|
||||
{
|
||||
m_conf.ds = temp_ds.get();
|
||||
}
|
||||
else if (features.primitive_id && !(m_conf.ps.scanmsk & 2) && (!m_conf.require_full_barrier || is_one_barrier))
|
||||
{
|
||||
DATE_one = false;
|
||||
DATE_PRIMID = true;
|
||||
m_conf.destination_alpha = GSHWDrawConfig::DestinationAlphaMode::PrimIDTracking;
|
||||
DevCon.Warning("HW: Depth buffer creation failed for Stencil Date. Fallback to PrimIDTracking.");
|
||||
}
|
||||
else
|
||||
{
|
||||
DATE = false;
|
||||
DATE_one = false;
|
||||
m_conf.destination_alpha = GSHWDrawConfig::DestinationAlphaMode::Off;
|
||||
DevCon.Warning("HW: Depth buffer creation failed for Stencil Date.");
|
||||
}
|
||||
}
|
||||
|
||||
// vs
|
||||
@@ -7404,18 +7458,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
m_conf.cb_ps.FogColor_AREF = fc.blend32<8>(m_conf.cb_ps.FogColor_AREF);
|
||||
}
|
||||
|
||||
GSDevice::RecycledTexture tex_copy;
|
||||
if (tex)
|
||||
{
|
||||
EmulateTextureSampler(rt, ds, tex, tmm, tex_copy);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float scale_factor = rt ? rt->GetScale() : ds->GetScale();
|
||||
m_conf.cb_ps.ScaleFactor = GSVector4(scale_factor * (1.0f / 16.0f), 1.0f / scale_factor, scale_factor, 0.0f);
|
||||
|
||||
m_conf.ps.tfx = 4;
|
||||
}
|
||||
|
||||
// Update RT scaled alpha flag, nothing's going to read it anymore.
|
||||
if (rt)
|
||||
|
||||
@@ -240,7 +240,7 @@ bool GSTextureCache::CanTranslate(u32 bp, u32 bw, u32 spsm, GSVector4i r, u32 db
|
||||
const bool page_aligned_rect = masked_rect.xyxy().eq(r.xyxy());
|
||||
const bool width_match = ((bw * 64) / src_page_size.x) == ((dbw * 64) / dst_page_size.x);
|
||||
const bool sequential_pages = page_aligned_rect && r.x == 0 && r.z == src_pixel_width;
|
||||
const bool single_row = (((bw * 64) / src_page_size.x) <= ((dbw * 64) / dst_page_size.x)) && r.z <= src_pixel_width && r.w <= src_page_size.y;
|
||||
const bool single_row = (((bw * 64) / src_page_size.x) <= ((dbw * 64) / dst_page_size.x)) && r.width() <= src_pixel_width && r.height() <= src_page_size.y;
|
||||
const bool single_page_aligned = page_aligned_rect && r.z <= src_page_size.x && r.w <= src_page_size.y;
|
||||
if (block_layout_match)
|
||||
{
|
||||
@@ -998,7 +998,7 @@ __ri static GSTextureCache::Source* FindSourceInMap(const GIFRegTEX0& TEX0, cons
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const u32 frame_fbp, bool req_color, bool req_alpha, bool palette)
|
||||
GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const GIFRegFRAME& frame, bool req_color, bool req_alpha, bool palette)
|
||||
{
|
||||
if (GSConfig.UserHacks_DisableDepthSupport)
|
||||
{
|
||||
@@ -1183,7 +1183,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, c
|
||||
else
|
||||
{
|
||||
// This is a bit of a worry, since it could load junk from local memory... but it's better than skipping the draw.
|
||||
return is_depth ? LookupSource(false, TEX0, TEXA, CLAMP, r, nullptr, possible_shuffle, linear, frame_fbp, req_color, req_alpha) : nullptr;
|
||||
return is_depth ? LookupSource(false, TEX0, TEXA, CLAMP, r, nullptr, possible_shuffle, linear, frame, req_color, req_alpha) : nullptr;
|
||||
}
|
||||
|
||||
pxAssert(src->m_texture);
|
||||
@@ -1192,7 +1192,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, c
|
||||
return src;
|
||||
}
|
||||
|
||||
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 u32 frame_fbp, bool req_color, bool req_alpha)
|
||||
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);
|
||||
|
||||
@@ -1412,7 +1412,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
{
|
||||
for (auto& dirty : t->m_dirty)
|
||||
{
|
||||
GSVector4i dirty_rect = dirty.GetDirtyRect(t->m_TEX0, t->m_TEX0.PSM != dirty.psm);
|
||||
const GSVector4i dirty_rect = dirty.GetDirtyRect(t->m_TEX0, t->m_TEX0.PSM != dirty.psm);
|
||||
if (!dirty_rect.rintersect(new_rect).rempty())
|
||||
{
|
||||
rect_clean = false;
|
||||
@@ -1426,10 +1426,19 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
const u32 channels = t->m_dirty.GetDirtyChannels() & channel_mask;
|
||||
|
||||
// If the source is reading the rt, make sure it's big enough.
|
||||
if (!possible_shuffle && t && GSUtil::HasCompatibleBits(psm, t->m_TEX0.PSM) && real_fmt_match)
|
||||
if (!possible_shuffle && t && GSUtil::HasCompatibleBits(psm, t->m_TEX0.PSM)&& real_fmt_match)
|
||||
{
|
||||
// Be careful if a new texture has been uploaded that expands the current one (Valkyrie Profile 2 does this)
|
||||
GSVector4i dirty_rect = (t->m_dirty.size() > 0 && bw == t->m_TEX0.TBW) ? t->m_dirty.GetTotalRect(t->m_TEX0, GSVector2i(new_rect.z, new_rect.w)) : GSVector4i(GSVector4(t->m_valid) * GSVector4(2));
|
||||
// Try to clamp the size of the target when using repeat, we don't want it getting too huge.
|
||||
GSVector4i resize_rect = new_rect;
|
||||
if (CLAMP.WMS == 0 || CLAMP.WMS == 3)
|
||||
resize_rect.z = std::min(resize_rect.z, static_cast<int>(t->m_TEX0.TBW) * 64);
|
||||
if ((CLAMP.WMT == 0 || CLAMP.WMT == 3) && resize_rect.w > (t->m_valid.w * 2))
|
||||
resize_rect.w = std::min(resize_rect.w, std::max(t->m_valid.w * 2, dirty_rect.w));
|
||||
|
||||
if (t->Overlaps(bp, bw, psm, new_rect))
|
||||
ResizeTarget(t, new_rect, bp, psm, bw);
|
||||
ResizeTarget(t, resize_rect, bp, psm, bw);
|
||||
}
|
||||
// If not all channels are clean/dirty or only part of the rect is dirty, we need to update the target.
|
||||
if (((channels & channel_mask) != channel_mask || partial))
|
||||
@@ -1447,7 +1456,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
else
|
||||
{
|
||||
rect_clean = t->m_dirty.empty();
|
||||
if (!possible_shuffle && frame_fbp != t->m_TEX0.TBP0 && rect_clean && bp == t->m_TEX0.TBP0 && t && GSUtil::HasCompatibleBits(psm, t->m_TEX0.PSM) && width_match && real_fmt_match)
|
||||
if (!possible_shuffle && frame.Block() != t->m_TEX0.TBP0 && rect_clean && bp == t->m_TEX0.TBP0 && t && GSUtil::HasCompatibleBits(psm, t->m_TEX0.PSM) && width_match && real_fmt_match)
|
||||
{
|
||||
if (!tex_merge_rt && t->Overlaps(bp, bw, psm, req_rect))
|
||||
{
|
||||
@@ -1462,13 +1471,21 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
if (block_boundary_rect.w > t->m_valid.w)
|
||||
AddDirtyRectTarget(t, GSVector4i(t->m_valid.x, t->m_valid.w, std::max(block_boundary_rect.z, t->m_valid.z), block_boundary_rect.w), t->m_TEX0.PSM, t->m_TEX0.TBW, rgba_mask);
|
||||
}
|
||||
|
||||
// Try to clamp the size of the target when using repeat, we don't want it getting too huge.
|
||||
GSVector4i resize_rect = req_rect;
|
||||
if (CLAMP.WMS == 0 || CLAMP.WMS == 3)
|
||||
resize_rect.z = std::min(resize_rect.z, static_cast<int>(t->m_TEX0.TBW) * 64);
|
||||
if ((CLAMP.WMT == 0 || CLAMP.WMT == 3) && resize_rect.w > (t->m_valid.w * 2))
|
||||
resize_rect.w = std::min(resize_rect.w, t->m_valid.w * 2);
|
||||
|
||||
// Resize including the extra pixel for bilinear.
|
||||
ResizeTarget(t, req_rect, bp, psm, bw);
|
||||
ResizeTarget(t, resize_rect, bp, psm, bw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (t->m_TEX0.TBP0 != frame_fbp && !possible_shuffle && bp > t->m_TEX0.TBP0 && t->Overlaps(bp, bw, psm, req_rect) && GSUtil::GetChannelMask(psm) == GSUtil::GetChannelMask(t->m_TEX0.PSM) && !width_match)
|
||||
if (t->m_TEX0.TBP0 != frame.Block() && !possible_shuffle && bp > t->m_TEX0.TBP0 && t->Overlaps(bp, bw, psm, req_rect) && GSUtil::GetChannelMask(psm) == GSUtil::GetChannelMask(t->m_TEX0.PSM) && !width_match)
|
||||
{
|
||||
GSVector4i new_rect = req_rect;
|
||||
|
||||
@@ -1633,6 +1650,10 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
{
|
||||
u32 rt_tbw = std::max(1U, t->m_TEX0.TBW);
|
||||
u32 horz_page_offset = ((bp - t->m_TEX0.TBP0) >> 5) % rt_tbw;
|
||||
|
||||
if (GSLocalMemory::m_psm[psm].bpp == GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp && bw != rt_tbw && block_boundary_rect.height() > GSLocalMemory::m_psm[psm].pgs.y)
|
||||
continue;
|
||||
|
||||
if (GSLocalMemory::m_psm[color_psm].bpp == 16 && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == 32 && bw != 1 &&
|
||||
((t->m_TEX0.TBW < (horz_page_offset + ((block_boundary_rect.z + GSLocalMemory::m_psm[psm].pgs.x - 1) / GSLocalMemory::m_psm[psm].pgs.x)) ||
|
||||
(t->m_TEX0.TBW != bw && block_boundary_rect.w > GSLocalMemory::m_psm[psm].pgs.y))))
|
||||
@@ -1689,11 +1710,12 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
|
||||
GSVector4i new_rect = (GSLocalMemory::m_psm[color_psm].bpp != GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp && (psm & 0x7) != PSMCT16) ? block_boundary_rect : rect;
|
||||
|
||||
// Check if it is possible to hit with valid <x,y> offset on the given Target.
|
||||
// Fixes Jak eyes rendering.
|
||||
// Fixes Xenosaga 3 last dungeon graphic bug.
|
||||
// Fixes Pause menu in The Getaway.
|
||||
const bool can_translate = CanTranslate(bp, bw, src_psm, new_rect, t->m_TEX0.TBP0, t->m_TEX0.PSM, t->m_TEX0.TBW);
|
||||
// If the sizing is completely wrong on the frame vs the source when reading from alpha then it's likely the target has 2 different sizes for rgb and alpha.
|
||||
// This is just changing the target width for the rect translation, it has no bearing on the actual source read or the target itself.
|
||||
// Hitman Blood Money is an example of this in the theatre.
|
||||
const u32 rt_tbw = (possible_shuffle || bw == 1 || GSUtil::GetChannelMask(psm) != 0x8 || frame.FBW <= bw || frame.FBW == t->m_TEX0.TBW) ? t->m_TEX0.TBW : frame.FBW;
|
||||
|
||||
const bool can_translate = CanTranslate(bp, bw, src_psm, new_rect, t->m_TEX0.TBP0, t->m_TEX0.PSM, rt_tbw);
|
||||
if (can_translate)
|
||||
{
|
||||
const bool swizzle_match = GSLocalMemory::m_psm[src_psm].depth == GSLocalMemory::m_psm[t->m_TEX0.PSM].depth;
|
||||
@@ -1703,7 +1725,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
|
||||
if (swizzle_match)
|
||||
{
|
||||
rect = TranslateAlignedRectByPage(t, bp, src_psm, bw, new_rect);
|
||||
rect = TranslateAlignedRectByPage(t->m_TEX0.TBP0, t->m_end_block, rt_tbw, t->m_TEX0.PSM, bp, src_psm, bw, new_rect);
|
||||
rect.x -= new_rect.x;
|
||||
rect.y -= new_rect.y;
|
||||
}
|
||||
@@ -1752,7 +1774,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
dst = t;
|
||||
tex_merge_rt = false;
|
||||
found_t = true;
|
||||
if (dst->m_TEX0.TBP0 == frame_fbp && possible_shuffle)
|
||||
if (dst->m_TEX0.TBP0 == frame.Block() && possible_shuffle)
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
@@ -1778,7 +1800,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
tex_merge_rt = false;
|
||||
found_t = true;
|
||||
// Keep looking, just in case there is an exact match (Situation: Target frame drawn inside target frame, current makes a separate texture)
|
||||
if (dst->m_TEX0.TBP0 == frame_fbp && possible_shuffle)
|
||||
if (dst->m_TEX0.TBP0 == frame.Block() && possible_shuffle)
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
@@ -1835,7 +1857,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
break;
|
||||
}
|
||||
|
||||
if (dst->m_TEX0.TBP0 == frame_fbp && possible_shuffle)
|
||||
if (dst->m_TEX0.TBP0 == frame.Block() && possible_shuffle)
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
@@ -1852,7 +1874,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
|
||||
// Prefer a target inside over a target outside.
|
||||
found_t = false;
|
||||
if (dst->m_TEX0.TBP0 == frame_fbp && possible_shuffle)
|
||||
if (dst->m_TEX0.TBP0 == frame.Block() && possible_shuffle)
|
||||
break;
|
||||
else
|
||||
continue;
|
||||
@@ -1913,7 +1935,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
GIFRegTEX0 depth_TEX0;
|
||||
depth_TEX0.U32[0] = TEX0.U32[0] | (0x30u << 20u);
|
||||
depth_TEX0.U32[1] = TEX0.U32[1];
|
||||
src = LookupDepthSource(false, depth_TEX0, TEXA, CLAMP, block_boundary_rect, possible_shuffle, linear, frame_fbp, req_color, req_alpha);
|
||||
src = LookupDepthSource(false, depth_TEX0, TEXA, CLAMP, block_boundary_rect, possible_shuffle, linear, frame, req_color, req_alpha);
|
||||
|
||||
if (src != nullptr)
|
||||
{
|
||||
@@ -1935,7 +1957,7 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
}
|
||||
else
|
||||
{
|
||||
src = LookupDepthSource(false, TEX0, TEXA, CLAMP, block_boundary_rect, possible_shuffle, linear, frame_fbp, req_color, req_alpha, true);
|
||||
src = LookupDepthSource(false, TEX0, TEXA, CLAMP, block_boundary_rect, possible_shuffle, linear, frame, req_color, req_alpha, true);
|
||||
|
||||
if (src != nullptr)
|
||||
{
|
||||
@@ -2075,7 +2097,7 @@ void GSTextureCache::CombineAlignedInsideTargets(Target* target, GSTextureCache:
|
||||
if (t != target)
|
||||
{
|
||||
// Target not contained, skip it.
|
||||
if (t->m_TEX0.TBP0 < target->m_TEX0.TBP0 || t->m_end_block > target->m_end_block)
|
||||
if (t->m_TEX0.TBP0 < target->m_TEX0.TBP0 || t->UnwrappedEndBlock() > target->UnwrappedEndBlock())
|
||||
{
|
||||
i++;
|
||||
continue;
|
||||
@@ -2089,14 +2111,27 @@ void GSTextureCache::CombineAlignedInsideTargets(Target* target, GSTextureCache:
|
||||
|
||||
if ((page_offset + page_width) <= target->m_TEX0.TBW)
|
||||
{
|
||||
const u32 vertical_offset = (((t->m_TEX0.TBP0 - target->m_TEX0.TBP0) >> 5) / std::max(1U, t->m_TEX0.TBW)) * t_psm.pgs.y;
|
||||
const u32 horizontal_offset = page_offset * t_psm.pgs.x;
|
||||
const GSVector4i target_drect_unscaled = t->m_valid + GSVector4i(horizontal_offset, vertical_offset).xyxy();
|
||||
const GSVector4 target_drect = GSVector4(target_drect_unscaled) * target->m_scale;
|
||||
if (t->m_last_draw > target->m_last_draw || t->m_valid.rintersect(target->m_valid).rempty())
|
||||
{
|
||||
if (!t->m_drawn_since_read.rempty())
|
||||
{
|
||||
t->Update();
|
||||
|
||||
g_gs_device->StretchRect(t->m_texture, GSVector4(0, 0, 1, 1), target->m_texture, target_drect, (target->m_type == RenderTarget) ? ShaderConvert::COPY : ShaderConvert::DEPTH_COPY, t->m_scale < target->m_scale);
|
||||
const u32 vertical_offset = (((t->m_TEX0.TBP0 - target->m_TEX0.TBP0) >> 5) / std::max(1U, t->m_TEX0.TBW)) * t_psm.pgs.y;
|
||||
const u32 horizontal_offset = page_offset * t_psm.pgs.x;
|
||||
const GSVector4i target_drect_unscaled = t->m_drawn_since_read + GSVector4i(horizontal_offset, vertical_offset).xyxy();
|
||||
|
||||
target->UpdateValidity(target_drect_unscaled);
|
||||
const GSVector4 source_rect = GSVector4(t->m_drawn_since_read) / (GSVector4(t->m_unscaled_size) * t->GetScale());
|
||||
const GSVector4 target_drect = GSVector4(target_drect_unscaled) * target->m_scale;
|
||||
|
||||
const bool valid_color = t->m_valid_rgb;
|
||||
const bool valid_alpha = (t->m_valid_alpha_high | t->m_valid_alpha_low) && (GSUtil::GetChannelMask(t->m_TEX0.PSM) & 0x8);
|
||||
|
||||
g_gs_device->StretchRect(t->m_texture, source_rect, target->m_texture, target_drect, valid_color, valid_color, valid_color, valid_alpha, (target->m_type == RenderTarget) ? ShaderConvert::COPY : ShaderConvert::DEPTH_COPY);
|
||||
|
||||
target->UpdateValidity(target_drect_unscaled);
|
||||
}
|
||||
}
|
||||
|
||||
if (src && src->m_from_target == t)
|
||||
{
|
||||
@@ -2252,10 +2287,12 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
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)));
|
||||
const bool width_match = (t->m_TEX0.TBW == TEX0.TBW || (TEX0.TBW == 1 && draw_rect.w <= GSLocalMemory::m_psm[t->m_TEX0.PSM].pgs.y));
|
||||
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);
|
||||
// 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 (no_target_or_newer && is_aligned_ok && width_match && overlaps)
|
||||
if (no_target_or_newer && is_aligned_ok && width_match && overlaps && (is_shuffle || ds_offset || is_double_buffer))
|
||||
{
|
||||
const GSLocalMemory::psm_t& s_psm = GSLocalMemory::m_psm[TEX0.PSM];
|
||||
|
||||
@@ -2286,13 +2323,33 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
InvalidateSourcesFromTarget(t);
|
||||
i = list.erase(i);
|
||||
delete t;
|
||||
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (t->m_dirty.empty() || (t->m_TEX0.TBP0 <= bp && t->m_last_draw >= (GSState::s_n - 1) &&
|
||||
t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size).rintersect(GSVector4i(0, 0, 0, 0).max_i32(TranslateAlignedRectByPage(t, TEX0.TBP0, TEX0.PSM, TEX0.TBW, min_rect))).rempty()))
|
||||
|
||||
GSVector4i lookup_rect = min_rect;
|
||||
|
||||
if (is_shuffle)
|
||||
lookup_rect = lookup_rect & GSVector4i(~8);
|
||||
|
||||
const GSVector4i translated_rect = GSVector4i(0, 0, 0, 0).max_i32(TranslateAlignedRectByPage(t, TEX0.TBP0, TEX0.PSM, TEX0.TBW, lookup_rect));
|
||||
const GSVector4i dirty_rect = t->m_dirty.empty() ? GSVector4i::zero() : t->m_dirty.GetTotalRect(t->m_TEX0, t->m_unscaled_size).rintersect(t->m_valid);
|
||||
const bool all_dirty = dirty_rect.eq(t->m_valid);
|
||||
|
||||
|
||||
if (!is_shuffle && !t->m_dirty.empty() && (!preserve_alpha && !preserve_rgb) && (GSState::s_n - 1) != t->m_last_draw)
|
||||
{
|
||||
if (TEX0.TBW == t->m_TEX0.TBW && !is_shuffle && widthpage_offset == 0 && ((min_rect.w + 63)/ 64) > 1)
|
||||
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));
|
||||
InvalidateSourcesFromTarget(t);
|
||||
i = list.erase(i);
|
||||
delete t;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!all_dirty && ((translated_rect.w <= t->m_valid.w) || widthpage_offset == 0 || (GSState::s_n - 1) == t->m_last_draw))
|
||||
{
|
||||
if (TEX0.TBW == t->m_TEX0.TBW && !is_shuffle && widthpage_offset == 0 && ((min_rect.w + 63) / 64) > 1)
|
||||
{
|
||||
// Beyond Good and Evil does this awful thing where it puts one framebuffer at 0xf00, with the first row of pages blanked out, and the whole thing goes down to 0x2080
|
||||
// which is a problem, because it then puts the Z buffer at 0x1fc0, then offsets THAT by 1 row of pages, so it starts at, you guessed it, 2080.
|
||||
@@ -3036,6 +3093,8 @@ GSTextureCache::Target* GSTextureCache::CreateTarget(GIFRegTEX0 TEX0, const GSVe
|
||||
else
|
||||
dst->m_last_draw += 1; // If we preload and it needs to decorrect and we couldn't catch it early, we need to make sure it decorrects the data.
|
||||
|
||||
CombineAlignedInsideTargets(dst, src);
|
||||
|
||||
pxAssert(dst && dst->m_texture && dst->m_scale == scale);
|
||||
return dst;
|
||||
}
|
||||
@@ -3859,8 +3918,9 @@ void GSTextureCache::InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 wr
|
||||
continue;
|
||||
}
|
||||
|
||||
// If not fully contained, just dirty the area.
|
||||
if (start_bp != t->m_TEX0.TBP0 && (t->m_TEX0.TBP0 < start_bp || t->UnwrappedEndBlock() > end_bp))
|
||||
const u32 offset = (std::abs(static_cast<int>(start_bp - t->m_TEX0.TBP0)) >> 5) % std::max(1U, t->m_TEX0.TBW);
|
||||
// If not fully contained but they are aligned and or clean, just dirty the area.
|
||||
if (start_bp != t->m_TEX0.TBP0 && (t->m_TEX0.TBP0 < start_bp || t->UnwrappedEndBlock() > end_bp) && (offset == 0 || t->m_dirty.size() == 0))
|
||||
{
|
||||
if (write_bw == t->m_TEX0.TBW && GSLocalMemory::m_psm[t->m_TEX0.PSM].bpp == GSLocalMemory::m_psm[write_psm].bpp)
|
||||
{
|
||||
@@ -4599,6 +4659,9 @@ bool GSTextureCache::Move(u32 SBP, u32 SBW, u32 SPSM, int sx, int sy, u32 DBP, u
|
||||
dst = LookupTarget(new_TEX0, target_size, src->m_scale, src->m_type);
|
||||
if (!dst)
|
||||
dst = CreateTarget(new_TEX0, target_size, target_size, src->m_scale, src->m_type);
|
||||
else // Expand if necessary (Silent hill 4 takes an old target which is smaller).
|
||||
dst->ResizeTexture(std::max(dst->m_unscaled_size.x, target_size.x), std::max(dst->m_unscaled_size.y, target_size.y));
|
||||
|
||||
if (!dst)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -494,8 +494,8 @@ public:
|
||||
GSTexture* LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVector2i& offset, float* scale, const GSVector2i& size);
|
||||
std::shared_ptr<Palette> LookupPaletteObject(const u32* clut, u16 pal, bool need_gs_texture);
|
||||
|
||||
Source* 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 u32 frame_fbp = 0xFFFFFFFF, bool req_color = true, bool req_alpha = true);
|
||||
Source* LookupDepthSource(const bool is_depth, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const u32 frame_fbp = 0xFFFFFFFF, bool req_color = true, bool req_alpha = true, bool palette = false);
|
||||
Source* 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 = true, bool req_alpha = true);
|
||||
Source* LookupDepthSource(const bool is_depth, const GIFRegTEX0& TEX0, const GIFRegTEXA& TEXA, const GIFRegCLAMP& CLAMP, const GSVector4i& r, const bool possible_shuffle, const bool linear, const GIFRegFRAME& frame, bool req_color = true, bool req_alpha = true, bool palette = false);
|
||||
|
||||
Target* FindTargetOverlap(Target* target, int type, int psm);
|
||||
void CombineAlignedInsideTargets(Target* target, GSTextureCache::Source* src = nullptr);
|
||||
|
||||
@@ -244,6 +244,7 @@ namespace FullscreenUI
|
||||
void DrawSvgTexture(GSTexture* padded_texture, ImVec2 unpadded_size);
|
||||
void DrawCachedSvgTexture(const std::string& path, ImVec2 size, SvgScaling mode);
|
||||
void DrawCachedSvgTextureAsync(const std::string& path, ImVec2 size, SvgScaling mode);
|
||||
void DrawListSvgTexture(ImDrawList* drawList, GSTexture* padded_texture, const ImVec2& p_min, const ImVec2& p_unpadded_max);
|
||||
|
||||
static MainWindowType s_current_main_window = MainWindowType::None;
|
||||
static PauseSubMenu s_current_pause_submenu = PauseSubMenu::None;
|
||||
@@ -269,6 +270,7 @@ namespace FullscreenUI
|
||||
|
||||
static std::array<std::shared_ptr<GSTexture>, static_cast<u32>(GameDatabaseSchema::Compatibility::Perfect)>
|
||||
s_game_compatibility_textures;
|
||||
static std::shared_ptr<GSTexture> s_banner_texture;
|
||||
static std::shared_ptr<GSTexture> s_fallback_disc_texture;
|
||||
static std::shared_ptr<GSTexture> s_fallback_exe_texture;
|
||||
static std::vector<std::unique_ptr<GSTexture>> s_cleanup_textures;
|
||||
@@ -611,7 +613,7 @@ void FullscreenUI::ApplyLayoutSettings(const SettingsInterface* bsi)
|
||||
|
||||
const InputLayout layout = ImGuiFullscreen::GetGamepadLayout();
|
||||
|
||||
if (sdl2_nintendo_mode == "true" || (sdl2_nintendo_mode == "auto") && layout == InputLayout::Nintendo)
|
||||
if ((sdl2_nintendo_mode == "true" || sdl2_nintendo_mode == "auto") && layout == InputLayout::Nintendo)
|
||||
{
|
||||
// Apply
|
||||
ImGuiManager::SwapGamepadNorthWest(true);
|
||||
@@ -715,6 +717,23 @@ void FullscreenUI::DrawCachedSvgTextureAsync(const std::string& path, ImVec2 siz
|
||||
DrawSvgTexture(GetCachedSvgTextureAsync(path, size, mode), size);
|
||||
}
|
||||
|
||||
// p_unpadded_max should be equal to p_min + unpadded_size
|
||||
void FullscreenUI::DrawListSvgTexture(ImDrawList* drawList, GSTexture* padded_texture, const ImVec2& p_min, const ImVec2& p_unpadded_max)
|
||||
{
|
||||
const ImVec2 unpadded_size = p_unpadded_max - p_min;
|
||||
if (padded_texture != GetPlaceholderTexture().get())
|
||||
{
|
||||
const ImVec2 padded_size(padded_texture->GetWidth(), padded_texture->GetHeight());
|
||||
const ImVec2 uv1 = unpadded_size / padded_size;
|
||||
drawList->AddImage(reinterpret_cast<ImTextureID>(padded_texture->GetNativeHandle()), p_min, p_unpadded_max, ImVec2(0.0f, 0.0f), uv1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Placeholder is a png file and should be scaled by ImGui
|
||||
drawList->AddImage(reinterpret_cast<ImTextureID>(padded_texture->GetNativeHandle()), p_min, p_unpadded_max);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// Main
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1096,6 +1115,8 @@ bool FullscreenUI::LoadResources()
|
||||
|
||||
bool FullscreenUI::LoadSvgResources()
|
||||
{
|
||||
s_banner_texture = LoadSvgTexture("icons/AppBanner.svg", LayoutScale(500.0f, 76.0f), SvgScaling::Fit);
|
||||
|
||||
for (u32 i = static_cast<u32>(GameDatabaseSchema::Compatibility::Nothing);
|
||||
i <= static_cast<u32>(GameDatabaseSchema::Compatibility::Perfect); i++)
|
||||
{
|
||||
@@ -1109,6 +1130,7 @@ void FullscreenUI::DestroyResources()
|
||||
{
|
||||
s_fallback_exe_texture.reset();
|
||||
s_fallback_disc_texture.reset();
|
||||
s_banner_texture.reset();
|
||||
for (auto& tex : s_game_compatibility_textures)
|
||||
tex.reset();
|
||||
for (auto& tex : s_cleanup_textures)
|
||||
@@ -7017,7 +7039,7 @@ void FullscreenUI::OpenAboutWindow()
|
||||
|
||||
void FullscreenUI::DrawAboutWindow()
|
||||
{
|
||||
ImGui::SetNextWindowSize(LayoutScale(1000.0f, 580.0f));
|
||||
ImGui::SetNextWindowSize(LayoutScale(1000.0f, 600.0f));
|
||||
ImGui::SetNextWindowPos(ImGui::GetIO().DisplaySize * 0.5f, ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
ImGui::OpenPopup(FSUI_CSTR("About PCSX2"));
|
||||
|
||||
@@ -7027,21 +7049,24 @@ void FullscreenUI::DrawAboutWindow()
|
||||
|
||||
if (ImGui::BeginPopupModal(FSUI_CSTR("About PCSX2"), &s_about_window_open, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize))
|
||||
{
|
||||
const ImVec2 image_size = LayoutScale(500.0f, 76.0f);
|
||||
const ImRect image_bb(ImGui::GetCursorScreenPos(), ImGui::GetCursorScreenPos() + ImVec2(ImGui::GetCurrentWindow()->WorkRect.GetWidth(), image_size.y));
|
||||
const ImRect image_rect(CenterImage(image_bb, image_size));
|
||||
|
||||
DrawListSvgTexture(ImGui::GetWindowDrawList(), s_banner_texture.get(), image_rect.Min, image_rect.Max);
|
||||
|
||||
const float indent = image_size.y + LayoutScale(12.0f);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + indent);
|
||||
ImGui::TextWrapped("%s", FSUI_CSTR(
|
||||
"PCSX2 is a free and open-source PlayStation 2 (PS2) emulator. Its purpose is to emulate the PS2's hardware, using a "
|
||||
"combination of MIPS CPU Interpreters, Recompilers and a Virtual Machine which manages hardware states and PS2 system memory. "
|
||||
"This allows you to play PS2 games on your PC, with many additional features and benefits."));
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::TextWrapped(FSUI_CSTR("Version: %s"), BuildVersion::GitRev);
|
||||
ImGui::NewLine();
|
||||
|
||||
ImGui::TextWrapped("%s",
|
||||
FSUI_CSTR("PlayStation 2 and PS2 are registered trademarks of Sony Interactive Entertainment. This application is not "
|
||||
"affiliated in any way with Sony Interactive Entertainment."));
|
||||
|
||||
ImGui::NewLine();
|
||||
|
||||
BeginMenuButtons();
|
||||
|
||||
if (ActiveButton(FSUI_ICONSTR(ICON_FA_GLOBE, "Website"), false))
|
||||
@@ -7068,6 +7093,10 @@ void FullscreenUI::DrawAboutWindow()
|
||||
|
||||
EndMenuButtons();
|
||||
|
||||
const float alignment = image_size.x + image_size.y;
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + alignment);
|
||||
ImGui::TextWrapped(FSUI_CSTR("Version: %s"), BuildVersion::GitRev);
|
||||
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
@@ -7803,8 +7832,8 @@ TRANSLATE_NOOP("FullscreenUI", "Identifies any new files added to the game direc
|
||||
TRANSLATE_NOOP("FullscreenUI", "Forces a full rescan of all games previously identified.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "About PCSX2");
|
||||
TRANSLATE_NOOP("FullscreenUI", "PCSX2 is a free and open-source PlayStation 2 (PS2) emulator. Its purpose is to emulate the PS2's hardware, using a combination of MIPS CPU Interpreters, Recompilers and a Virtual Machine which manages hardware states and PS2 system memory. This allows you to play PS2 games on your PC, with many additional features and benefits.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Version: %s");
|
||||
TRANSLATE_NOOP("FullscreenUI", "PlayStation 2 and PS2 are registered trademarks of Sony Interactive Entertainment. This application is not affiliated in any way with Sony Interactive Entertainment.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Version: %s");
|
||||
TRANSLATE_NOOP("FullscreenUI", "When enabled and logged in, PCSX2 will scan for achievements on startup.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "\"Challenge\" mode for achievements, including leaderboard tracking. Disables save state, cheats, and slowdown functions.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages on events such as achievement unlocks and leaderboard submissions.");
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
||||
/// shaders change, to invalidate the cache.
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 64;
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 65;
|
||||
|
||||
Reference in New Issue
Block a user