Compare commits
121 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0064976c43 | |||
| 4bdb6674eb | |||
| c7f7d7ef5b | |||
| 2c19fdf092 | |||
| 8fc9862614 | |||
| 55d84414ee | |||
| 8c0bdd71d9 | |||
| 3c9126d91f | |||
| 8b4836a12f | |||
| b2a7eee1ec | |||
| ed21bb309f | |||
| 7b3e4f5e3d | |||
| 30b3af0d12 | |||
| 541cb4062b | |||
| 4e9160104a | |||
| 86fa379c78 | |||
| 8733505d0a | |||
| 242611aa46 | |||
| baa5a261a5 | |||
| 3730b9d1da | |||
| 0d35363ea0 | |||
| 75504b3f5e | |||
| 4ca98e53a6 | |||
| 300a36d3d6 | |||
| 60c7a508a7 | |||
| 1fa18757fc | |||
| fbb7186e66 | |||
| 0961a43997 | |||
| 7037504dcf | |||
| 2385029eab | |||
| eed55a446c | |||
| bbcb6b6851 | |||
| b95630d84a | |||
| af1d3c2aa6 | |||
| ec3e5c547f | |||
| 963a87fed5 | |||
| 173d05b54f | |||
| 865bb47462 | |||
| 3e7ed8a831 | |||
| 3a49a77c07 | |||
| 6782b22637 | |||
| 4600094829 | |||
| daaa83b9ca | |||
| 3288050680 | |||
| b8c29ae957 | |||
| 47bacc0ef0 | |||
| 3d0dced4bd | |||
| 30bba09fed | |||
| 31b07f2c5c | |||
| f7063bb57b | |||
| e4ef85b6e0 | |||
| b7c2088489 | |||
| 59cd0a9c7f | |||
| af107df0b4 | |||
| 0e7e40f2cb | |||
| 0b788f5b43 | |||
| db5c2500c2 | |||
| a1496eb1f1 | |||
| 4aa89132d7 | |||
| 9b8eb089b1 | |||
| c1f08ce58d | |||
| 09a0d046f4 | |||
| 0741698f13 | |||
| c2ac05f734 | |||
| f8f5f9f418 | |||
| 7e6d6b45d4 | |||
| 361e80f7dc | |||
| 395b4bfa45 | |||
| ce2b790d8f | |||
| 1ffc1e82b0 | |||
| 8520ca7ef7 | |||
| 89fba1c385 | |||
| 00a0d37455 | |||
| dbb2251f93 | |||
| 7abf755a57 | |||
| 055f0e2e4a | |||
| 49f4da3016 | |||
| bf234dc668 | |||
| 11bd65c2b5 | |||
| e0d1ac676e | |||
| 494cbac78b | |||
| 0d46a8e786 | |||
| 626b9f93c4 | |||
| 53f9defb07 | |||
| 4bf8d1e41f | |||
| 936c817bd8 | |||
| 9c9495621c | |||
| d53673c6f7 | |||
| 882e949f80 | |||
| e6849a59a2 | |||
| 6918e265ec | |||
| e9f293f522 | |||
| 5fc36d64b6 | |||
| 95e6d78689 | |||
| f4a666345a | |||
| 7a5c88a8d1 | |||
| 0de0dded53 | |||
| 5e58cf6079 | |||
| b0737d1c90 | |||
| 779ed75a19 | |||
| dbf1573e89 | |||
| 96fd8556f2 | |||
| 8f324dfc0a | |||
| 34a6085cc0 | |||
| b3efa75206 | |||
| b90a7dc66a | |||
| 200557c036 | |||
| 472cb3b1c2 | |||
| d8ee6a2edb | |||
| ddcacb8258 | |||
| a8e1754fa4 | |||
| 5db45c3699 | |||
| 89dcafbe41 | |||
| 3d05e61f7e | |||
| 5146f3ec47 | |||
| 170a95f5df | |||
| c661578906 | |||
| f20e0c2898 | |||
| 64b2ae3cd5 | |||
| a11d66f52d | |||
| 304a4a1b61 |
+8
-8
@@ -54,7 +54,7 @@ before_script:
|
||||
- git submodule update --init asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Utilities/yaml-cpp 3rdparty/cereal 3rdparty/hidapi 3rdparty/Optional Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers
|
||||
- mkdir build
|
||||
- cd build
|
||||
- export CMAKE_PREFIX_PATH=~/Qt/5.9.1/gcc_64/lib/cmake
|
||||
- export CMAKE_PREFIX_PATH=~/Qt/5.9.2/gcc_64/lib/cmake
|
||||
- if [ "$TRAVIS_PULL_REQUEST" = false ]; then
|
||||
export CXXFLAGS="$CXXFLAGS -DBRANCH=$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH";
|
||||
else
|
||||
@@ -64,20 +64,20 @@ before_script:
|
||||
- make -j 3
|
||||
- # AppImage generation
|
||||
- if [ -n "$UPLOAD_URL" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$CC" = "clang-4.0" ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then
|
||||
export LD_LIBRARY_PATH=~/Qt/5.9.1/gcc_64/lib;
|
||||
export LD_LIBRARY_PATH=~/Qt/5.9.2/gcc_64/lib;
|
||||
make DESTDIR=appdir install ; find appdir/ ;
|
||||
find ../bin ;
|
||||
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" ;
|
||||
chmod a+x linuxdeployqt*.AppImage ;
|
||||
export PATH=~/Qt/5.9.1/gcc_64/bin/:${PATH} ;
|
||||
export PATH=~/Qt/5.9.2/gcc_64/bin/:${PATH} ;
|
||||
./linuxdeployqt*.AppImage --appimage-extract ;
|
||||
./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -bundle-non-qt-libs ;
|
||||
mkdir ./appdir/usr/plugins/xcbglintegrations/ ;
|
||||
mkdir ./appdir/usr/plugins/imageformats/ ;
|
||||
cp ~/Qt/5.9.1/gcc_64/lib/libQt5Svg.so.5 ./appdir/usr/lib/ ;
|
||||
cp ~/Qt/5.9.1/gcc_64/plugins/xcbglintegrations/* ./appdir/usr/plugins/xcbglintegrations/ ;
|
||||
cp ~/Qt/5.9.1/gcc_64/plugins/imageformats/* ./appdir/usr/plugins/imageformats/ ;
|
||||
cp ~/Qt/5.9.1/gcc_64/plugins/platforms/* ./appdir/usr/plugins/platforms/ ;
|
||||
cp ~/Qt/5.9.2/gcc_64/lib/libQt5Svg.so.5 ./appdir/usr/lib/ ;
|
||||
cp ~/Qt/5.9.2/gcc_64/plugins/xcbglintegrations/* ./appdir/usr/plugins/xcbglintegrations/ ;
|
||||
cp ~/Qt/5.9.2/gcc_64/plugins/imageformats/* ./appdir/usr/plugins/imageformats/ ;
|
||||
cp ~/Qt/5.9.2/gcc_64/plugins/platforms/* ./appdir/usr/plugins/platforms/ ;
|
||||
export PATH=${TRAVIS_BUILD_DIR}/build/squashfs-root/usr/bin/:${PATH} ;
|
||||
./squashfs-root/usr/bin/appimagetool ${TRAVIS_BUILD_DIR}/build/appdir ;
|
||||
find ./appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq ;
|
||||
@@ -115,7 +115,7 @@ addons:
|
||||
- libstdc++-5-dev
|
||||
- lib32stdc++6
|
||||
- zlib1g-dev
|
||||
# We need to install qt 5.9.1 manually because the version trusty provides is too old.
|
||||
# We need to install qt 5.9.2 manually because the version trusty provides is too old.
|
||||
#- qtbase5-dev
|
||||
- libudev-dev
|
||||
- libevdev-dev
|
||||
|
||||
@@ -24,7 +24,7 @@ If you want to contribute please take a look at the [Coding Style](https://githu
|
||||
* [Visual C++ Redistributable Packages for Visual Studio 2015](http://www.microsoft.com/en-us/download/details.aspx?id=48145)
|
||||
* [Cmake 3.1.0+](https://www.cmake.org/download/) (required; add to PATH)
|
||||
* [Python 3.3+](https://www.python.org/downloads/) (required; add to PATH)
|
||||
* [Qt 5.7+](https://www.qt.io/download-open-source/) (required; add QTDIR `<QtInstallFolder>\5.7\msvc2015_64\` environment variable if you do not want to use the Visual Studio Qt Plugin)
|
||||
* [Qt 5.8+](https://www.qt.io/download-open-source/) (required; add QTDIR `<QtInstallFolder>\5.8\msvc2015_64\` environment variable if you do not want to use the Visual Studio Qt Plugin)
|
||||
* [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2015) (optional; see above)
|
||||
|
||||
### Linux
|
||||
@@ -47,10 +47,10 @@ To initialize the repository don't forget to execute `git submodule update --ini
|
||||
### Configuring Qt
|
||||
|
||||
*If you're using Visual Studio 2017 without Qt plugin support (or simply dont want to use it):*
|
||||
1) Add `QTDIR` environment variable and set it to `<QtInstallFolder>\5.7\msvc2015_64\` </br>
|
||||
1) Add `QTDIR` environment variable and set it to `<QtInstallFolder>\5.8\msvc2015_64\` </br>
|
||||
|
||||
*If you wish to use the Visual Studio plugin for Qt:* </br>
|
||||
1) Go to the Qt5 menu and edit Qt5 options. Add the path to your Qt installation with compiler e.g. `C:\Qt\5.7\msvc2015_64`. </br>
|
||||
1) Go to the Qt5 menu and edit Qt5 options. Add the path to your Qt installation with compiler e.g. `C:\Qt\5.8\msvc2015_64`. </br>
|
||||
2) While selecting the rpcs3qt project, go to Qt5->Project Setting and select the version you added.
|
||||
|
||||
### Building the projects
|
||||
|
||||
@@ -96,6 +96,7 @@ static fs::error to_error(DWORD e)
|
||||
case ERROR_INVALID_NAME: return fs::error::inval;
|
||||
case ERROR_SHARING_VIOLATION: return fs::error::acces;
|
||||
case ERROR_DIR_NOT_EMPTY: return fs::error::notempty;
|
||||
case ERROR_NOT_READY: return fs::error::noent;
|
||||
default: fmt::throw_exception("Unknown Win32 error: %u.", e);
|
||||
}
|
||||
}
|
||||
|
||||
+21
-11
@@ -1884,20 +1884,30 @@ void thread_ctrl::set_native_priority(int priority)
|
||||
HANDLE _this_thread = GetCurrentThread();
|
||||
INT native_priority = THREAD_PRIORITY_NORMAL;
|
||||
|
||||
switch (priority)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
if (priority > 0)
|
||||
native_priority = THREAD_PRIORITY_ABOVE_NORMAL;
|
||||
break;
|
||||
case -1:
|
||||
if (priority < 0)
|
||||
native_priority = THREAD_PRIORITY_BELOW_NORMAL;
|
||||
break;
|
||||
}
|
||||
|
||||
SetThreadPriority(_this_thread, native_priority);
|
||||
if (!SetThreadPriority(_this_thread, native_priority))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "SetThreadPriority() failed: 0x%x", GetLastError());
|
||||
}
|
||||
#else
|
||||
int policy;
|
||||
struct sched_param param;
|
||||
|
||||
pthread_getschedparam(pthread_self(), &policy, ¶m);
|
||||
|
||||
if (priority > 0)
|
||||
param.sched_priority = sched_get_priority_max(policy);
|
||||
if (priority < 0)
|
||||
param.sched_priority = sched_get_priority_min(policy);
|
||||
|
||||
if (int err = pthread_setschedparam(pthread_self(), policy, ¶m))
|
||||
{
|
||||
LOG_ERROR(GENERAL, "pthraed_setschedparam() failed: %d", err);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ rem // Official git repository and contact information can be found at
|
||||
rem // https://github.com/RPCS3/rpcs3 and http://rpcs3.net/.
|
||||
|
||||
setlocal ENABLEDELAYEDEXPANSION
|
||||
setlocal ENABLEEXTENSIONS
|
||||
|
||||
set GIT_VERSION_FILE=%~p0..\rpcs3\git-version.h
|
||||
if not defined GIT (
|
||||
@@ -54,9 +55,35 @@ if errorlevel 1 (
|
||||
goto done
|
||||
)
|
||||
|
||||
rem // Get commit count from HEAD by default
|
||||
for /F %%I IN ('call %GIT% rev-list HEAD --count') do set GIT_VERSION=%%I
|
||||
|
||||
rem // If we're in AppVeyor and we're building for master: Get commit count from unshallowed upstream
|
||||
if defined APPVEYOR (
|
||||
if not defined APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH (
|
||||
call %GIT% remote add upstream https://github.com/RPCS3/RPCS3.git
|
||||
call %GIT% fetch --unshallow upstream
|
||||
for /F %%I IN ('call %GIT% rev-list --count upstream/master') do set GIT_VERSION=%%I
|
||||
)
|
||||
)
|
||||
|
||||
if defined APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH (
|
||||
if "%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%"=="master" (
|
||||
for /f "tokens=1* delims=/" %%a in ("%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%") do set user=%%a
|
||||
set "GIT_BRANCH=!user!/%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%"
|
||||
) else (
|
||||
set GIT_BRANCH=%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%
|
||||
)
|
||||
|
||||
) else (
|
||||
for /F %%I IN ('call %GIT% rev-parse --abbrev-ref HEAD') do set GIT_BRANCH=%%I
|
||||
)
|
||||
|
||||
rem // Get last commit (shortened) and concat after commit count in GIT_VERSION
|
||||
for /F %%I IN ('call %GIT% rev-parse --short HEAD') do set GIT_VERSION=%GIT_VERSION%-%%I
|
||||
for /F %%I IN ('call %GIT% rev-parse --abbrev-ref HEAD') do set GIT_BRANCH=%%I
|
||||
|
||||
rem // Echo obtained GIT_VERSION for debug purposes if needed
|
||||
echo %GIT_VERSION%
|
||||
|
||||
rem // Don't modify the file if it already has the current version.
|
||||
if exist "%GIT_VERSION_FILE%" (
|
||||
@@ -69,7 +96,7 @@ if exist "%GIT_VERSION_FILE%" (
|
||||
echo // This is a generated file. > "%GIT_VERSION_FILE%"
|
||||
echo. >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_VERSION "%GIT_VERSION%" >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_BRANCH "%GIT_BRANCH%" >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_BRANCH ^"%GIT_BRANCH%^" >> "%GIT_VERSION_FILE%"
|
||||
echo. >> "%GIT_VERSION_FILE%"
|
||||
echo // If you don't want this file to update/recompile, change to 1. >> "%GIT_VERSION_FILE%"
|
||||
echo #define RPCS3_GIT_VERSION_NO_UPDATE 0 >> "%GIT_VERSION_FILE%"
|
||||
|
||||
+21
-1
@@ -48,7 +48,7 @@
|
||||
#define CONCATENATE_DETAIL(x, y) x ## y
|
||||
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
|
||||
|
||||
#define STRINGIZE_DETAIL(x) #x
|
||||
#define STRINGIZE_DETAIL(x) #x ""
|
||||
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
|
||||
|
||||
#define HERE "\n(in file " __FILE__ ":" STRINGIZE(__LINE__) ")"
|
||||
@@ -534,6 +534,26 @@ inline u64 cntlz64(u64 arg, bool nonzero = false)
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u32 cnttz32(u32 arg, bool nonzero = false)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
ulong res;
|
||||
return _BitScanForward(&res, arg) || nonzero ? res : 32;
|
||||
#else
|
||||
return arg || nonzero ? __builtin_ctzll(arg) : 32;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline u64 cnttz64(u64 arg, bool nonzero = false)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
ulong res;
|
||||
return _BitScanForward64(&res, arg) || nonzero ? res : 64;
|
||||
#else
|
||||
return arg || nonzero ? __builtin_ctzll(arg) : 64;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Helper function, used by ""_u16, ""_u32, ""_u64
|
||||
constexpr u8 to_u8(char c)
|
||||
{
|
||||
|
||||
Submodule Vulkan/Vulkan-LoaderAndValidationLayers updated: 115665a3b5...85926a33d4
+1
-1
Submodule Vulkan/glslang updated: 0e07119ae2...cf571f7310
+72
-34
@@ -1,44 +1,82 @@
|
||||
version: '0.0.3-{build}'
|
||||
#---------------------------------#
|
||||
# general configuration #
|
||||
#---------------------------------#
|
||||
|
||||
os: Visual Studio 2015
|
||||
platform: x64
|
||||
clone_folder: C:\rpcs3
|
||||
clone_depth: 3
|
||||
test: off
|
||||
# version format
|
||||
version: '0.0.4-{build}'
|
||||
|
||||
configuration:
|
||||
# Release
|
||||
- ReleaseLLVM
|
||||
#---------------------------------#
|
||||
# environment configuration #
|
||||
#---------------------------------#
|
||||
|
||||
before_build:
|
||||
- ps: $env:Date="$(git show -s --date=short --format='%ad')"
|
||||
- git submodule update --init 3rdparty/ffmpeg 3rdparty/pugixml asmjit 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp 3rdparty/cereal 3rdparty/zlib 3rdparty/hidapi 3rdparty/Optional
|
||||
- 7z x zlib.7z -aos -oC:\rpcs3\ > null
|
||||
- 7z x vulkan.7z -aos -oC:\rpcs3\Vulkan > null
|
||||
- set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%/#%APPVEYOR_PULL_REQUEST_NUMBER%
|
||||
- if "%APPVEYOR_PULL_REQUEST_NUMBER%"=="" (set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%)
|
||||
- set CXXFLAGS=-DBRANCH=%BRANCH%
|
||||
- if %configuration%==Release (cmake -G "Visual Studio 14 Win64" -DZLIB_ROOT=C:/rpcs3/zlib/ -DVULKAN_PREBUILT=ON)
|
||||
else (7z x llvmlibs.7z -aos -oC:\rpcs3 > null && cmake -G "Visual Studio 14 Win64" -DLLVM_DIR=C:/rpcs3/llvm_build/lib/cmake/llvm -DZLIB_ROOT=C:/rpcs3/zlib/ -DVULKAN_PREBUILT=ON)
|
||||
# Build worker image (VM template)
|
||||
image: Visual Studio 2015
|
||||
|
||||
build_script:
|
||||
- cmake --build . --config Release -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
|
||||
# clone directory
|
||||
clone_folder: c:\projects\rpcs3
|
||||
|
||||
install:
|
||||
- if not exist llvmlibs.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRY2k3Q2Yya05lcm8" -FileName llvmlibs.7z
|
||||
- if not exist vulkan.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRaHYxV3VOS2d0a0U" -FileName vulkan.7z
|
||||
- if not exist zlib.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B-HVE3xvheVFX05lRFdnZlh5aUU" -FileName zlib.7z
|
||||
- set QTDIR=C:\Qt\5.8\msvc2015_64
|
||||
- set OPENALDIR=C:\rpcs3\3rdparty\OpenAL
|
||||
- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%QTDIR%;%PATH%
|
||||
- set COMMIT_SHA=%APPVEYOR_REPO_COMMIT:~0,8%
|
||||
# set clone depth
|
||||
clone_depth: 3 # clone entire repository history if not defined
|
||||
|
||||
artifacts:
|
||||
- path: bin
|
||||
name: 'rpcs3-v0.0.3-$(Date)-$(COMMIT_SHA)_win64'
|
||||
type: zip
|
||||
# environment variables
|
||||
environment:
|
||||
QTDIR: C:\Qt\5.9.1\msvc2015_64
|
||||
|
||||
# build cache to preserve files/folders between builds
|
||||
cache:
|
||||
- llvmlibs.7z -> appveyor.yml
|
||||
- vulkan.7z -> appveyor.yml
|
||||
- zlib.7z -> appveyor.yml
|
||||
|
||||
# scripts that run after cloning repository
|
||||
install:
|
||||
- git submodule update --init 3rdparty/cereal 3rdparty/ffmpeg 3rdparty/GSL 3rdparty/hidapi 3rdparty/libpng 3rdparty/Optional 3rdparty/pugixml 3rdparty/zlib asmjit Utilities/yaml-cpp Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers
|
||||
|
||||
#---------------------------------#
|
||||
# build configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# build platform, i.e. x86, x64, Any CPU. This setting is optional.
|
||||
platform: x64
|
||||
|
||||
# build Configuration, i.e. Debug, Release, etc.
|
||||
configuration: Release - LLVM
|
||||
|
||||
build:
|
||||
parallel: true # enable MSBuild parallel builds
|
||||
project: rpcs3.sln # path to Visual Studio solution or project
|
||||
# MSBuild verbosity level
|
||||
verbosity: normal
|
||||
|
||||
# scripts to run before build
|
||||
before_build:
|
||||
- set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%/#%APPVEYOR_PULL_REQUEST_NUMBER%
|
||||
- if "%APPVEYOR_PULL_REQUEST_NUMBER%"=="" (set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%)
|
||||
- set PATH=%PATH%;%QTDIR%
|
||||
- if not exist llvmlibs.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRY2k3Q2Yya05lcm8" -FileName llvmlibs.7z
|
||||
- 7z x llvmlibs.7z -aos -o%APPVEYOR_BUILD_FOLDER% > null
|
||||
- if not exist vulkan.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRaHYxV3VOS2d0a0U" -FileName vulkan.7z
|
||||
- 7z x vulkan.7z -aos -o"%APPVEYOR_BUILD_FOLDER%\lib\%CONFIGURATION%-%PLATFORM%" > null
|
||||
|
||||
# scripts to run *after* solution is built and *before* automatic packaging occurs (web apps, NuGet packages, Azure Cloud Services)
|
||||
before_package:
|
||||
- rm %APPVEYOR_BUILD_FOLDER%\bin\rpcs3.exp
|
||||
- rm %APPVEYOR_BUILD_FOLDER%\bin\rpcs3.lib
|
||||
- rm %APPVEYOR_BUILD_FOLDER%\bin\rpcs3.pdb
|
||||
- set COMMIT_DATE=%APPVEYOR_REPO_COMMIT_TIMESTAMP:~0,10%
|
||||
- set COMMIT_SHA=%APPVEYOR_REPO_COMMIT:~0,8%
|
||||
|
||||
#---------------------------------#
|
||||
# tests configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# to disable automatic tests
|
||||
test: off
|
||||
|
||||
#---------------------------------#
|
||||
# artifacts configuration #
|
||||
#---------------------------------#
|
||||
|
||||
# pushing entire folder as a zip archive
|
||||
artifacts:
|
||||
- path: bin
|
||||
name: 'rpcs3-v0.0.4-$(COMMIT_DATE)-$(COMMIT_SHA)_win64'
|
||||
|
||||
@@ -40,7 +40,7 @@ QWidget {
|
||||
|
||||
/* Mouse tooltips */
|
||||
QToolTip {
|
||||
border: 1px solid #323232;
|
||||
border: 0.05em solid #323232;
|
||||
background-color: #323232;
|
||||
color: #ecf0f1;
|
||||
}
|
||||
@@ -49,29 +49,29 @@ QToolTip {
|
||||
QHeaderView::section {
|
||||
background-color: #323232;
|
||||
color: #ecf0f1;
|
||||
padding-left: 4px;
|
||||
border: 1px solid #323232;
|
||||
padding-left: 0.2em;
|
||||
border: 0.05em solid #323232;
|
||||
}
|
||||
|
||||
/* Settings Dialog: Tabs */
|
||||
QTabBar::tab {
|
||||
color: #ecf0f1;
|
||||
border: 1px solid #444;
|
||||
border: 0.05em solid #444;
|
||||
border-bottom-style: none;
|
||||
background-color: #333333;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
margin-right: -2px;
|
||||
padding-left: 0.9em;
|
||||
padding-right: 0.9em;
|
||||
padding-top: 0.2em;
|
||||
padding-bottom: 0.2em;
|
||||
margin-right: -0.2em;
|
||||
}
|
||||
QTabBar::tab:last {
|
||||
margin-right: 0px;
|
||||
margin-right: 0em;
|
||||
}
|
||||
QTabBar::tab:!selected {
|
||||
color: #b1b1b1;
|
||||
border-bottom-style: solid;
|
||||
margin-top: 3px;
|
||||
margin-top: 0.15em;
|
||||
background-color: #292929;
|
||||
}
|
||||
QTabBar::tab:hover {
|
||||
@@ -81,11 +81,11 @@ QTabBar::tab:hover {
|
||||
|
||||
/* Checkboxes */
|
||||
QCheckBox::indicator {
|
||||
border-radius: 2px;
|
||||
border: 1px solid #ecf0f1;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-top: 1px;
|
||||
border-radius: 0.1em;
|
||||
border: 0.05em solid #ecf0f1;
|
||||
margin-top: 0.05em;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
}
|
||||
QCheckBox::indicator:checked {
|
||||
background-color: #2ecc71; /* Green */
|
||||
@@ -99,11 +99,11 @@ QCheckBox::indicator::disabled {
|
||||
|
||||
/* Radio Buttons */
|
||||
QRadioButton::indicator {
|
||||
border-radius: 6px;
|
||||
border: 1px solid #ecf0f1;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-top: 1px;
|
||||
border-radius: 0.4em;
|
||||
border: 0.05em solid;
|
||||
border-color: white;
|
||||
width: 0.8em;
|
||||
height: 0.8em;
|
||||
}
|
||||
QRadioButton::indicator:checked {
|
||||
background-color: #2ecc71; /* Green */
|
||||
@@ -119,10 +119,10 @@ QRadioButton::indicator::disabled {
|
||||
QComboBox {
|
||||
background-color: #404040;
|
||||
color: #fff;
|
||||
border: 1px solid #1e1e1e;
|
||||
border-radius: 3px;
|
||||
padding-bottom: 2px;
|
||||
padding-left: 4px;
|
||||
border: 0.05em solid #1e1e1e;
|
||||
border-radius: 0.15em;
|
||||
padding-bottom: 0.2em;
|
||||
padding-left: 0.4em;
|
||||
}
|
||||
QComboBox::disabled {
|
||||
background-color: #828790;
|
||||
@@ -131,15 +131,15 @@ QComboBox::disabled {
|
||||
|
||||
/* Group Boxes (Settings Dialog) */
|
||||
QGroupBox {
|
||||
margin-top: 17px;
|
||||
font-size: 13px;
|
||||
border: 1px solid #bdc3c7;
|
||||
border-radius: 4px;
|
||||
margin-top: 1em;
|
||||
font-size: 8pt;
|
||||
border: 0.05em solid #bdc3c7;
|
||||
border-radius: 0.3em;
|
||||
}
|
||||
QGroupBox::title {
|
||||
subcontrol-origin: margin;
|
||||
subcontrol-position: top center;
|
||||
padding: 5px 10px 5px 10px;
|
||||
subcontrol-position: top;
|
||||
padding: 0.3em 0.5em 0.3em 0.5em;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@@ -154,19 +154,19 @@ QPushButton::disabled {
|
||||
|
||||
/* Log and Debugger borders */
|
||||
QTextEdit {
|
||||
border: 1px solid #828790;
|
||||
border: 0.05em solid #828790;
|
||||
}
|
||||
|
||||
/* For dock buttons to be visible */
|
||||
QDockWidget::close-button, QDockWidget::float-button {
|
||||
background-color: #bdc3c7;
|
||||
border: 1px solid #000;
|
||||
border-radius: 4px;
|
||||
border: 0.05em solid #000;
|
||||
border-radius: 0.3em;
|
||||
}
|
||||
|
||||
/* Disable ugly borders */
|
||||
QTabWidget::pane {
|
||||
border: 0px solid #828790;
|
||||
border: 0em solid #828790;
|
||||
}
|
||||
|
||||
/* Top menu bar */
|
||||
@@ -174,14 +174,14 @@ QMenuBar::item:selected {
|
||||
background: #444444;
|
||||
}
|
||||
QMenu::item {
|
||||
padding-left: 20px;
|
||||
padding-right: 15px;
|
||||
padding-top: 4px;
|
||||
padding-bottom: 4px;
|
||||
padding-left: 1.5em;
|
||||
padding-right: 0.75em;
|
||||
padding-top: 0.25em;
|
||||
padding-bottom: 0.25em;
|
||||
}
|
||||
QMenu::item:selected {
|
||||
background: #444444;
|
||||
border: 1px solid #bdc3c7;
|
||||
border: 0.05em solid #bdc3c7;
|
||||
}
|
||||
QMenu::item:disabled {
|
||||
background-color: #444444;
|
||||
@@ -223,7 +223,7 @@ QLabel#color_button {
|
||||
|
||||
/* Seachbar on main toolbar */
|
||||
QLineEdit#mw_searchbar {
|
||||
margin-left:14px;
|
||||
margin-left: 0.7em;
|
||||
color: #ecf0f1;
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ Controller.prototype.ComponentSelectionPageCallback = function() {
|
||||
var widget = gui.currentPageWidget();
|
||||
|
||||
widget.deselectAll();
|
||||
widget.selectComponent("qt.591.gcc_64");
|
||||
widget.selectComponent("qt.592.gcc_64");
|
||||
|
||||
gui.clickButton(buttons.NextButton);
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ if (NOT Qt5Widgets_FOUND)
|
||||
if ("${CMAKE_SYSTEM}" MATCHES "Linux")
|
||||
message(FATAL_ERROR "Most distros do not provide an up-to-date version of Qt.
|
||||
If you're on Ubuntu or Linux Mint, there are PPAs you can use to install an up-to-date qt5 version.
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt591-xenial
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt591-trusty
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt592-xenial
|
||||
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt592-trusty
|
||||
just make sure to run
|
||||
source /opt/qt59/bin/qt59-env.sh
|
||||
before re-running cmake")
|
||||
@@ -342,7 +342,6 @@ if (NOT WIN32 AND VULKAN_FOUND)
|
||||
"${RPCS3_SRC_DIR}/../Vulkan/glslang/glslang/MachineIndependent/*.cpp"
|
||||
"${RPCS3_SRC_DIR}/../Vulkan/glslang/glslang/OSDependent/Unix/*.cpp"
|
||||
"${RPCS3_SRC_DIR}/../Vulkan/glslang/OGLCompilersDLL/*.cpp"
|
||||
"${RPCS3_SRC_DIR}/../Vulkan/glslang/hlsl/*.cpp"
|
||||
"${RPCS3_SRC_DIR}/../Vulkan/glslang/SPIRV/*.cpp"
|
||||
)
|
||||
|
||||
|
||||
@@ -50,6 +50,8 @@ OpenALThread::OpenALThread()
|
||||
{
|
||||
m_format = g_cfg.audio.convert_to_u16 ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32;
|
||||
}
|
||||
|
||||
m_buffers = std::make_unique<ALuint[]>(g_cfg.audio.frames);
|
||||
}
|
||||
|
||||
OpenALThread::~OpenALThread()
|
||||
@@ -83,7 +85,7 @@ void OpenALThread::Close()
|
||||
if (alIsSource(m_source))
|
||||
alDeleteSources(1, &m_source);
|
||||
|
||||
alDeleteBuffers(g_al_buffers_count, m_buffers);
|
||||
alDeleteBuffers(g_cfg.audio.frames, m_buffers.get());
|
||||
checkForAlError("alDeleteBuffers");
|
||||
}
|
||||
|
||||
@@ -98,7 +100,7 @@ void OpenALThread::Open(const void* src, int size)
|
||||
alGenSources(1, &m_source);
|
||||
checkForAlError("alGenSources");
|
||||
|
||||
alGenBuffers(g_al_buffers_count, m_buffers);
|
||||
alGenBuffers(g_cfg.audio.frames, m_buffers.get());
|
||||
checkForAlError("alGenBuffers");
|
||||
|
||||
alSourcei(m_source, AL_LOOPING, AL_FALSE);
|
||||
@@ -106,13 +108,13 @@ void OpenALThread::Open(const void* src, int size)
|
||||
|
||||
m_buffer_size = size;
|
||||
|
||||
for (uint i = 0; i<g_al_buffers_count; ++i)
|
||||
for (int i = 0; i < g_cfg.audio.frames; ++i)
|
||||
{
|
||||
alBufferData(m_buffers[i], m_format, src, m_buffer_size, 48000);
|
||||
checkForAlError("alBufferData");
|
||||
}
|
||||
|
||||
alSourceQueueBuffers(m_source, g_al_buffers_count, m_buffers);
|
||||
alSourceQueueBuffers(m_source, g_cfg.audio.frames, m_buffers.get());
|
||||
checkForAlError("alSourceQueueBuffers");
|
||||
Play();
|
||||
}
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
|
||||
#include "Emu/Audio/AudioThread.h"
|
||||
#include "3rdparty/OpenAL/include/alext.h"
|
||||
#include <memory>
|
||||
|
||||
class OpenALThread : public AudioThread
|
||||
{
|
||||
private:
|
||||
static const uint g_al_buffers_count = 24;
|
||||
|
||||
ALint m_format;
|
||||
ALuint m_source;
|
||||
ALuint m_buffers[g_al_buffers_count];
|
||||
std::unique_ptr<ALuint[]> m_buffers;
|
||||
ALsizei m_buffer_size;
|
||||
|
||||
public:
|
||||
|
||||
@@ -59,7 +59,7 @@ ALSAThread::ALSAThread()
|
||||
if (!check(snd_pcm_hw_params_set_channels(s_tls_handle, hw_params, g_cfg.audio.downmix_to_2ch ? 2 : 8), "snd_pcm_hw_params_set_channels"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_hw_params_set_buffer_size(s_tls_handle, hw_params, 8 * 256), "snd_pcm_hw_params_set_buffer_size"))
|
||||
if (!check(snd_pcm_hw_params_set_buffer_size(s_tls_handle, hw_params, g_cfg.audio.frames * 256), "snd_pcm_hw_params_set_buffer_size"))
|
||||
return;
|
||||
|
||||
if (!check(snd_pcm_hw_params_set_period_size(s_tls_handle, hw_params, 256, 0), "snd_pcm_hw_params_set_period_size"))
|
||||
|
||||
@@ -57,6 +57,8 @@ void audio_config::on_init(const std::shared_ptr<void>& _this)
|
||||
|
||||
void audio_config::on_task()
|
||||
{
|
||||
thread_ctrl::set_native_priority(1);
|
||||
|
||||
AudioDumper m_dump(g_cfg.audio.dump_to_file ? 2 : 0); // Init AudioDumper for 2 channels if enabled
|
||||
|
||||
float buf2ch[2 * BUFFER_SIZE]{}; // intermediate buffer for 2 channels
|
||||
@@ -337,8 +339,8 @@ void audio_config::on_task()
|
||||
case 8: m_dump.WriteData(&buf8ch, sizeof(buf8ch)); break; // write file data (8 ch)
|
||||
}
|
||||
|
||||
cellAudio.trace("Audio perf: start=%d (access=%d, AddData=%d, events=%d, dump=%d)",
|
||||
time_pos, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3);
|
||||
cellAudio.trace("Audio perf: (access=%d, AddData=%d, events=%d, dump=%d)",
|
||||
stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -659,6 +659,11 @@ error_code cellGameGetParamString(s32 id, vm::ptr<char> buf, u32 bufsize)
|
||||
{
|
||||
cellGame.warning("cellGameGetParamString(id=%d, buf=*0x%x, bufsize=%d)", id, buf, bufsize);
|
||||
|
||||
if (!buf || bufsize == 0)
|
||||
{
|
||||
return CELL_GAME_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const auto prm = fxm::get<content_permission>();
|
||||
|
||||
if (!prm)
|
||||
@@ -685,6 +690,11 @@ error_code cellGameSetParamString(s32 id, vm::cptr<char> buf)
|
||||
{
|
||||
cellGame.warning("cellGameSetParamString(id=%d, buf=*0x%x)", id, buf);
|
||||
|
||||
if (!buf)
|
||||
{
|
||||
return CELL_GAME_ERROR_PARAM;
|
||||
}
|
||||
|
||||
const auto prm = fxm::get<content_permission>();
|
||||
|
||||
if (!prm)
|
||||
|
||||
@@ -74,7 +74,7 @@ s32 cellMouseGetInfo(vm::ptr<CellMouseInfo> info)
|
||||
for (u32 i=0; i<CELL_MAX_MICE; i++) info->vendor_id[i] = current_info.vendor_id[i];
|
||||
for (u32 i=0; i<CELL_MAX_MICE; i++) info->product_id[i] = current_info.product_id[i];
|
||||
for (u32 i=0; i<CELL_MAX_MICE; i++) info->status[i] = current_info.status[i];
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ s32 cellMouseInfoTabletMode(u32 port_no, vm::ptr<CellMouseInfoTablet> info)
|
||||
|
||||
info->is_supported = 0; // Unimplemented: (0=Tablet mode is not supported)
|
||||
info->mode = 1; // Unimplemented: (1=Mouse mode)
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ s32 cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
|
||||
{
|
||||
return CELL_MOUSE_ERROR_NO_DEVICE;
|
||||
}
|
||||
|
||||
|
||||
MouseData& current_data = handler->GetData(port_no);
|
||||
data->update = current_data.update;
|
||||
data->buttons = current_data.buttons;
|
||||
@@ -134,22 +134,27 @@ s32 cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
|
||||
|
||||
s32 cellMouseGetDataList(u32 port_no, vm::ptr<CellMouseDataList> data)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sys_io);
|
||||
|
||||
return CELL_OK;
|
||||
sys_io.todo("cellMouseGetDataList(port_no=%d, data=0x%x", port_no, data);
|
||||
if (g_cfg.io.mouse == mouse_handler::null)
|
||||
return CELL_MOUSE_ERROR_NO_DEVICE;
|
||||
else
|
||||
{
|
||||
data->list_num = 0;
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
s32 cellMouseSetTabletMode(u32 port_no, u32 mode)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sys_io);
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 cellMouseGetTabletDataList(u32 port_no, u32 data_addr)
|
||||
{
|
||||
UNIMPLEMENTED_FUNC(sys_io);
|
||||
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,7 +147,8 @@ s32 sceNpSnsFbCheckThrottle()
|
||||
|
||||
s32 sceNpSnsFbCheckConfig()
|
||||
{
|
||||
fmt::throw_exception("Unimplemented" HERE);
|
||||
sceNpSns.todo("sceNpSnsFbCheckConfig()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
s32 sceNpSnsFbLoadThrottle()
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
logs::channel sceNpTrophy("sceNpTrophy");
|
||||
|
||||
TrophyNotificationBase::~TrophyNotificationBase()
|
||||
{
|
||||
}
|
||||
|
||||
struct trophy_context_t
|
||||
{
|
||||
static const u32 id_base = 1;
|
||||
@@ -264,7 +268,7 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
|
||||
const size_t kTargetBufferLength = 31;
|
||||
char target[kTargetBufferLength + 1];
|
||||
target[kTargetBufferLength] = 0;
|
||||
strcpy_trunc(target, fmt::format("TROP_%02d.SFM", /*rpcs3::config.system.language.value()*/0));
|
||||
strcpy_trunc(target, fmt::format("TROP_%02d.SFM", static_cast<s32>(g_cfg.sys.language)));
|
||||
|
||||
if (trp.ContainsEntry(target))
|
||||
{
|
||||
@@ -286,7 +290,7 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
|
||||
for (s32 i = 0; i <= 18; i++)
|
||||
{
|
||||
strcpy_trunc(target, fmt::format("TROP_%02d.SFM", i));
|
||||
if (i != /*rpcs3::config.system.language.value()*/0)
|
||||
if (i != g_cfg.sys.language)
|
||||
{
|
||||
trp.RemoveEntry(target);
|
||||
}
|
||||
@@ -490,6 +494,40 @@ error_code sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::pt
|
||||
*platinumId = SCE_NP_TROPHY_INVALID_TROPHY_ID; // TODO
|
||||
}
|
||||
|
||||
if (g_cfg.misc.show_trophy_popups)
|
||||
{
|
||||
// Figure out how many zeros are needed for padding. (either 0, 1, or 2)
|
||||
std::string padding = "";
|
||||
if (trophyId < 10)
|
||||
{
|
||||
padding = "00";
|
||||
}
|
||||
else if (trophyId < 100)
|
||||
{
|
||||
padding = "0";
|
||||
}
|
||||
|
||||
// Get icon for the notification.
|
||||
std::string trophyIconPath = "/dev_hdd0/home/00000001/trophy/" + ctxt->trp_name + "/TROP" + padding + std::to_string(trophyId) + ".PNG";
|
||||
fs::file trophyIconFile = fs::file(vfs::get(trophyIconPath));
|
||||
u32 iconSize = trophyIconFile.size();
|
||||
std::vector<uchar> trophyIconData;
|
||||
trophyIconFile.read(trophyIconData, iconSize);
|
||||
|
||||
vm::ptr<SceNpTrophyDetails> details = vm::make_var(SceNpTrophyDetails());
|
||||
vm::ptr<SceNpTrophyData> _ = vm::make_var(SceNpTrophyData());
|
||||
|
||||
s32 ret = sceNpTrophyGetTrophyInfo(context, handle, trophyId, details, _);
|
||||
if (ret != CELL_OK)
|
||||
{
|
||||
sceNpTrophy.error("Failed to get info for trophy dialog. Error code %x", ret);
|
||||
*details = SceNpTrophyDetails();
|
||||
}
|
||||
Emu.CallAfter([det = *details, trophyIconData]() {
|
||||
Emu.GetCallbacks().get_trophy_notification_dialog()->ShowTrophyNotification(det, trophyIconData);
|
||||
});
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -137,3 +137,14 @@ enum
|
||||
};
|
||||
|
||||
using SceNpTrophyStatusCallback = s32(u32 context, u32 status, s32 completed, s32 total, vm::ptr<void> arg);
|
||||
|
||||
// Forward declare this function since trophyunlock needs it
|
||||
error_code sceNpTrophyGetTrophyInfo(u32 context, u32 handle, s32 trophyId, vm::ptr<SceNpTrophyDetails> details, vm::ptr<SceNpTrophyData> data);
|
||||
|
||||
class TrophyNotificationBase
|
||||
{
|
||||
public:
|
||||
virtual ~TrophyNotificationBase();
|
||||
|
||||
virtual s32 ShowTrophyNotification(const SceNpTrophyDetails& trophy, const std::vector<uchar>& trophyIconBfr) = 0;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "Utilities/bit_set.h"
|
||||
#include "Utilities/BEType.h"
|
||||
#include "PPUOpcodes.h"
|
||||
|
||||
// PPU Function Attributes
|
||||
enum class ppu_attr : u32
|
||||
@@ -941,3 +942,738 @@ struct ppu_iname
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
// PPU Analyser Context
|
||||
struct ppu_acontext
|
||||
{
|
||||
// General-purpose register range
|
||||
struct spec_gpr
|
||||
{
|
||||
// Integral range: normalized undef = (0;UINT64_MAX), unnormalized undefs are possible (when max = min - 1)
|
||||
// Bit range: constant 0 = (0;0), constant 1 = (1;1), normalized undef = (0;1), unnormalized undef = (1;0)
|
||||
|
||||
u64 imin = 0; // Integral range begin
|
||||
u64 imax = -1; // Integral range end
|
||||
u64 bmin = 0; // Bit range begin
|
||||
u64 bmax = -1; // Bit range end
|
||||
|
||||
void set_undef()
|
||||
{
|
||||
imin = 0;
|
||||
imax = -1;
|
||||
bmin = 0;
|
||||
bmax = -1;
|
||||
}
|
||||
|
||||
// (Number of possible values - 1), 0 = const
|
||||
u64 div() const
|
||||
{
|
||||
return imax - imin;
|
||||
}
|
||||
|
||||
// Return zero bits for zeros, ones for ones or undefs
|
||||
u64 mask() const
|
||||
{
|
||||
return bmin | bmax;
|
||||
}
|
||||
|
||||
// Return one bits for ones, zeros for zeros or undefs
|
||||
u64 ones() const
|
||||
{
|
||||
return bmin & bmax;
|
||||
}
|
||||
|
||||
// Return one bits for undefs
|
||||
u64 undefs() const
|
||||
{
|
||||
return bmin ^ bmax;
|
||||
}
|
||||
|
||||
// Return number of trailing zero bits
|
||||
u64 tz() const
|
||||
{
|
||||
return ::cnttz64(mask());
|
||||
}
|
||||
|
||||
// Range NOT
|
||||
spec_gpr operator ~() const
|
||||
{
|
||||
spec_gpr r;
|
||||
r.imin = ~imax;
|
||||
r.imax = ~imin;
|
||||
r.bmin = ~bmax;
|
||||
r.bmax = ~bmin;
|
||||
return r;
|
||||
}
|
||||
|
||||
// Range ADD
|
||||
spec_gpr operator +(const spec_gpr& rhs) const
|
||||
{
|
||||
spec_gpr r{};
|
||||
|
||||
const u64 adiv = div();
|
||||
const u64 bdiv = rhs.div();
|
||||
|
||||
// Check overflow, generate normalized range
|
||||
if (adiv != -1 && bdiv != -1 && adiv <= adiv + bdiv)
|
||||
{
|
||||
r = range(imin + rhs.imin, imax + rhs.imax);
|
||||
}
|
||||
|
||||
// Carry for bitrange computation
|
||||
u64 cmin = 0;
|
||||
u64 cmax = 0;
|
||||
|
||||
const u64 amask = mask();
|
||||
const u64 bmask = rhs.mask();
|
||||
const u64 aones = ones();
|
||||
const u64 bones = rhs.ones();
|
||||
|
||||
for (u32 i = 0; i < 64; i++)
|
||||
{
|
||||
cmin += ((amask >> i) & 1) + ((bmask >> i) & 1);
|
||||
cmax += ((aones >> i) & 1) + ((bones >> i) & 1);
|
||||
|
||||
// Discover some constant bits
|
||||
if (cmin == cmax)
|
||||
{
|
||||
r.bmin |= (cmin & 1) << i;
|
||||
r.bmax &= ~((~cmin & 1) << i);
|
||||
}
|
||||
|
||||
cmin >>= 1;
|
||||
cmax >>= 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// Range AND
|
||||
spec_gpr operator &(const spec_gpr& rhs) const
|
||||
{
|
||||
// Ignore inverted ranges (TODO)
|
||||
if (imin > imax || rhs.imin > rhs.imax)
|
||||
{
|
||||
return approx(ones() & rhs.ones(), mask() & rhs.mask());
|
||||
}
|
||||
|
||||
// Const (TODO: remove when unnecessary)
|
||||
if (imin == imax && rhs.imin == rhs.imax)
|
||||
{
|
||||
return fixed(imin & rhs.imin);
|
||||
}
|
||||
|
||||
// Swap (TODO: remove when unnecessary)
|
||||
if (imin == imax || rhs.undefs() > undefs())
|
||||
{
|
||||
return rhs & *this;
|
||||
}
|
||||
|
||||
// Copy and attempt to partially preserve integral range
|
||||
spec_gpr r = *this;
|
||||
|
||||
for (u32 i = 63; ~i; i--)
|
||||
{
|
||||
const u64 m = 1ull << i;
|
||||
|
||||
if (!(rhs.mask() & m))
|
||||
{
|
||||
if (r.undefs() & m)
|
||||
{
|
||||
// undef -> 0
|
||||
r.imin &= ~(m - 1);
|
||||
r.imax |= (m - 1);
|
||||
r.imin &= ~m;
|
||||
r.imax &= ~m;
|
||||
}
|
||||
else if (r.ones() & m)
|
||||
{
|
||||
// 1 -> 0
|
||||
if ((r.imin ^ r.imax) > (m - 1))
|
||||
{
|
||||
r.imin &= ~(m - 1);
|
||||
r.imax |= (m - 1);
|
||||
}
|
||||
|
||||
r.imin &= ~m;
|
||||
r.imax &= ~m;
|
||||
}
|
||||
}
|
||||
else if (rhs.undefs() & m)
|
||||
{
|
||||
// -> undef
|
||||
r.imin &= ~(m - 1);
|
||||
r.imax |= (m - 1);
|
||||
r.imin &= ~m;
|
||||
r.imax |= m;
|
||||
}
|
||||
}
|
||||
|
||||
r.bmin = ones() & rhs.ones();
|
||||
r.bmax = mask() & rhs.mask();
|
||||
return r;
|
||||
}
|
||||
|
||||
// Range OR
|
||||
spec_gpr operator |(const spec_gpr& rhs) const
|
||||
{
|
||||
// Ignore inverted ranges (TODO)
|
||||
if (imin > imax || rhs.imin > rhs.imax)
|
||||
{
|
||||
return approx(ones() | rhs.ones(), mask() | rhs.mask());
|
||||
}
|
||||
|
||||
// Const (TODO: remove when unnecessary)
|
||||
if (imin == imax && rhs.imin == rhs.imax)
|
||||
{
|
||||
return fixed(imin | rhs.imin);
|
||||
}
|
||||
|
||||
// Swap (TODO: remove when unnecessary)
|
||||
if (imin == imax || rhs.undefs() > undefs())
|
||||
{
|
||||
return rhs | *this;
|
||||
}
|
||||
|
||||
// Copy and attempt to partially preserve integral range
|
||||
spec_gpr r = *this;
|
||||
|
||||
for (u32 i = 63; ~i; i--)
|
||||
{
|
||||
const u64 m = 1ull << i;
|
||||
|
||||
if (rhs.ones() & m)
|
||||
{
|
||||
if (r.undefs() & m)
|
||||
{
|
||||
// undef -> 1
|
||||
r.imin &= ~(m - 1);
|
||||
r.imax |= (m - 1);
|
||||
r.imin |= m;
|
||||
r.imax |= m;
|
||||
}
|
||||
else if (!(r.mask() & m))
|
||||
{
|
||||
// 0 -> 1
|
||||
if ((r.imin ^ r.imax) > (m - 1))
|
||||
{
|
||||
r.imin &= ~(m - 1);
|
||||
r.imax |= (m - 1);
|
||||
}
|
||||
|
||||
r.imin |= m;
|
||||
r.imax |= m;
|
||||
}
|
||||
}
|
||||
else if (rhs.undefs() & m)
|
||||
{
|
||||
// -> undef
|
||||
r.imin &= ~(m - 1);
|
||||
r.imax |= (m - 1);
|
||||
r.imin &= ~m;
|
||||
r.imax |= m;
|
||||
}
|
||||
}
|
||||
|
||||
r.bmin = ones() | rhs.ones();
|
||||
r.bmax = mask() | rhs.mask();
|
||||
return r;
|
||||
}
|
||||
|
||||
// Range XOR
|
||||
spec_gpr operator ^(const spec_gpr& rhs)
|
||||
{
|
||||
return (~*this & rhs) | (*this & ~rhs);
|
||||
}
|
||||
|
||||
// Check whether the value is in range
|
||||
bool test(u64 value) const
|
||||
{
|
||||
if (imin <= imax)
|
||||
{
|
||||
if (value < imin || value > imax)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (value < imin && value > imax)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((value & mask()) != value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((value | ones()) != value)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Constant value
|
||||
static spec_gpr fixed(u64 value)
|
||||
{
|
||||
spec_gpr r;
|
||||
r.imin = value;
|
||||
r.imax = value;
|
||||
r.bmin = value;
|
||||
r.bmax = value;
|
||||
return r;
|
||||
}
|
||||
|
||||
// Range (tz = number of constant trailing zeros)
|
||||
static spec_gpr range(u64 min, u64 max, u64 tz = 0)
|
||||
{
|
||||
const u64 mask = tz < 64 ? ~0ull << tz : 0ull;
|
||||
|
||||
spec_gpr r;
|
||||
r.bmin = 0;
|
||||
r.bmax = mask;
|
||||
|
||||
// Normalize min/max for tz (TODO)
|
||||
if (min < max)
|
||||
{
|
||||
// Inverted constant MSB mask
|
||||
const u64 mix = ~0ull >> ::cntlz64(min ^ max, true);
|
||||
r.bmin |= min & ~mix;
|
||||
r.bmax &= max | mix;
|
||||
|
||||
r.imin = (min + ~mask) & mask;
|
||||
r.imax = max & mask;
|
||||
verify("Impossible range" HERE), r.imin <= r.imax;
|
||||
}
|
||||
else
|
||||
{
|
||||
r.imin = min & mask;
|
||||
r.imax = (max + ~mask) & mask;
|
||||
verify("Impossible range" HERE), r.imin >= r.imax;
|
||||
}
|
||||
|
||||
// Fix const values
|
||||
if (r.imin == r.imax)
|
||||
{
|
||||
r.bmin = r.imin;
|
||||
r.bmax = r.imax;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// Make from bitrange (normalize, approximate range values)
|
||||
static spec_gpr approx(u64 bmin, u64 bmax)
|
||||
{
|
||||
spec_gpr r;
|
||||
r.imin = bmin & ~(bmin ^ bmax);
|
||||
r.imax = bmax | (bmin ^ bmax);
|
||||
r.bmin = bmin & ~(bmin ^ bmax);
|
||||
r.bmax = bmax | (bmin ^ bmax);
|
||||
return r;
|
||||
}
|
||||
} gpr[32]{};
|
||||
|
||||
// Vector registers (draft)
|
||||
struct spec_vec
|
||||
{
|
||||
u8 imin8[16]{};
|
||||
u8 imax8[16]{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
|
||||
u16 imin16[8]{};
|
||||
u16 imax16[8]{0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
|
||||
u32 imin32[4]{};
|
||||
u32 imax32[4]{0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu};
|
||||
u64 bmin64[2]{};
|
||||
u64 bmax64[2]{0xffffffffffffffffull, 0xffffffffffffffffull};
|
||||
};
|
||||
|
||||
// Info
|
||||
u32 cia;
|
||||
|
||||
// Analyser step
|
||||
void UNK(ppu_opcode_t);
|
||||
|
||||
void MFVSCR(ppu_opcode_t);
|
||||
void MTVSCR(ppu_opcode_t);
|
||||
void VADDCUW(ppu_opcode_t);
|
||||
void VADDFP(ppu_opcode_t);
|
||||
void VADDSBS(ppu_opcode_t);
|
||||
void VADDSHS(ppu_opcode_t);
|
||||
void VADDSWS(ppu_opcode_t);
|
||||
void VADDUBM(ppu_opcode_t);
|
||||
void VADDUBS(ppu_opcode_t);
|
||||
void VADDUHM(ppu_opcode_t);
|
||||
void VADDUHS(ppu_opcode_t);
|
||||
void VADDUWM(ppu_opcode_t);
|
||||
void VADDUWS(ppu_opcode_t);
|
||||
void VAND(ppu_opcode_t);
|
||||
void VANDC(ppu_opcode_t);
|
||||
void VAVGSB(ppu_opcode_t);
|
||||
void VAVGSH(ppu_opcode_t);
|
||||
void VAVGSW(ppu_opcode_t);
|
||||
void VAVGUB(ppu_opcode_t);
|
||||
void VAVGUH(ppu_opcode_t);
|
||||
void VAVGUW(ppu_opcode_t);
|
||||
void VCFSX(ppu_opcode_t);
|
||||
void VCFUX(ppu_opcode_t);
|
||||
void VCMPBFP(ppu_opcode_t);
|
||||
void VCMPEQFP(ppu_opcode_t);
|
||||
void VCMPEQUB(ppu_opcode_t);
|
||||
void VCMPEQUH(ppu_opcode_t);
|
||||
void VCMPEQUW(ppu_opcode_t);
|
||||
void VCMPGEFP(ppu_opcode_t);
|
||||
void VCMPGTFP(ppu_opcode_t);
|
||||
void VCMPGTSB(ppu_opcode_t);
|
||||
void VCMPGTSH(ppu_opcode_t);
|
||||
void VCMPGTSW(ppu_opcode_t);
|
||||
void VCMPGTUB(ppu_opcode_t);
|
||||
void VCMPGTUH(ppu_opcode_t);
|
||||
void VCMPGTUW(ppu_opcode_t);
|
||||
void VCTSXS(ppu_opcode_t);
|
||||
void VCTUXS(ppu_opcode_t);
|
||||
void VEXPTEFP(ppu_opcode_t);
|
||||
void VLOGEFP(ppu_opcode_t);
|
||||
void VMADDFP(ppu_opcode_t);
|
||||
void VMAXFP(ppu_opcode_t);
|
||||
void VMAXSB(ppu_opcode_t);
|
||||
void VMAXSH(ppu_opcode_t);
|
||||
void VMAXSW(ppu_opcode_t);
|
||||
void VMAXUB(ppu_opcode_t);
|
||||
void VMAXUH(ppu_opcode_t);
|
||||
void VMAXUW(ppu_opcode_t);
|
||||
void VMHADDSHS(ppu_opcode_t);
|
||||
void VMHRADDSHS(ppu_opcode_t);
|
||||
void VMINFP(ppu_opcode_t);
|
||||
void VMINSB(ppu_opcode_t);
|
||||
void VMINSH(ppu_opcode_t);
|
||||
void VMINSW(ppu_opcode_t);
|
||||
void VMINUB(ppu_opcode_t);
|
||||
void VMINUH(ppu_opcode_t);
|
||||
void VMINUW(ppu_opcode_t);
|
||||
void VMLADDUHM(ppu_opcode_t);
|
||||
void VMRGHB(ppu_opcode_t);
|
||||
void VMRGHH(ppu_opcode_t);
|
||||
void VMRGHW(ppu_opcode_t);
|
||||
void VMRGLB(ppu_opcode_t);
|
||||
void VMRGLH(ppu_opcode_t);
|
||||
void VMRGLW(ppu_opcode_t);
|
||||
void VMSUMMBM(ppu_opcode_t);
|
||||
void VMSUMSHM(ppu_opcode_t);
|
||||
void VMSUMSHS(ppu_opcode_t);
|
||||
void VMSUMUBM(ppu_opcode_t);
|
||||
void VMSUMUHM(ppu_opcode_t);
|
||||
void VMSUMUHS(ppu_opcode_t);
|
||||
void VMULESB(ppu_opcode_t);
|
||||
void VMULESH(ppu_opcode_t);
|
||||
void VMULEUB(ppu_opcode_t);
|
||||
void VMULEUH(ppu_opcode_t);
|
||||
void VMULOSB(ppu_opcode_t);
|
||||
void VMULOSH(ppu_opcode_t);
|
||||
void VMULOUB(ppu_opcode_t);
|
||||
void VMULOUH(ppu_opcode_t);
|
||||
void VNMSUBFP(ppu_opcode_t);
|
||||
void VNOR(ppu_opcode_t);
|
||||
void VOR(ppu_opcode_t);
|
||||
void VPERM(ppu_opcode_t);
|
||||
void VPKPX(ppu_opcode_t);
|
||||
void VPKSHSS(ppu_opcode_t);
|
||||
void VPKSHUS(ppu_opcode_t);
|
||||
void VPKSWSS(ppu_opcode_t);
|
||||
void VPKSWUS(ppu_opcode_t);
|
||||
void VPKUHUM(ppu_opcode_t);
|
||||
void VPKUHUS(ppu_opcode_t);
|
||||
void VPKUWUM(ppu_opcode_t);
|
||||
void VPKUWUS(ppu_opcode_t);
|
||||
void VREFP(ppu_opcode_t);
|
||||
void VRFIM(ppu_opcode_t);
|
||||
void VRFIN(ppu_opcode_t);
|
||||
void VRFIP(ppu_opcode_t);
|
||||
void VRFIZ(ppu_opcode_t);
|
||||
void VRLB(ppu_opcode_t);
|
||||
void VRLH(ppu_opcode_t);
|
||||
void VRLW(ppu_opcode_t);
|
||||
void VRSQRTEFP(ppu_opcode_t);
|
||||
void VSEL(ppu_opcode_t);
|
||||
void VSL(ppu_opcode_t);
|
||||
void VSLB(ppu_opcode_t);
|
||||
void VSLDOI(ppu_opcode_t);
|
||||
void VSLH(ppu_opcode_t);
|
||||
void VSLO(ppu_opcode_t);
|
||||
void VSLW(ppu_opcode_t);
|
||||
void VSPLTB(ppu_opcode_t);
|
||||
void VSPLTH(ppu_opcode_t);
|
||||
void VSPLTISB(ppu_opcode_t);
|
||||
void VSPLTISH(ppu_opcode_t);
|
||||
void VSPLTISW(ppu_opcode_t);
|
||||
void VSPLTW(ppu_opcode_t);
|
||||
void VSR(ppu_opcode_t);
|
||||
void VSRAB(ppu_opcode_t);
|
||||
void VSRAH(ppu_opcode_t);
|
||||
void VSRAW(ppu_opcode_t);
|
||||
void VSRB(ppu_opcode_t);
|
||||
void VSRH(ppu_opcode_t);
|
||||
void VSRO(ppu_opcode_t);
|
||||
void VSRW(ppu_opcode_t);
|
||||
void VSUBCUW(ppu_opcode_t);
|
||||
void VSUBFP(ppu_opcode_t);
|
||||
void VSUBSBS(ppu_opcode_t);
|
||||
void VSUBSHS(ppu_opcode_t);
|
||||
void VSUBSWS(ppu_opcode_t);
|
||||
void VSUBUBM(ppu_opcode_t);
|
||||
void VSUBUBS(ppu_opcode_t);
|
||||
void VSUBUHM(ppu_opcode_t);
|
||||
void VSUBUHS(ppu_opcode_t);
|
||||
void VSUBUWM(ppu_opcode_t);
|
||||
void VSUBUWS(ppu_opcode_t);
|
||||
void VSUMSWS(ppu_opcode_t);
|
||||
void VSUM2SWS(ppu_opcode_t);
|
||||
void VSUM4SBS(ppu_opcode_t);
|
||||
void VSUM4SHS(ppu_opcode_t);
|
||||
void VSUM4UBS(ppu_opcode_t);
|
||||
void VUPKHPX(ppu_opcode_t);
|
||||
void VUPKHSB(ppu_opcode_t);
|
||||
void VUPKHSH(ppu_opcode_t);
|
||||
void VUPKLPX(ppu_opcode_t);
|
||||
void VUPKLSB(ppu_opcode_t);
|
||||
void VUPKLSH(ppu_opcode_t);
|
||||
void VXOR(ppu_opcode_t);
|
||||
void TDI(ppu_opcode_t);
|
||||
void TWI(ppu_opcode_t);
|
||||
void MULLI(ppu_opcode_t);
|
||||
void SUBFIC(ppu_opcode_t);
|
||||
void CMPLI(ppu_opcode_t);
|
||||
void CMPI(ppu_opcode_t);
|
||||
void ADDIC(ppu_opcode_t);
|
||||
void ADDI(ppu_opcode_t);
|
||||
void ADDIS(ppu_opcode_t);
|
||||
void BC(ppu_opcode_t);
|
||||
void SC(ppu_opcode_t);
|
||||
void B(ppu_opcode_t);
|
||||
void MCRF(ppu_opcode_t);
|
||||
void BCLR(ppu_opcode_t);
|
||||
void CRNOR(ppu_opcode_t);
|
||||
void CRANDC(ppu_opcode_t);
|
||||
void ISYNC(ppu_opcode_t);
|
||||
void CRXOR(ppu_opcode_t);
|
||||
void CRNAND(ppu_opcode_t);
|
||||
void CRAND(ppu_opcode_t);
|
||||
void CREQV(ppu_opcode_t);
|
||||
void CRORC(ppu_opcode_t);
|
||||
void CROR(ppu_opcode_t);
|
||||
void BCCTR(ppu_opcode_t);
|
||||
void RLWIMI(ppu_opcode_t);
|
||||
void RLWINM(ppu_opcode_t);
|
||||
void RLWNM(ppu_opcode_t);
|
||||
void ORI(ppu_opcode_t);
|
||||
void ORIS(ppu_opcode_t);
|
||||
void XORI(ppu_opcode_t);
|
||||
void XORIS(ppu_opcode_t);
|
||||
void ANDI(ppu_opcode_t);
|
||||
void ANDIS(ppu_opcode_t);
|
||||
void RLDICL(ppu_opcode_t);
|
||||
void RLDICR(ppu_opcode_t);
|
||||
void RLDIC(ppu_opcode_t);
|
||||
void RLDIMI(ppu_opcode_t);
|
||||
void RLDCL(ppu_opcode_t);
|
||||
void RLDCR(ppu_opcode_t);
|
||||
void CMP(ppu_opcode_t);
|
||||
void TW(ppu_opcode_t);
|
||||
void LVSL(ppu_opcode_t);
|
||||
void LVEBX(ppu_opcode_t);
|
||||
void SUBFC(ppu_opcode_t);
|
||||
void ADDC(ppu_opcode_t);
|
||||
void MULHDU(ppu_opcode_t);
|
||||
void MULHWU(ppu_opcode_t);
|
||||
void MFOCRF(ppu_opcode_t);
|
||||
void LWARX(ppu_opcode_t);
|
||||
void LDX(ppu_opcode_t);
|
||||
void LWZX(ppu_opcode_t);
|
||||
void SLW(ppu_opcode_t);
|
||||
void CNTLZW(ppu_opcode_t);
|
||||
void SLD(ppu_opcode_t);
|
||||
void AND(ppu_opcode_t);
|
||||
void CMPL(ppu_opcode_t);
|
||||
void LVSR(ppu_opcode_t);
|
||||
void LVEHX(ppu_opcode_t);
|
||||
void SUBF(ppu_opcode_t);
|
||||
void LDUX(ppu_opcode_t);
|
||||
void DCBST(ppu_opcode_t);
|
||||
void LWZUX(ppu_opcode_t);
|
||||
void CNTLZD(ppu_opcode_t);
|
||||
void ANDC(ppu_opcode_t);
|
||||
void TD(ppu_opcode_t);
|
||||
void LVEWX(ppu_opcode_t);
|
||||
void MULHD(ppu_opcode_t);
|
||||
void MULHW(ppu_opcode_t);
|
||||
void LDARX(ppu_opcode_t);
|
||||
void DCBF(ppu_opcode_t);
|
||||
void LBZX(ppu_opcode_t);
|
||||
void LVX(ppu_opcode_t);
|
||||
void NEG(ppu_opcode_t);
|
||||
void LBZUX(ppu_opcode_t);
|
||||
void NOR(ppu_opcode_t);
|
||||
void STVEBX(ppu_opcode_t);
|
||||
void SUBFE(ppu_opcode_t);
|
||||
void ADDE(ppu_opcode_t);
|
||||
void MTOCRF(ppu_opcode_t);
|
||||
void STDX(ppu_opcode_t);
|
||||
void STWCX(ppu_opcode_t);
|
||||
void STWX(ppu_opcode_t);
|
||||
void STVEHX(ppu_opcode_t);
|
||||
void STDUX(ppu_opcode_t);
|
||||
void STWUX(ppu_opcode_t);
|
||||
void STVEWX(ppu_opcode_t);
|
||||
void SUBFZE(ppu_opcode_t);
|
||||
void ADDZE(ppu_opcode_t);
|
||||
void STDCX(ppu_opcode_t);
|
||||
void STBX(ppu_opcode_t);
|
||||
void STVX(ppu_opcode_t);
|
||||
void SUBFME(ppu_opcode_t);
|
||||
void MULLD(ppu_opcode_t);
|
||||
void ADDME(ppu_opcode_t);
|
||||
void MULLW(ppu_opcode_t);
|
||||
void DCBTST(ppu_opcode_t);
|
||||
void STBUX(ppu_opcode_t);
|
||||
void ADD(ppu_opcode_t);
|
||||
void DCBT(ppu_opcode_t);
|
||||
void LHZX(ppu_opcode_t);
|
||||
void EQV(ppu_opcode_t);
|
||||
void ECIWX(ppu_opcode_t);
|
||||
void LHZUX(ppu_opcode_t);
|
||||
void XOR(ppu_opcode_t);
|
||||
void MFSPR(ppu_opcode_t);
|
||||
void LWAX(ppu_opcode_t);
|
||||
void DST(ppu_opcode_t);
|
||||
void LHAX(ppu_opcode_t);
|
||||
void LVXL(ppu_opcode_t);
|
||||
void MFTB(ppu_opcode_t);
|
||||
void LWAUX(ppu_opcode_t);
|
||||
void DSTST(ppu_opcode_t);
|
||||
void LHAUX(ppu_opcode_t);
|
||||
void STHX(ppu_opcode_t);
|
||||
void ORC(ppu_opcode_t);
|
||||
void ECOWX(ppu_opcode_t);
|
||||
void STHUX(ppu_opcode_t);
|
||||
void OR(ppu_opcode_t);
|
||||
void DIVDU(ppu_opcode_t);
|
||||
void DIVWU(ppu_opcode_t);
|
||||
void MTSPR(ppu_opcode_t);
|
||||
void DCBI(ppu_opcode_t);
|
||||
void NAND(ppu_opcode_t);
|
||||
void STVXL(ppu_opcode_t);
|
||||
void DIVD(ppu_opcode_t);
|
||||
void DIVW(ppu_opcode_t);
|
||||
void LVLX(ppu_opcode_t);
|
||||
void LDBRX(ppu_opcode_t);
|
||||
void LSWX(ppu_opcode_t);
|
||||
void LWBRX(ppu_opcode_t);
|
||||
void LFSX(ppu_opcode_t);
|
||||
void SRW(ppu_opcode_t);
|
||||
void SRD(ppu_opcode_t);
|
||||
void LVRX(ppu_opcode_t);
|
||||
void LSWI(ppu_opcode_t);
|
||||
void LFSUX(ppu_opcode_t);
|
||||
void SYNC(ppu_opcode_t);
|
||||
void LFDX(ppu_opcode_t);
|
||||
void LFDUX(ppu_opcode_t);
|
||||
void STVLX(ppu_opcode_t);
|
||||
void STDBRX(ppu_opcode_t);
|
||||
void STSWX(ppu_opcode_t);
|
||||
void STWBRX(ppu_opcode_t);
|
||||
void STFSX(ppu_opcode_t);
|
||||
void STVRX(ppu_opcode_t);
|
||||
void STFSUX(ppu_opcode_t);
|
||||
void STSWI(ppu_opcode_t);
|
||||
void STFDX(ppu_opcode_t);
|
||||
void STFDUX(ppu_opcode_t);
|
||||
void LVLXL(ppu_opcode_t);
|
||||
void LHBRX(ppu_opcode_t);
|
||||
void SRAW(ppu_opcode_t);
|
||||
void SRAD(ppu_opcode_t);
|
||||
void LVRXL(ppu_opcode_t);
|
||||
void DSS(ppu_opcode_t);
|
||||
void SRAWI(ppu_opcode_t);
|
||||
void SRADI(ppu_opcode_t);
|
||||
void EIEIO(ppu_opcode_t);
|
||||
void STVLXL(ppu_opcode_t);
|
||||
void STHBRX(ppu_opcode_t);
|
||||
void EXTSH(ppu_opcode_t);
|
||||
void STVRXL(ppu_opcode_t);
|
||||
void EXTSB(ppu_opcode_t);
|
||||
void STFIWX(ppu_opcode_t);
|
||||
void EXTSW(ppu_opcode_t);
|
||||
void ICBI(ppu_opcode_t);
|
||||
void DCBZ(ppu_opcode_t);
|
||||
void LWZ(ppu_opcode_t);
|
||||
void LWZU(ppu_opcode_t);
|
||||
void LBZ(ppu_opcode_t);
|
||||
void LBZU(ppu_opcode_t);
|
||||
void STW(ppu_opcode_t);
|
||||
void STWU(ppu_opcode_t);
|
||||
void STB(ppu_opcode_t);
|
||||
void STBU(ppu_opcode_t);
|
||||
void LHZ(ppu_opcode_t);
|
||||
void LHZU(ppu_opcode_t);
|
||||
void LHA(ppu_opcode_t);
|
||||
void LHAU(ppu_opcode_t);
|
||||
void STH(ppu_opcode_t);
|
||||
void STHU(ppu_opcode_t);
|
||||
void LMW(ppu_opcode_t);
|
||||
void STMW(ppu_opcode_t);
|
||||
void LFS(ppu_opcode_t);
|
||||
void LFSU(ppu_opcode_t);
|
||||
void LFD(ppu_opcode_t);
|
||||
void LFDU(ppu_opcode_t);
|
||||
void STFS(ppu_opcode_t);
|
||||
void STFSU(ppu_opcode_t);
|
||||
void STFD(ppu_opcode_t);
|
||||
void STFDU(ppu_opcode_t);
|
||||
void LD(ppu_opcode_t);
|
||||
void LDU(ppu_opcode_t);
|
||||
void LWA(ppu_opcode_t);
|
||||
void STD(ppu_opcode_t);
|
||||
void STDU(ppu_opcode_t);
|
||||
void FDIVS(ppu_opcode_t);
|
||||
void FSUBS(ppu_opcode_t);
|
||||
void FADDS(ppu_opcode_t);
|
||||
void FSQRTS(ppu_opcode_t);
|
||||
void FRES(ppu_opcode_t);
|
||||
void FMULS(ppu_opcode_t);
|
||||
void FMADDS(ppu_opcode_t);
|
||||
void FMSUBS(ppu_opcode_t);
|
||||
void FNMSUBS(ppu_opcode_t);
|
||||
void FNMADDS(ppu_opcode_t);
|
||||
void MTFSB1(ppu_opcode_t);
|
||||
void MCRFS(ppu_opcode_t);
|
||||
void MTFSB0(ppu_opcode_t);
|
||||
void MTFSFI(ppu_opcode_t);
|
||||
void MFFS(ppu_opcode_t);
|
||||
void MTFSF(ppu_opcode_t);
|
||||
void FCMPU(ppu_opcode_t);
|
||||
void FRSP(ppu_opcode_t);
|
||||
void FCTIW(ppu_opcode_t);
|
||||
void FCTIWZ(ppu_opcode_t);
|
||||
void FDIV(ppu_opcode_t);
|
||||
void FSUB(ppu_opcode_t);
|
||||
void FADD(ppu_opcode_t);
|
||||
void FSQRT(ppu_opcode_t);
|
||||
void FSEL(ppu_opcode_t);
|
||||
void FMUL(ppu_opcode_t);
|
||||
void FRSQRTE(ppu_opcode_t);
|
||||
void FMSUB(ppu_opcode_t);
|
||||
void FMADD(ppu_opcode_t);
|
||||
void FNMSUB(ppu_opcode_t);
|
||||
void FNMADD(ppu_opcode_t);
|
||||
void FCMPO(ppu_opcode_t);
|
||||
void FNEG(ppu_opcode_t);
|
||||
void FMR(ppu_opcode_t);
|
||||
void FNABS(ppu_opcode_t);
|
||||
void FABS(ppu_opcode_t);
|
||||
void FCTID(ppu_opcode_t);
|
||||
void FCTIDZ(ppu_opcode_t);
|
||||
void FCFID(ppu_opcode_t);
|
||||
};
|
||||
|
||||
@@ -133,7 +133,7 @@ Function* PPUTranslator::Translate(const ppu_function& info)
|
||||
const u64 base = m_reloc ? m_reloc->addr : 0;
|
||||
m_addr = info.addr - base;
|
||||
|
||||
m_thread = &*m_function->getArgumentList().begin();
|
||||
m_thread = &*m_function->arg_begin();
|
||||
m_base_loaded = m_ir->CreateLoad(m_base);
|
||||
|
||||
m_body = BasicBlock::Create(m_context, "__body", m_function);
|
||||
@@ -290,7 +290,7 @@ Value* PPUTranslator::RegInit(Value*& local)
|
||||
|
||||
Value* PPUTranslator::RegLoad(Value*& local)
|
||||
{
|
||||
const uint index = ::narrow<uint>(&local - m_locals);
|
||||
const auto index = ::narrow<uint>(&local - m_locals);
|
||||
|
||||
if (local)
|
||||
{
|
||||
@@ -315,7 +315,7 @@ void PPUTranslator::FlushRegisters()
|
||||
|
||||
for (auto& local : m_locals)
|
||||
{
|
||||
const uint index = static_cast<uint>(&local - m_locals);
|
||||
const auto index = ::narrow<uint>(&local - m_locals);
|
||||
|
||||
// Store value if necessary
|
||||
if (local && m_globals[index])
|
||||
|
||||
@@ -999,6 +999,7 @@ u32 SPUThread::get_ch_count(u32 ch)
|
||||
case SPU_RdSigNotify2: return ch_snr2.get_count();
|
||||
case MFC_RdAtomicStat: return ch_atomic_stat.get_count();
|
||||
case SPU_RdEventStat: return get_events() != 0;
|
||||
case MFC_Cmd: return std::max(16 - mfc_queue.size(), (u32)0);
|
||||
}
|
||||
|
||||
fmt::throw_exception("Unknown/illegal channel (ch=%d [%s])" HERE, ch, ch < 128 ? spu_ch_name[ch] : "???");
|
||||
@@ -1434,8 +1435,9 @@ bool SPUThread::set_ch_value(u32 ch, u32 value)
|
||||
case MFC_Cmd:
|
||||
{
|
||||
ch_mfc_cmd.cmd = MFC(value & 0xff);
|
||||
auto cmd = ch_mfc_cmd; // save and restore previous command arguments
|
||||
process_mfc_cmd();
|
||||
ch_mfc_cmd = {}; // clear non-persistent data
|
||||
ch_mfc_cmd = cmd;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/IdManager.h"
|
||||
|
||||
#include "Crypto/unedat.h"
|
||||
#include "Emu/Cell/ErrorCodes.h"
|
||||
#include "Emu/Cell/PPUThread.h"
|
||||
#include "sys_lwmutex.h"
|
||||
@@ -288,13 +289,20 @@ void _sys_process_exit2(ppu_thread& ppu, s32 status, vm::ptr<sys_exit2_param> ar
|
||||
|
||||
vm::temporary_unlock(ppu);
|
||||
|
||||
Emu.CallAfter([path = std::move(path), argv = std::move(argv), envp = std::move(envp), data = std::move(data)]()
|
||||
Emu.CallAfter([path = std::move(path), argv = std::move(argv), envp = std::move(envp), data = std::move(data), disc = vfs::get("/dev_bdvd/"), klic = fxm::get_always<LoadedNpdrmKeys_t>()->devKlic]() mutable
|
||||
{
|
||||
sys_process.success("Process finished -> %s", argv[0]);
|
||||
Emu.Stop();
|
||||
Emu.argv = std::move(argv);
|
||||
Emu.envp = std::move(envp);
|
||||
Emu.data = std::move(data);
|
||||
Emu.disc = std::move(disc);
|
||||
|
||||
if (klic != std::array<u8, 16>{})
|
||||
{
|
||||
Emu.klic.assign(klic.begin(), klic.end());
|
||||
}
|
||||
|
||||
Emu.BootGame(path, true);
|
||||
|
||||
if (Emu.IsReady() && !g_cfg.misc.autostart)
|
||||
|
||||
@@ -242,6 +242,7 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
|
||||
case 0x001: // FIFO
|
||||
render->ctrl->get = a3;
|
||||
render->ctrl->put = a4;
|
||||
render->internal_get = a3;
|
||||
break;
|
||||
|
||||
case 0x100: // Display mode set
|
||||
@@ -322,6 +323,12 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
|
||||
//a5 low bits = ret.format = base | ((base + ((size - 1) / 0x10000)) << 13) | (comp << 26) | (1 << 30);
|
||||
|
||||
auto& tile = render->tiles[a3];
|
||||
|
||||
// When tile is going to be unbinded, we can use it as a hint that the address will no longer be used as a surface and can be removed/invalidated
|
||||
// Todo: There may be more checks such as format/size/width can could be done
|
||||
if (tile.binded && a5 == 0)
|
||||
render->notify_tile_unbound(a3);
|
||||
|
||||
tile.location = ((a4 >> 32) & 0xF) - 1;
|
||||
tile.offset = ((((a4 >> 32) & 0xFFFFFFFF) >> 16) * 0x10000);
|
||||
tile.size = ((((a4 & 0x7FFFFFFF) >> 16) + 1) * 0x10000) - tile.offset;
|
||||
|
||||
@@ -11,7 +11,7 @@ const HCRYPTPROV s_crypto_provider = []() -> HCRYPTPROV
|
||||
{
|
||||
HCRYPTPROV result;
|
||||
|
||||
if (!CryptAcquireContextW(&result, nullptr, nullptr, PROV_RSA_FULL, 0))
|
||||
if (!CryptAcquireContextW(&result, nullptr, nullptr, PROV_RSA_FULL, 0) && !CryptAcquireContextW(&result, nullptr, nullptr, PROV_RSA_FULL, CRYPT_NEWKEYSET))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -456,18 +456,22 @@ void write_vertex_array_data_to_buffer(gsl::span<gsl::byte> raw_dst_span, gsl::s
|
||||
namespace
|
||||
{
|
||||
template<typename T>
|
||||
std::tuple<T, T> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
|
||||
std::tuple<T, T, u32> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
|
||||
{
|
||||
T min_index = -1;
|
||||
T max_index = 0;
|
||||
|
||||
verify(HERE), (dst.size_bytes() >= src.size_bytes());
|
||||
|
||||
size_t dst_idx = 0;
|
||||
u32 dst_idx = 0;
|
||||
for (T index : src)
|
||||
{
|
||||
if (is_primitive_restart_enabled && index == primitive_restart_index)
|
||||
{
|
||||
// List types do not need primitive restart. Just skip over this instead
|
||||
if (rsx::method_registers.current_draw_clause.is_disjoint_primitive)
|
||||
continue;
|
||||
|
||||
index = -1;
|
||||
}
|
||||
else
|
||||
@@ -478,125 +482,108 @@ std::tuple<T, T> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::span<T>
|
||||
|
||||
dst[dst_idx++] = index;
|
||||
}
|
||||
return std::make_tuple(min_index, max_index);
|
||||
return std::make_tuple(min_index, max_index, dst_idx);
|
||||
}
|
||||
|
||||
// FIXME: expanded primitive type may not support primitive restart correctly
|
||||
template<typename T>
|
||||
std::tuple<T, T> expand_indexed_triangle_fan(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
|
||||
std::tuple<T, T, u32> expand_indexed_triangle_fan(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
|
||||
{
|
||||
T min_index = -1;
|
||||
const T invalid_index = (T)-1;
|
||||
|
||||
T min_index = invalid_index;
|
||||
T max_index = 0;
|
||||
|
||||
verify(HERE), (dst.size() >= 3 * (src.size() - 2));
|
||||
|
||||
const T index0 = src[0];
|
||||
if (!is_primitive_restart_enabled || index0 != -1) // Cut
|
||||
u32 dst_idx = 0;
|
||||
u32 src_idx = 0;
|
||||
|
||||
bool needs_anchor = true;
|
||||
T anchor = invalid_index;
|
||||
T last_index = invalid_index;
|
||||
|
||||
for (size_t src_idx = 0; src_idx < src.size(); ++src_idx)
|
||||
{
|
||||
min_index = std::min(min_index, index0);
|
||||
max_index = std::max(max_index, index0);
|
||||
if (needs_anchor)
|
||||
{
|
||||
if (is_primitive_restart_enabled && src[src_idx] == primitive_restart_index)
|
||||
continue;
|
||||
|
||||
anchor = src[src_idx];
|
||||
needs_anchor = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (is_primitive_restart_enabled && src[src_idx] == primitive_restart_index)
|
||||
{
|
||||
needs_anchor = true;
|
||||
last_index = invalid_index;
|
||||
continue;
|
||||
}
|
||||
|
||||
T index = src[src_idx];
|
||||
max_index = std::max(max_index, index);
|
||||
min_index = std::min(min_index, index);
|
||||
|
||||
if (last_index == invalid_index)
|
||||
{
|
||||
//Need at least one anchor and one outer index to create a triange
|
||||
last_index = index;
|
||||
continue;
|
||||
}
|
||||
|
||||
dst[dst_idx++] = anchor;
|
||||
dst[dst_idx++] = last_index;
|
||||
dst[dst_idx++] = index;
|
||||
|
||||
last_index = index;
|
||||
}
|
||||
|
||||
size_t dst_idx = 0;
|
||||
while (src.size() > 2)
|
||||
{
|
||||
gsl::span<to_be_t<const T>> tri_indexes = src.subspan(0, 2);
|
||||
T index1 = tri_indexes[0];
|
||||
if (is_primitive_restart_enabled && index1 == primitive_restart_index)
|
||||
{
|
||||
index1 = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_index = std::min(min_index, index1);
|
||||
max_index = std::max(max_index, index1);
|
||||
}
|
||||
T index2 = tri_indexes[1];
|
||||
if (is_primitive_restart_enabled && index2 == primitive_restart_index)
|
||||
{
|
||||
index2 = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_index = std::min(min_index, index2);
|
||||
max_index = std::max(max_index, index2);
|
||||
}
|
||||
|
||||
dst[dst_idx++] = index0;
|
||||
dst[dst_idx++] = index1;
|
||||
dst[dst_idx++] = index2;
|
||||
|
||||
src = src.subspan(2);
|
||||
}
|
||||
return std::make_tuple(min_index, max_index);
|
||||
return std::make_tuple(min_index, max_index, dst_idx);
|
||||
}
|
||||
|
||||
// FIXME: expanded primitive type may not support primitive restart correctly
|
||||
template<typename T>
|
||||
std::tuple<T, T> expand_indexed_quads(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
|
||||
std::tuple<T, T, u32> expand_indexed_quads(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
|
||||
{
|
||||
T min_index = -1;
|
||||
T max_index = 0;
|
||||
|
||||
verify(HERE), (4 * dst.size_bytes() >= 6 * src.size_bytes());
|
||||
|
||||
size_t dst_idx = 0;
|
||||
while (!src.empty())
|
||||
u32 dst_idx = 0;
|
||||
u8 set_size = 0;
|
||||
T tmp_indices[4];
|
||||
|
||||
for (int src_idx = 0; src_idx < src.size(); ++src_idx)
|
||||
{
|
||||
gsl::span<to_be_t<const T>> quad_indexes = src.subspan(0, 4);
|
||||
T index0 = quad_indexes[0];
|
||||
if (is_primitive_restart_enabled && index0 == primitive_restart_index)
|
||||
T index = src[src_idx];
|
||||
if (is_primitive_restart_enabled && index == primitive_restart_index)
|
||||
{
|
||||
index0 = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_index = std::min(min_index, index0);
|
||||
max_index = std::max(max_index, index0);
|
||||
}
|
||||
T index1 = quad_indexes[1];
|
||||
if (is_primitive_restart_enabled && index1 == primitive_restart_index)
|
||||
{
|
||||
index1 = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_index = std::min(min_index, index1);
|
||||
max_index = std::max(max_index, index1);
|
||||
}
|
||||
T index2 = quad_indexes[2];
|
||||
if (is_primitive_restart_enabled && index2 == primitive_restart_index)
|
||||
{
|
||||
index2 = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_index = std::min(min_index, index2);
|
||||
max_index = std::max(max_index, index2);
|
||||
}
|
||||
T index3 = quad_indexes[3];
|
||||
if (is_primitive_restart_enabled &&index3 == primitive_restart_index)
|
||||
{
|
||||
index3 = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
min_index = std::min(min_index, index3);
|
||||
max_index = std::max(max_index, index3);
|
||||
//empty temp buffer
|
||||
set_size = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// First triangle
|
||||
dst[dst_idx++] = index0;
|
||||
dst[dst_idx++] = index1;
|
||||
dst[dst_idx++] = index2;
|
||||
// Second triangle
|
||||
dst[dst_idx++] = index2;
|
||||
dst[dst_idx++] = index3;
|
||||
dst[dst_idx++] = index0;
|
||||
tmp_indices[set_size++] = index;
|
||||
max_index = std::max(max_index, index);
|
||||
min_index = std::min(min_index, index);
|
||||
|
||||
src = src.subspan(4);
|
||||
if (set_size == 4)
|
||||
{
|
||||
// First triangle
|
||||
dst[dst_idx++] = tmp_indices[0];
|
||||
dst[dst_idx++] = tmp_indices[1];
|
||||
dst[dst_idx++] = tmp_indices[2];
|
||||
// Second triangle
|
||||
dst[dst_idx++] = tmp_indices[2];
|
||||
dst[dst_idx++] = tmp_indices[3];
|
||||
dst[dst_idx++] = tmp_indices[0];
|
||||
|
||||
set_size = 0;
|
||||
}
|
||||
}
|
||||
return std::make_tuple(min_index, max_index);
|
||||
|
||||
return std::make_tuple(min_index, max_index, dst_idx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -714,7 +701,7 @@ namespace
|
||||
|
||||
// TODO: Unify indexed and non indexed primitive expansion ?
|
||||
template<typename T>
|
||||
std::tuple<T, T> write_index_array_data_to_buffer_impl(gsl::span<T> dst,
|
||||
std::tuple<T, T, u32> write_index_array_data_to_buffer_impl(gsl::span<T> dst,
|
||||
gsl::span<const be_t<T>> src,
|
||||
rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments,
|
||||
std::function<bool(rsx::primitive_type)> expands)
|
||||
@@ -743,7 +730,7 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst,
|
||||
std::tuple<u32, u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst,
|
||||
gsl::span<const gsl::byte> src,
|
||||
rsx::index_array_type type, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments,
|
||||
std::function<bool(rsx::primitive_type)> expands)
|
||||
|
||||
@@ -29,10 +29,10 @@ u32 get_index_type_size(rsx::index_array_type type);
|
||||
|
||||
/**
|
||||
* Write count indexes using (first, first + count) ranges.
|
||||
* Returns min/max index found during the process.
|
||||
* Returns min/max index found during the process and the number of valid indices written to the buffer.
|
||||
* The function expands index buffer for non native primitive type if expands(draw_mode) return true.
|
||||
*/
|
||||
std::tuple<u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst, gsl::span<const gsl::byte> src,
|
||||
std::tuple<u32, u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst, gsl::span<const gsl::byte> src,
|
||||
rsx::index_array_type, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments,
|
||||
std::function<bool(rsx::primitive_type)> expands);
|
||||
|
||||
|
||||
@@ -735,21 +735,12 @@ std::string FragmentProgramDecompiler::Decompile()
|
||||
if (SIP()) break;
|
||||
if (handle_tex_srb(opcode)) break;
|
||||
|
||||
if (forced_unit == FORCE_NONE)
|
||||
{
|
||||
if (handle_sct(opcode)) break;
|
||||
if (handle_scb(opcode)) break;
|
||||
}
|
||||
else if (forced_unit == FORCE_SCT)
|
||||
{
|
||||
forced_unit = FORCE_NONE;
|
||||
if (handle_sct(opcode)) break;
|
||||
}
|
||||
else if (forced_unit == FORCE_SCB)
|
||||
{
|
||||
forced_unit = FORCE_NONE;
|
||||
if (handle_scb(opcode)) break;
|
||||
}
|
||||
//FENCT/FENCB do not actually reject instructions if they dont match the forced unit
|
||||
//Tested with Dark Souls II where the repecting FENCX instruction will result in empty luminance averaging shaders
|
||||
//TODO: More reasearch is needed to determine what real HW does
|
||||
if (handle_sct(opcode)) break;
|
||||
if (handle_scb(opcode)) break;
|
||||
forced_unit = FORCE_NONE;
|
||||
|
||||
LOG_ERROR(RSX, "Unknown/illegal instruction: 0x%x (forced unit %d)", opcode, prev_force_unit);
|
||||
break;
|
||||
|
||||
@@ -278,6 +278,8 @@ namespace glsl
|
||||
OS << "vec4 read_location(int location)\n";
|
||||
OS << "{\n";
|
||||
OS << " attribute_desc desc = fetch_desc(location);\n";
|
||||
OS << " //if attribute is disabled return 1 (makes all operations with it nop except add/sub - TODO)\n";
|
||||
OS << " if (desc.attribute_size == 0) return vec4(1.);\n";
|
||||
OS << "\n";
|
||||
OS << " int vertex_id = " << vertex_id_name << " - int(vertex_base_index);\n";
|
||||
OS << " if (desc.frequency == 0)\n";
|
||||
@@ -334,11 +336,6 @@ namespace glsl
|
||||
OS << " return decodeLinearDepth(texture(tex, coord.xy).r);\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << "vec4 texture2DReconstruct(sampler2DRect tex, vec2 coord)\n";
|
||||
OS << "{\n";
|
||||
OS << " return decodeLinearDepth(texture(tex, coord.xy).r);\n";
|
||||
OS << "}\n\n";
|
||||
|
||||
OS << "vec4 get_wpos()\n";
|
||||
OS << "{\n";
|
||||
OS << " float abs_scale = abs(wpos_scale);\n";
|
||||
@@ -350,4 +347,75 @@ namespace glsl
|
||||
{
|
||||
program_common::insert_fog_declaration(OS, "vec4", "fog_c");
|
||||
}
|
||||
|
||||
static std::string getFunctionImpl(FUNCTION f)
|
||||
{
|
||||
switch (f)
|
||||
{
|
||||
default:
|
||||
abort();
|
||||
case FUNCTION::FUNCTION_DP2:
|
||||
return "vec4(dot($0.xy, $1.xy))";
|
||||
case FUNCTION::FUNCTION_DP2A:
|
||||
return "vec4(dot($0.xy, $1.xy) + $2.x)";
|
||||
case FUNCTION::FUNCTION_DP3:
|
||||
return "vec4(dot($0.xyz, $1.xyz))";
|
||||
case FUNCTION::FUNCTION_DP4:
|
||||
return "vec4(dot($0, $1))";
|
||||
case FUNCTION::FUNCTION_DPH:
|
||||
return "vec4(dot(vec4($0.xyz, 1.0), $1))";
|
||||
case FUNCTION::FUNCTION_SFL:
|
||||
return "vec4(0., 0., 0., 0.)";
|
||||
case FUNCTION::FUNCTION_STR:
|
||||
return "vec4(1., 1., 1., 1.)";
|
||||
case FUNCTION::FUNCTION_FRACT:
|
||||
return "fract($0)";
|
||||
case FUNCTION::FUNCTION_REFL:
|
||||
return "vec4($0 - 2.0 * (dot($0, $1)) * $1)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D:
|
||||
return "texture($t, $0.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ:
|
||||
return "textureProj($t, $0.x, $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD:
|
||||
return "textureLod($t, $0.x, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD:
|
||||
return "textureGrad($t, $0.x, $1.x, $2.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D:
|
||||
return "texture($t, $0.xy * texture_parameters[$_i].xy)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ:
|
||||
return "textureProj($t, $0 , $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD:
|
||||
return "textureLod($t, $0.xy * texture_parameters[$_i].xy, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD:
|
||||
return "textureGrad($t, $0.xy * texture_parameters[$_i].xy , $1.xy, $2.xy)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D:
|
||||
return "texture($t, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ:
|
||||
return "textureProj($t, $0, $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE:
|
||||
return "texture($t, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ:
|
||||
return "texture($t, ($0.xyz / $0.w))";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD:
|
||||
return "textureLod($t, $0.xyz, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD:
|
||||
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D:
|
||||
return "texture($t, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ:
|
||||
return "textureProj($t, $0.xyzw, $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD:
|
||||
return "textureLod($t, $0.xyz, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_GRAD:
|
||||
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
|
||||
case FUNCTION::FUNCTION_DFDX:
|
||||
return "dFdx($0)";
|
||||
case FUNCTION::FUNCTION_DFDY:
|
||||
return "dFdy($0)";
|
||||
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D:
|
||||
return "textureLod($t, $0.xy, 0)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA:
|
||||
return "texture2DReconstruct($t, $0.xy * texture_parameters[$_i].xy)";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,8 @@ struct data_heap
|
||||
size_t m_min_guard_size; //If an allocation touches the guard region, reset the heap to avoid going over budget
|
||||
size_t m_current_allocated_size;
|
||||
size_t m_largest_allocated_pool;
|
||||
|
||||
char* m_name;
|
||||
public:
|
||||
data_heap() = default;
|
||||
~data_heap() = default;
|
||||
@@ -54,8 +56,10 @@ public:
|
||||
|
||||
size_t m_get_pos; // End of free space
|
||||
|
||||
void init(size_t heap_size, size_t min_guard_size=0x10000)
|
||||
void init(size_t heap_size, const char* buffer_name = "unnamed", size_t min_guard_size=0x10000)
|
||||
{
|
||||
m_name = const_cast<char*>(buffer_name);
|
||||
|
||||
m_size = heap_size;
|
||||
m_put_pos = 0;
|
||||
m_get_pos = heap_size - 1;
|
||||
@@ -71,8 +75,8 @@ public:
|
||||
{
|
||||
if (!can_alloc<Alignement>(size))
|
||||
{
|
||||
fmt::throw_exception("Working buffer not big enough, buffer_length=%d allocated=%d requested=%d guard=%d largest_pool=%d" HERE,
|
||||
m_size, m_current_allocated_size, size, m_min_guard_size, m_largest_allocated_pool);
|
||||
fmt::throw_exception("[%s] Working buffer not big enough, buffer_length=%d allocated=%d requested=%d guard=%d largest_pool=%d" HERE,
|
||||
m_name, m_size, m_current_allocated_size, size, m_min_guard_size, m_largest_allocated_pool);
|
||||
}
|
||||
|
||||
size_t alloc_size = align(size, Alignement);
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace rsx
|
||||
struct surface_subresource_storage
|
||||
{
|
||||
surface_type surface = nullptr;
|
||||
u32 base_address = 0;
|
||||
|
||||
u16 x = 0;
|
||||
u16 y = 0;
|
||||
@@ -29,8 +30,8 @@ namespace rsx
|
||||
|
||||
surface_subresource_storage() {}
|
||||
|
||||
surface_subresource_storage(surface_type src, u16 X, u16 Y, u16 W, u16 H, bool _Bound, bool _Depth, bool _Clipped = false)
|
||||
: surface(src), x(X), y(Y), w(W), h(H), is_bound(_Bound), is_depth_surface(_Depth), is_clipped(_Clipped)
|
||||
surface_subresource_storage(u32 addr, surface_type src, u16 X, u16 Y, u16 W, u16 H, bool _Bound, bool _Depth, bool _Clipped = false)
|
||||
: base_address(addr), surface(src), x(X), y(Y), w(W), h(H), is_bound(_Bound), is_depth_surface(_Depth), is_clipped(_Clipped)
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -46,11 +47,25 @@ namespace rsx
|
||||
template <typename image_storage_type>
|
||||
struct render_target_descriptor
|
||||
{
|
||||
GcmTileInfo *tile = nullptr;
|
||||
rsx::surface_antialiasing aa_mode = rsx::surface_antialiasing::center_1_sample;
|
||||
|
||||
u16 raster_offset_x = 0;
|
||||
u16 raster_offset_y = 0;
|
||||
u32 raster_address_offset = 0;
|
||||
|
||||
virtual image_storage_type get_surface() const = 0;
|
||||
virtual u16 get_surface_width() const = 0;
|
||||
virtual u16 get_surface_height() const = 0;
|
||||
virtual u16 get_rsx_pitch() const = 0;
|
||||
virtual u16 get_native_pitch() const = 0;
|
||||
|
||||
void set_raster_offset(u16 x, u16 y, u8 bpp)
|
||||
{
|
||||
raster_offset_x = x;
|
||||
raster_offset_y = y;
|
||||
raster_address_offset = (y * get_rsx_pitch()) + (x * bpp);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -114,6 +129,7 @@ namespace rsx
|
||||
std::tuple<u32, surface_type> m_bound_depth_stencil = {};
|
||||
|
||||
std::list<surface_storage_type> invalidated_resources;
|
||||
u64 cache_tag = 0ull;
|
||||
|
||||
surface_store() = default;
|
||||
~surface_store() = default;
|
||||
@@ -163,8 +179,11 @@ namespace rsx
|
||||
new_surface_storage = std::move(rtt);
|
||||
|
||||
if (old_surface)
|
||||
{
|
||||
//Exchange this surface with the invalidated one
|
||||
Traits::notify_surface_invalidated(old_surface_storage);
|
||||
rtt = std::move(old_surface_storage);
|
||||
}
|
||||
else
|
||||
//rtt is now empty - erase it
|
||||
invalidated_resources.erase(It);
|
||||
@@ -177,8 +196,11 @@ namespace rsx
|
||||
}
|
||||
|
||||
if (old_surface != nullptr && new_surface == nullptr)
|
||||
{
|
||||
//This was already determined to be invalid and is excluded from testing above
|
||||
Traits::notify_surface_invalidated(old_surface_storage);
|
||||
invalidated_resources.push_back(std::move(old_surface_storage));
|
||||
}
|
||||
|
||||
if (new_surface != nullptr)
|
||||
{
|
||||
@@ -227,8 +249,11 @@ namespace rsx
|
||||
new_surface_storage = std::move(ds);
|
||||
|
||||
if (old_surface)
|
||||
{
|
||||
//Exchange this surface with the invalidated one
|
||||
Traits::notify_surface_invalidated(old_surface_storage);
|
||||
ds = std::move(old_surface_storage);
|
||||
}
|
||||
else
|
||||
invalidated_resources.erase(It);
|
||||
|
||||
@@ -240,8 +265,11 @@ namespace rsx
|
||||
}
|
||||
|
||||
if (old_surface != nullptr && new_surface == nullptr)
|
||||
{
|
||||
//This was already determined to be invalid and is excluded from testing above
|
||||
Traits::notify_surface_invalidated(old_surface_storage);
|
||||
invalidated_resources.push_back(std::move(old_surface_storage));
|
||||
}
|
||||
|
||||
if (new_surface != nullptr)
|
||||
{
|
||||
@@ -272,6 +300,8 @@ namespace rsx
|
||||
// u32 clip_x = clip_horizontal_reg;
|
||||
// u32 clip_y = clip_vertical_reg;
|
||||
|
||||
cache_tag++;
|
||||
|
||||
// Make previous RTTs sampleable
|
||||
for (std::tuple<u32, surface_type> &rtt : m_bound_render_targets)
|
||||
{
|
||||
@@ -494,8 +524,11 @@ namespace rsx
|
||||
|
||||
if (surface == ref)
|
||||
{
|
||||
Traits::notify_surface_invalidated(It->second);
|
||||
invalidated_resources.push_back(std::move(It->second));
|
||||
m_render_targets_storage.erase(It);
|
||||
|
||||
cache_tag++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -509,21 +542,63 @@ namespace rsx
|
||||
|
||||
if (surface == ref)
|
||||
{
|
||||
Traits::notify_surface_invalidated(It->second);
|
||||
invalidated_resources.push_back(std::move(It->second));
|
||||
m_depth_stencil_storage.erase(It);
|
||||
|
||||
cache_tag++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates surface that exists at an address
|
||||
*/
|
||||
void invalidate_surface_address(u32 addr, bool depth)
|
||||
{
|
||||
if (address_is_bound(addr, depth))
|
||||
{
|
||||
LOG_ERROR(RSX, "Cannot invalidate a currently bound render target!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!depth)
|
||||
{
|
||||
auto It = m_render_targets_storage.find(addr);
|
||||
if (It != m_render_targets_storage.end())
|
||||
{
|
||||
Traits::notify_surface_invalidated(It->second);
|
||||
invalidated_resources.push_back(std::move(It->second));
|
||||
m_render_targets_storage.erase(It);
|
||||
|
||||
cache_tag++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto It = m_depth_stencil_storage.find(addr);
|
||||
if (It != m_depth_stencil_storage.end())
|
||||
{
|
||||
Traits::notify_surface_invalidated(It->second);
|
||||
invalidated_resources.push_back(std::move(It->second));
|
||||
m_depth_stencil_storage.erase(It);
|
||||
|
||||
cache_tag++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clipping and fitting lookup funcrions
|
||||
* surface_overlaps - returns true if surface overlaps a given surface address and returns the relative x and y position of the surface address within the surface
|
||||
* address_is_bound - returns true if the surface at a given address is actively bound
|
||||
* get_surface_subresource_if_available - returns a sectiion descriptor that allows to crop surfaces stored in memory
|
||||
*/
|
||||
bool surface_overlaps_address(surface_type surface, u32 surface_address, u32 texaddr, u16 *x, u16 *y, bool scale_to_fit, bool double_height)
|
||||
bool surface_overlaps_address(surface_type surface, u32 surface_address, u32 texaddr, u16 *x, u16 *y)
|
||||
{
|
||||
bool is_subslice = false;
|
||||
u16 x_offset = 0;
|
||||
@@ -532,52 +607,70 @@ namespace rsx
|
||||
if (surface_address > texaddr)
|
||||
return false;
|
||||
|
||||
u32 offset = texaddr - surface_address;
|
||||
if (texaddr >= surface_address)
|
||||
const u32 offset = texaddr - surface_address;
|
||||
if (offset == 0)
|
||||
{
|
||||
if (offset == 0)
|
||||
*x = 0;
|
||||
*y = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
surface_format_info info;
|
||||
Traits::get_surface_info(surface, &info);
|
||||
|
||||
bool doubled_x = false;
|
||||
bool doubled_y = false;
|
||||
|
||||
switch (surface->aa_mode)
|
||||
{
|
||||
case rsx::surface_antialiasing::square_rotated_4_samples:
|
||||
case rsx::surface_antialiasing::square_centered_4_samples:
|
||||
doubled_y = true;
|
||||
//fall through
|
||||
case rsx::surface_antialiasing::diagonal_centered_2_samples:
|
||||
doubled_x = true;
|
||||
break;
|
||||
}
|
||||
|
||||
u32 range = info.rsx_pitch * info.surface_height;
|
||||
if (doubled_y) range <<= 1;
|
||||
|
||||
if (offset < range)
|
||||
{
|
||||
y_offset = (offset / info.rsx_pitch);
|
||||
x_offset = (offset % info.rsx_pitch) / info.bpp;
|
||||
|
||||
if (doubled_x) x_offset /= 2;
|
||||
if (doubled_y) y_offset /= 2;
|
||||
|
||||
is_subslice = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
surface_format_info info;
|
||||
Traits::get_surface_info(surface, &info);
|
||||
|
||||
u32 range = info.rsx_pitch * info.surface_height;
|
||||
if (double_height) range *= 2;
|
||||
|
||||
if (offset < range)
|
||||
{
|
||||
const u32 y = (offset / info.rsx_pitch);
|
||||
u32 x = (offset % info.rsx_pitch) / info.bpp;
|
||||
|
||||
if (scale_to_fit)
|
||||
{
|
||||
const f32 x_scale = (f32)info.rsx_pitch / info.native_pitch;
|
||||
x = (u32)((f32)x / x_scale);
|
||||
}
|
||||
|
||||
x_offset = x;
|
||||
y_offset = y;
|
||||
|
||||
if (double_height) y_offset /= 2;
|
||||
is_subslice = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_subslice)
|
||||
{
|
||||
*x = x_offset;
|
||||
*y = y_offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_subslice)
|
||||
{
|
||||
*x = x_offset;
|
||||
*y = y_offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//Fast hit test
|
||||
inline bool surface_overlaps_address_fast(surface_type surface, u32 surface_address, u32 texaddr)
|
||||
{
|
||||
if (surface_address > texaddr)
|
||||
return false;
|
||||
|
||||
const u32 offset = texaddr - surface_address;
|
||||
const u32 range = surface->get_rsx_pitch() * surface->get_surface_height();
|
||||
|
||||
return (offset < range);
|
||||
}
|
||||
|
||||
bool address_is_bound(u32 address, bool is_depth) const
|
||||
{
|
||||
if (is_depth)
|
||||
@@ -604,30 +697,35 @@ namespace rsx
|
||||
return true;
|
||||
}
|
||||
|
||||
surface_subresource get_surface_subresource_if_applicable(u32 texaddr, u16 requested_width, u16 requested_height, u16 requested_pitch, bool scale_to_fit = false, bool crop = false, bool ignore_depth_formats = false, bool double_height = false)
|
||||
surface_subresource get_surface_subresource_if_applicable(u32 texaddr, u16 requested_width, u16 requested_height, u16 requested_pitch,
|
||||
bool crop = false, bool ignore_depth_formats = false, bool ignore_color_formats = false)
|
||||
{
|
||||
auto test_surface = [&](surface_type surface, u32 this_address, u16 &x_offset, u16 &y_offset, u16 &w, u16 &h, bool &clipped)
|
||||
{
|
||||
if (surface_overlaps_address(surface, this_address, texaddr, &x_offset, &y_offset, scale_to_fit, double_height))
|
||||
if (surface_overlaps_address(surface, this_address, texaddr, &x_offset, &y_offset))
|
||||
{
|
||||
surface_format_info info;
|
||||
Traits::get_surface_info(surface, &info);
|
||||
|
||||
if (info.rsx_pitch != requested_pitch)
|
||||
return false;
|
||||
|
||||
u16 real_width = requested_width;
|
||||
u16 real_height = requested_height;
|
||||
|
||||
if (scale_to_fit)
|
||||
switch (surface->aa_mode)
|
||||
{
|
||||
f32 pitch_scaling = (f32)requested_pitch / info.native_pitch;
|
||||
real_width = (u16)((f32)requested_width / pitch_scaling);
|
||||
case rsx::surface_antialiasing::diagonal_centered_2_samples:
|
||||
real_width /= 2;
|
||||
break;
|
||||
case rsx::surface_antialiasing::square_centered_4_samples:
|
||||
case rsx::surface_antialiasing::square_rotated_4_samples:
|
||||
real_width /= 2;
|
||||
real_height /= 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (region_fits(info.surface_width, info.surface_height, x_offset, y_offset, real_width, requested_height))
|
||||
if (region_fits(info.surface_width, info.surface_height, x_offset, y_offset, real_width, real_height))
|
||||
{
|
||||
w = real_width;
|
||||
h = requested_height;
|
||||
h = real_height;
|
||||
clipped = false;
|
||||
|
||||
return true;
|
||||
@@ -640,17 +738,17 @@ namespace rsx
|
||||
u16 remaining_height = info.surface_height - y_offset;
|
||||
|
||||
w = std::min(real_width, remaining_width);
|
||||
h = std::min(requested_height, remaining_height);
|
||||
h = std::min(real_height, remaining_height);
|
||||
clipped = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (info.surface_width >= requested_width && info.surface_height >= requested_height)
|
||||
if (info.surface_width >= real_width && info.surface_height >= real_height)
|
||||
{
|
||||
LOG_WARNING(RSX, "Overlapping surface exceeds bounds; returning full surface region");
|
||||
w = real_width;
|
||||
h = requested_height;
|
||||
h = real_height;
|
||||
clipped = true;
|
||||
|
||||
return true;
|
||||
@@ -668,26 +766,55 @@ namespace rsx
|
||||
u16 w;
|
||||
u16 h;
|
||||
|
||||
for (auto &tex_info : m_render_targets_storage)
|
||||
if (!ignore_color_formats)
|
||||
{
|
||||
u32 this_address = std::get<0>(tex_info);
|
||||
surface = std::get<1>(tex_info).get();
|
||||
for (auto &tex_info : m_render_targets_storage)
|
||||
{
|
||||
const u32 this_address = std::get<0>(tex_info);
|
||||
if (texaddr < this_address)
|
||||
continue;
|
||||
|
||||
if (test_surface(surface, this_address, x_offset, y_offset, w, h, clipped))
|
||||
return { surface, x_offset, y_offset, w, h, address_is_bound(this_address, false), false, clipped };
|
||||
surface = std::get<1>(tex_info).get();
|
||||
if (surface->get_rsx_pitch() != requested_pitch)
|
||||
continue;
|
||||
|
||||
if (requested_width == 0 || requested_height == 0)
|
||||
{
|
||||
if (!surface_overlaps_address_fast(surface, this_address, texaddr))
|
||||
continue;
|
||||
else
|
||||
return{ this_address, surface, 0, 0, 0, 0, false, false, false };
|
||||
}
|
||||
|
||||
if (test_surface(surface, this_address, x_offset, y_offset, w, h, clipped))
|
||||
return{ this_address, surface, x_offset, y_offset, w, h, address_is_bound(this_address, false), false, clipped };
|
||||
}
|
||||
}
|
||||
|
||||
if (ignore_depth_formats)
|
||||
return{};
|
||||
|
||||
//Check depth surfaces for overlap
|
||||
for (auto &tex_info : m_depth_stencil_storage)
|
||||
if (!ignore_depth_formats)
|
||||
{
|
||||
u32 this_address = std::get<0>(tex_info);
|
||||
surface = std::get<1>(tex_info).get();
|
||||
//Check depth surfaces for overlap
|
||||
for (auto &tex_info : m_depth_stencil_storage)
|
||||
{
|
||||
const u32 this_address = std::get<0>(tex_info);
|
||||
if (texaddr < this_address)
|
||||
continue;
|
||||
|
||||
if (test_surface(surface, this_address, x_offset, y_offset, w, h, clipped))
|
||||
return { surface, x_offset, y_offset, w, h, address_is_bound(this_address, true), true, clipped };
|
||||
surface = std::get<1>(tex_info).get();
|
||||
if (surface->get_rsx_pitch() != requested_pitch)
|
||||
continue;
|
||||
|
||||
if (requested_width == 0 || requested_height == 0)
|
||||
{
|
||||
if (!surface_overlaps_address_fast(surface, this_address, texaddr))
|
||||
continue;
|
||||
else
|
||||
return{ this_address, surface, 0, 0, 0, 0, false, true, false };
|
||||
}
|
||||
|
||||
if (test_surface(surface, this_address, x_offset, y_offset, w, h, clipped))
|
||||
return{ this_address, surface, x_offset, y_offset, w, h, address_is_bound(this_address, true), true, clipped };
|
||||
}
|
||||
}
|
||||
|
||||
return{};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -410,7 +410,7 @@ namespace
|
||||
gsl::span<gsl::byte> dst{
|
||||
reinterpret_cast<gsl::byte*>(mapped_buffer), ::narrow<u32>(buffer_size)};
|
||||
|
||||
std::tie(min_index, max_index) =
|
||||
std::tie(min_index, max_index, index_count) =
|
||||
write_index_array_data_to_buffer(dst, command.raw_index_buffer, indexed_type,
|
||||
rsx::method_registers.current_draw_clause.primitive,
|
||||
rsx::method_registers.restart_index_enabled(),
|
||||
|
||||
@@ -183,4 +183,5 @@ protected:
|
||||
virtual std::array<std::vector<gsl::byte>, 4> copy_render_targets_to_memory() override;
|
||||
virtual std::array<std::vector<gsl::byte>, 2> copy_depth_stencil_buffer_to_memory() override;
|
||||
virtual std::pair<std::string, std::string> get_programs() const override;
|
||||
virtual void notify_tile_unbound(u32 tile) override;
|
||||
};
|
||||
|
||||
@@ -54,7 +54,7 @@ void D3D12GSRender::load_program()
|
||||
};
|
||||
|
||||
get_current_vertex_program();
|
||||
get_current_fragment_program(rtt_lookup_func);
|
||||
get_current_fragment_program_legacy(rtt_lookup_func);
|
||||
|
||||
if (!current_fragment_program.valid)
|
||||
return;
|
||||
@@ -316,4 +316,10 @@ std::pair<std::string, std::string> D3D12GSRender::get_programs() const
|
||||
{
|
||||
return std::make_pair(m_pso_cache.get_transform_program(current_vertex_program).content, m_pso_cache.get_shader_program(current_fragment_program).content);
|
||||
}
|
||||
|
||||
void D3D12GSRender::notify_tile_unbound(u32 tile)
|
||||
{
|
||||
u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location);
|
||||
m_rtts.invalidate_surface_address(addr, false);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -103,9 +103,6 @@ namespace
|
||||
|
||||
void D3D12GSRender::clear_surface(u32 arg)
|
||||
{
|
||||
// Ignore clear if surface target is set to CELL_GCM_SURFACE_TARGET_NONE
|
||||
if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return;
|
||||
|
||||
std::chrono::time_point<steady_clock> start_duration = steady_clock::now();
|
||||
|
||||
std::chrono::time_point<steady_clock> rtt_duration_start = steady_clock::now();
|
||||
|
||||
@@ -142,6 +142,9 @@ struct render_target_traits
|
||||
//TODO
|
||||
}
|
||||
|
||||
static
|
||||
void notify_surface_invalidated(const ComPtr<ID3D12Resource>&)
|
||||
{}
|
||||
|
||||
static
|
||||
bool rtt_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, surface_color_format surface_color_format, size_t width, size_t height, bool=false)
|
||||
|
||||
@@ -4,77 +4,6 @@
|
||||
|
||||
namespace gl
|
||||
{
|
||||
std::string getFunctionImpl(FUNCTION f)
|
||||
{
|
||||
switch (f)
|
||||
{
|
||||
default:
|
||||
abort();
|
||||
case FUNCTION::FUNCTION_DP2:
|
||||
return "vec4(dot($0.xy, $1.xy))";
|
||||
case FUNCTION::FUNCTION_DP2A:
|
||||
return "vec4(dot($0.xy, $1.xy) + $2.x)";
|
||||
case FUNCTION::FUNCTION_DP3:
|
||||
return "vec4(dot($0.xyz, $1.xyz))";
|
||||
case FUNCTION::FUNCTION_DP4:
|
||||
return "vec4(dot($0, $1))";
|
||||
case FUNCTION::FUNCTION_DPH:
|
||||
return "vec4(dot(vec4($0.xyz, 1.0), $1))";
|
||||
case FUNCTION::FUNCTION_SFL:
|
||||
return "vec4(0., 0., 0., 0.)";
|
||||
case FUNCTION::FUNCTION_STR:
|
||||
return "vec4(1., 1., 1., 1.)";
|
||||
case FUNCTION::FUNCTION_FRACT:
|
||||
return "fract($0)";
|
||||
case FUNCTION::FUNCTION_REFL:
|
||||
return "vec4($0 - 2.0 * (dot($0, $1)) * $1)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D:
|
||||
return "texture($t, $0.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ:
|
||||
return "textureProj($t, $0.x, $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD:
|
||||
return "textureLod($t, $0.x, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD:
|
||||
return "textureGrad($t, $0.x, $1.x, $2.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D:
|
||||
return "texture($t, $0.xy * $t_coord_scale)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ:
|
||||
return "textureProj($t, $0 , $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD:
|
||||
return "textureLod($t, $0.xy * $t_coord_scale, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD:
|
||||
return "textureGrad($t, $0.xy * $t_coord_scale , $1.xy, $2.xy)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D:
|
||||
return "texture($t, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ:
|
||||
return "textureProj($t, $0, $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE:
|
||||
return "texture($t, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ:
|
||||
return "texture($t, ($0.xyz / $0.w))";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD:
|
||||
return "textureLod($t, $0.xyz, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD:
|
||||
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D:
|
||||
return "texture($t, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ:
|
||||
return "textureProj($t, $0.xyzw, $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD:
|
||||
return "textureLod($t, $0.xyz, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_GRAD:
|
||||
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
|
||||
case FUNCTION::FUNCTION_DFDX:
|
||||
return "dFdx($0)";
|
||||
case FUNCTION::FUNCTION_DFDY:
|
||||
return "dFdy($0)";
|
||||
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D:
|
||||
return "textureLod($t, $0.xy, 0)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA:
|
||||
return "texture2DReconstruct($t, $0.xy * $t_coord_scale)";
|
||||
}
|
||||
}
|
||||
|
||||
int get_varying_register_location(const std::string &var_name)
|
||||
{
|
||||
static const std::pair<std::string, int> reg_table[] =
|
||||
|
||||
@@ -6,6 +6,5 @@
|
||||
|
||||
namespace gl
|
||||
{
|
||||
std::string getFunctionImpl(FUNCTION f);
|
||||
int get_varying_register_location(const std::string &var_name);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ std::string GLFragmentDecompilerThread::getFloatTypeName(size_t elementCount)
|
||||
|
||||
std::string GLFragmentDecompilerThread::getFunction(FUNCTION f)
|
||||
{
|
||||
return gl::getFunctionImpl(f);
|
||||
return glsl::getFunctionImpl(f);
|
||||
}
|
||||
|
||||
std::string GLFragmentDecompilerThread::saturate(const std::string & code)
|
||||
@@ -173,11 +173,6 @@ namespace
|
||||
case rsx::texture_dimension_extended::texture_dimension_3d:
|
||||
case rsx::texture_dimension_extended::texture_dimension_cubemap: vec_type = "vec3";
|
||||
}
|
||||
|
||||
if (prog.unnormalized_coords & (1 << index))
|
||||
OS << "\t" << vec_type << " tex" << index << "_coord_scale = texture_parameters[" << index << "].xy / textureSize(tex" << index << ", 0);\n";
|
||||
else
|
||||
OS << "\t" << vec_type << " tex" << index << "_coord_scale = " << vec_type << "(1.);\n";
|
||||
}
|
||||
|
||||
std::string insert_texture_fetch(const RSXFragmentProgram& prog, int index)
|
||||
|
||||
+386
-284
@@ -24,14 +24,14 @@ namespace
|
||||
|
||||
GLGSRender::GLGSRender() : GSRender()
|
||||
{
|
||||
m_shaders_cache.reset(new gl::shader_cache(m_prog_buffer, "opengl", "v1"));
|
||||
m_shaders_cache.reset(new gl::shader_cache(m_prog_buffer, "opengl", "v1.1"));
|
||||
|
||||
if (g_cfg.video.disable_vertex_cache)
|
||||
m_vertex_cache.reset(new gl::null_vertex_cache());
|
||||
else
|
||||
m_vertex_cache.reset(new gl::weak_vertex_cache());
|
||||
|
||||
supports_multidraw = true;
|
||||
supports_multidraw = !g_cfg.video.strict_rendering_mode;
|
||||
}
|
||||
|
||||
extern CellGcmContextData current_context;
|
||||
@@ -51,7 +51,7 @@ namespace
|
||||
case rsx::comparison_function::greater_or_equal: return GL_GEQUAL;
|
||||
case rsx::comparison_function::always: return GL_ALWAYS;
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unsupported comparison op 0x%X" HERE, (u32)op);;
|
||||
}
|
||||
|
||||
GLenum stencil_op(rsx::stencil_op op)
|
||||
@@ -67,7 +67,7 @@ namespace
|
||||
case rsx::stencil_op::incr_wrap: return GL_INCR_WRAP;
|
||||
case rsx::stencil_op::decr_wrap: return GL_DECR_WRAP;
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unsupported stencil op 0x%X" HERE, (u32)op);
|
||||
}
|
||||
|
||||
GLenum blend_equation(rsx::blend_equation op)
|
||||
@@ -75,16 +75,20 @@ namespace
|
||||
switch (op)
|
||||
{
|
||||
// Note : maybe add is signed on gl
|
||||
case rsx::blend_equation::add_signed:
|
||||
LOG_TRACE(RSX, "blend equation add_signed used. Emulating using FUNC_ADD");
|
||||
case rsx::blend_equation::add: return GL_FUNC_ADD;
|
||||
case rsx::blend_equation::min: return GL_MIN;
|
||||
case rsx::blend_equation::max: return GL_MAX;
|
||||
case rsx::blend_equation::substract: return GL_FUNC_SUBTRACT;
|
||||
case rsx::blend_equation::reverse_substract_signed:
|
||||
LOG_TRACE(RSX, "blend equation reverse_subtract_signed used. Emulating using FUNC_REVERSE_SUBTRACT");
|
||||
case rsx::blend_equation::reverse_substract: return GL_FUNC_REVERSE_SUBTRACT;
|
||||
case rsx::blend_equation::reverse_substract_signed: throw "unsupported";
|
||||
case rsx::blend_equation::add_signed: throw "unsupported";
|
||||
case rsx::blend_equation::reverse_add_signed: throw "unsupported";
|
||||
case rsx::blend_equation::reverse_add_signed:
|
||||
default:
|
||||
LOG_ERROR(RSX, "Blend equation 0x%X is unimplemented!", (u32)op);
|
||||
return GL_FUNC_ADD;
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
GLenum blend_factor(rsx::blend_factor op)
|
||||
@@ -107,7 +111,7 @@ namespace
|
||||
case rsx::blend_factor::constant_alpha: return GL_CONSTANT_ALPHA;
|
||||
case rsx::blend_factor::one_minus_constant_alpha: return GL_ONE_MINUS_CONSTANT_ALPHA;
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unsupported blend factor 0x%X" HERE, (u32)op);
|
||||
}
|
||||
|
||||
GLenum logic_op(rsx::logic_op op)
|
||||
@@ -131,7 +135,7 @@ namespace
|
||||
case rsx::logic_op::logic_nand: return GL_NAND;
|
||||
case rsx::logic_op::logic_set: return GL_SET;
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unsupported logic op 0x%X" HERE, (u32)op);
|
||||
}
|
||||
|
||||
GLenum front_face(rsx::front_face op)
|
||||
@@ -143,7 +147,7 @@ namespace
|
||||
case rsx::front_face::cw: return (invert ? GL_CCW : GL_CW);
|
||||
case rsx::front_face::ccw: return (invert ? GL_CW : GL_CCW);
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unsupported front face 0x%X" HERE, (u32)op);
|
||||
}
|
||||
|
||||
GLenum cull_face(rsx::cull_face op)
|
||||
@@ -156,7 +160,7 @@ namespace
|
||||
case rsx::cull_face::back: return (invert ? GL_FRONT : GL_BACK);
|
||||
case rsx::cull_face::front_and_back: return GL_FRONT_AND_BACK;
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unsupported cull face 0x%X" HERE, (u32)op);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,141 +175,13 @@ void GLGSRender::begin()
|
||||
return;
|
||||
|
||||
init_buffers();
|
||||
|
||||
if (!framebuffer_status_valid)
|
||||
return;
|
||||
|
||||
std::chrono::time_point<steady_clock> then = steady_clock::now();
|
||||
|
||||
bool color_mask_b = rsx::method_registers.color_mask_b();
|
||||
bool color_mask_g = rsx::method_registers.color_mask_g();
|
||||
bool color_mask_r = rsx::method_registers.color_mask_r();
|
||||
bool color_mask_a = rsx::method_registers.color_mask_a();
|
||||
|
||||
gl_state.color_mask(color_mask_r, color_mask_g, color_mask_b, color_mask_a);
|
||||
gl_state.depth_mask(rsx::method_registers.depth_write_enabled());
|
||||
gl_state.stencil_mask(rsx::method_registers.stencil_mask());
|
||||
|
||||
if (gl_state.enable(rsx::method_registers.depth_test_enabled(), GL_DEPTH_TEST))
|
||||
{
|
||||
gl_state.depth_func(comparison_op(rsx::method_registers.depth_func()));
|
||||
|
||||
float range_near = rsx::method_registers.clip_min();
|
||||
float range_far = rsx::method_registers.clip_max();
|
||||
|
||||
//Workaround to preserve depth precision but respect z direction
|
||||
//Ni no Kuni sets a very restricted z range (0.9x - 1.) and depth reads / tests are broken
|
||||
if (range_near <= range_far)
|
||||
gl_state.depth_range(0.f, 1.f);
|
||||
else
|
||||
gl_state.depth_range(1.f, 0.f);
|
||||
}
|
||||
|
||||
if (glDepthBoundsEXT && (gl_state.enable(rsx::method_registers.depth_bounds_test_enabled(), GL_DEPTH_BOUNDS_TEST_EXT)))
|
||||
{
|
||||
gl_state.depth_bounds(rsx::method_registers.depth_bounds_min(), rsx::method_registers.depth_bounds_max());
|
||||
}
|
||||
|
||||
gl_state.enable(rsx::method_registers.dither_enabled(), GL_DITHER);
|
||||
|
||||
if (gl_state.enable(rsx::method_registers.blend_enabled(), GL_BLEND))
|
||||
{
|
||||
glBlendFuncSeparate(blend_factor(rsx::method_registers.blend_func_sfactor_rgb()),
|
||||
blend_factor(rsx::method_registers.blend_func_dfactor_rgb()),
|
||||
blend_factor(rsx::method_registers.blend_func_sfactor_a()),
|
||||
blend_factor(rsx::method_registers.blend_func_dfactor_a()));
|
||||
|
||||
auto blend_colors = rsx::get_constant_blend_colors();
|
||||
glBlendColor(blend_colors[0], blend_colors[1], blend_colors[2], blend_colors[3]);
|
||||
|
||||
glBlendEquationSeparate(blend_equation(rsx::method_registers.blend_equation_rgb()),
|
||||
blend_equation(rsx::method_registers.blend_equation_a()));
|
||||
}
|
||||
|
||||
if (gl_state.enable(rsx::method_registers.stencil_test_enabled(), GL_STENCIL_TEST))
|
||||
{
|
||||
glStencilFunc(comparison_op(rsx::method_registers.stencil_func()),
|
||||
rsx::method_registers.stencil_func_ref(),
|
||||
rsx::method_registers.stencil_func_mask());
|
||||
|
||||
glStencilOp(stencil_op(rsx::method_registers.stencil_op_fail()), stencil_op(rsx::method_registers.stencil_op_zfail()),
|
||||
stencil_op(rsx::method_registers.stencil_op_zpass()));
|
||||
|
||||
if (rsx::method_registers.two_sided_stencil_test_enabled())
|
||||
{
|
||||
glStencilMaskSeparate(GL_BACK, rsx::method_registers.back_stencil_mask());
|
||||
|
||||
glStencilFuncSeparate(GL_BACK, comparison_op(rsx::method_registers.back_stencil_func()),
|
||||
rsx::method_registers.back_stencil_func_ref(), rsx::method_registers.back_stencil_func_mask());
|
||||
|
||||
glStencilOpSeparate(GL_BACK, stencil_op(rsx::method_registers.back_stencil_op_fail()),
|
||||
stencil_op(rsx::method_registers.back_stencil_op_zfail()), stencil_op(rsx::method_registers.back_stencil_op_zpass()));
|
||||
}
|
||||
}
|
||||
|
||||
gl_state.enablei(rsx::method_registers.blend_enabled_surface_1(), GL_BLEND, 1);
|
||||
gl_state.enablei(rsx::method_registers.blend_enabled_surface_2(), GL_BLEND, 2);
|
||||
gl_state.enablei(rsx::method_registers.blend_enabled_surface_3(), GL_BLEND, 3);
|
||||
|
||||
if (gl_state.enable(rsx::method_registers.logic_op_enabled(), GL_COLOR_LOGIC_OP))
|
||||
{
|
||||
gl_state.logic_op(logic_op(rsx::method_registers.logic_operation()));
|
||||
}
|
||||
|
||||
gl_state.line_width(rsx::method_registers.line_width());
|
||||
gl_state.enable(rsx::method_registers.line_smooth_enabled(), GL_LINE_SMOOTH);
|
||||
|
||||
gl_state.enable(rsx::method_registers.poly_offset_point_enabled(), GL_POLYGON_OFFSET_POINT);
|
||||
gl_state.enable(rsx::method_registers.poly_offset_line_enabled(), GL_POLYGON_OFFSET_LINE);
|
||||
gl_state.enable(rsx::method_registers.poly_offset_fill_enabled(), GL_POLYGON_OFFSET_FILL);
|
||||
|
||||
//offset_bias is the constant factor, multiplied by the implementation factor R
|
||||
//offst_scale is the slope factor, multiplied by the triangle slope factor M
|
||||
gl_state.polygon_offset(rsx::method_registers.poly_offset_scale(), rsx::method_registers.poly_offset_bias());
|
||||
|
||||
if (gl_state.enable(rsx::method_registers.cull_face_enabled(), GL_CULL_FACE))
|
||||
{
|
||||
gl_state.cull_face(cull_face(rsx::method_registers.cull_face_mode()));
|
||||
}
|
||||
|
||||
gl_state.front_face(front_face(rsx::method_registers.front_face_mode()));
|
||||
|
||||
//TODO
|
||||
//NV4097_SET_ANISO_SPREAD
|
||||
//NV4097_SET_SPECULAR_ENABLE
|
||||
//NV4097_SET_TWO_SIDE_LIGHT_EN
|
||||
//NV4097_SET_FLAT_SHADE_OP
|
||||
//NV4097_SET_EDGE_FLAG
|
||||
|
||||
|
||||
|
||||
//NV4097_SET_COLOR_KEY_COLOR
|
||||
//NV4097_SET_SHADER_CONTROL
|
||||
//NV4097_SET_ZMIN_MAX_CONTROL
|
||||
//NV4097_SET_ANTI_ALIASING_CONTROL
|
||||
//NV4097_SET_CLIP_ID_TEST_ENABLE
|
||||
|
||||
std::chrono::time_point<steady_clock> now = steady_clock::now();
|
||||
m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
GLenum get_gl_target_for_texture(const rsx::fragment_texture& tex)
|
||||
GLenum get_gl_target_for_texture(const rsx::texture_dimension_extended type)
|
||||
{
|
||||
switch (tex.get_extended_texture_dimension())
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d: return GL_TEXTURE_1D;
|
||||
case rsx::texture_dimension_extended::texture_dimension_2d: return GL_TEXTURE_2D;
|
||||
case rsx::texture_dimension_extended::texture_dimension_cubemap: return GL_TEXTURE_CUBE_MAP;
|
||||
case rsx::texture_dimension_extended::texture_dimension_3d: return GL_TEXTURE_3D;
|
||||
}
|
||||
fmt::throw_exception("Unknown texture target" HERE);
|
||||
}
|
||||
|
||||
GLenum get_gl_target_for_texture(const rsx::vertex_texture& tex)
|
||||
{
|
||||
switch (tex.get_extended_texture_dimension())
|
||||
switch (type)
|
||||
{
|
||||
case rsx::texture_dimension_extended::texture_dimension_1d: return GL_TEXTURE_1D;
|
||||
case rsx::texture_dimension_extended::texture_dimension_2d: return GL_TEXTURE_2D;
|
||||
@@ -318,12 +194,17 @@ namespace
|
||||
|
||||
void GLGSRender::end()
|
||||
{
|
||||
std::chrono::time_point<steady_clock> state_check_start = steady_clock::now();
|
||||
|
||||
if (skip_frame || !framebuffer_status_valid || (conditional_render_enabled && conditional_render_test_failed) || !check_program_state())
|
||||
{
|
||||
rsx::thread::end();
|
||||
return;
|
||||
}
|
||||
|
||||
std::chrono::time_point<steady_clock> state_check_end = steady_clock::now();
|
||||
m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(state_check_end - state_check_start).count();
|
||||
|
||||
if (manually_flush_ring_buffers)
|
||||
{
|
||||
//Use approximations to reseve space. This path is mostly for debug purposes anyway
|
||||
@@ -342,6 +223,73 @@ void GLGSRender::end()
|
||||
std::optional<std::tuple<GLenum, u32> > indexed_draw_info;
|
||||
std::tie(vertex_draw_count, actual_vertex_count, vertex_base, indexed_draw_info) = set_vertex_buffer();
|
||||
|
||||
//Load textures
|
||||
{
|
||||
std::chrono::time_point<steady_clock> textures_start = steady_clock::now();
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_sampler_mutex);
|
||||
void* unused = nullptr;
|
||||
bool update_framebuffer_sourced = false;
|
||||
|
||||
if (surface_store_tag != m_rtts.cache_tag)
|
||||
{
|
||||
update_framebuffer_sourced = true;
|
||||
surface_store_tag = m_rtts.cache_tag;
|
||||
}
|
||||
|
||||
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
|
||||
{
|
||||
if (!fs_sampler_state[i])
|
||||
fs_sampler_state[i] = std::make_unique<gl::texture_cache::sampled_image_descriptor>();
|
||||
|
||||
if (m_samplers_dirty || m_textures_dirty[i] ||
|
||||
(update_framebuffer_sourced && fs_sampler_state[i]->upload_context == rsx::texture_upload_context::framebuffer_storage))
|
||||
{
|
||||
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
|
||||
|
||||
if (rsx::method_registers.fragment_textures[i].enabled())
|
||||
{
|
||||
*sampler_state = m_gl_texture_cache.upload_texture(unused, rsx::method_registers.fragment_textures[i], m_rtts);
|
||||
|
||||
if (m_textures_dirty[i])
|
||||
m_gl_sampler_states[i].apply(rsx::method_registers.fragment_textures[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
*sampler_state = {};
|
||||
}
|
||||
|
||||
m_textures_dirty[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
|
||||
{
|
||||
if (!vs_sampler_state[i])
|
||||
vs_sampler_state[i] = std::make_unique<gl::texture_cache::sampled_image_descriptor>();
|
||||
|
||||
if (m_samplers_dirty || m_vertex_textures_dirty[i] ||
|
||||
(update_framebuffer_sourced && vs_sampler_state[i]->upload_context == rsx::texture_upload_context::framebuffer_storage))
|
||||
{
|
||||
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(vs_sampler_state[i].get());
|
||||
|
||||
if (rsx::method_registers.vertex_textures[i].enabled())
|
||||
{
|
||||
*sampler_state = m_gl_texture_cache.upload_texture(unused, rsx::method_registers.vertex_textures[i], m_rtts);
|
||||
}
|
||||
else
|
||||
*sampler_state = {};
|
||||
|
||||
m_vertex_textures_dirty[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
m_samplers_dirty.store(false);
|
||||
|
||||
std::chrono::time_point<steady_clock> textures_end = steady_clock::now();
|
||||
m_textures_upload_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(textures_end - textures_start).count();
|
||||
}
|
||||
|
||||
std::chrono::time_point<steady_clock> program_start = steady_clock::now();
|
||||
//Load program here since it is dependent on vertex state
|
||||
|
||||
@@ -361,20 +309,102 @@ void GLGSRender::end()
|
||||
//glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
|
||||
}
|
||||
|
||||
//Bind textures and resolve external copy operations
|
||||
std::chrono::time_point<steady_clock> textures_start = steady_clock::now();
|
||||
int unused_location;
|
||||
|
||||
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
|
||||
{
|
||||
if (m_program->uniforms.has_location("tex" + std::to_string(i), &unused_location))
|
||||
{
|
||||
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
|
||||
|
||||
if (sampler_state->flag)
|
||||
continue;
|
||||
|
||||
sampler_state->flag = true;
|
||||
auto &tex = rsx::method_registers.fragment_textures[i];
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
|
||||
if (tex.enabled())
|
||||
{
|
||||
GLenum target = get_gl_target_for_texture(sampler_state->image_type);
|
||||
if (sampler_state->image_handle)
|
||||
{
|
||||
glBindTexture(target, sampler_state->image_handle);
|
||||
}
|
||||
else if (sampler_state->external_subresource_desc.external_handle)
|
||||
{
|
||||
void *unused = nullptr;
|
||||
glBindTexture(target, m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc));
|
||||
sampler_state->flag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(target, GL_NONE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, GL_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
|
||||
{
|
||||
if (m_program->uniforms.has_location("vtex" + std::to_string(i), &unused_location))
|
||||
{
|
||||
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(vs_sampler_state[i].get());
|
||||
|
||||
if (sampler_state->flag)
|
||||
continue;
|
||||
|
||||
sampler_state->flag = true;
|
||||
glActiveTexture(GL_TEXTURE0 + rsx::limits::fragment_textures_count + i);
|
||||
|
||||
if (sampler_state->image_handle)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, sampler_state->image_handle);
|
||||
}
|
||||
else if (sampler_state->external_subresource_desc.external_handle)
|
||||
{
|
||||
void *unused = nullptr;
|
||||
glBindTexture(GL_TEXTURE_2D, m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc));
|
||||
sampler_state->flag = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, GL_NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::chrono::time_point<steady_clock> textures_end = steady_clock::now();
|
||||
m_textures_upload_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(textures_end - textures_start).count();
|
||||
|
||||
update_draw_state();
|
||||
|
||||
//Check if depth buffer is bound and valid
|
||||
//If ds is not initialized clear it; it seems new depth textures should have depth cleared
|
||||
auto copy_rtt_contents = [](gl::render_target *surface)
|
||||
{
|
||||
//Copy data from old contents onto this one
|
||||
//1. Clip a rectangular region defning the data
|
||||
//2. Perform a GPU blit
|
||||
u16 parent_w = surface->old_contents->width();
|
||||
u16 parent_h = surface->old_contents->height();
|
||||
u16 copy_w, copy_h;
|
||||
if (surface->get_compatible_internal_format() == surface->old_contents->get_compatible_internal_format())
|
||||
{
|
||||
//Copy data from old contents onto this one
|
||||
//1. Clip a rectangular region defning the data
|
||||
//2. Perform a GPU blit
|
||||
u16 parent_w = surface->old_contents->width();
|
||||
u16 parent_h = surface->old_contents->height();
|
||||
u16 copy_w, copy_h;
|
||||
|
||||
std::tie(std::ignore, std::ignore, copy_w, copy_h) = rsx::clip_region<u16>(parent_w, parent_h, 0, 0, surface->width(), surface->height(), true);
|
||||
glCopyImageSubData(surface->old_contents->id(), GL_TEXTURE_2D, 0, 0, 0, 0, surface->id(), GL_TEXTURE_2D, 0, 0, 0, 0, copy_w, copy_h, 1);
|
||||
surface->set_cleared();
|
||||
}
|
||||
//TODO: download image contents and reupload them or do a memory cast to copy memory contents if not compatible
|
||||
|
||||
std::tie(std::ignore, std::ignore, copy_w, copy_h) = rsx::clip_region<u16>(parent_w, parent_h, 0, 0, surface->width(), surface->height(), true);
|
||||
glCopyImageSubData(surface->old_contents->id(), GL_TEXTURE_2D, 0, 0, 0, 0, surface->id(), GL_TEXTURE_2D, 0, 0, 0, 0, copy_w, copy_h, 1);
|
||||
surface->set_cleared();
|
||||
surface->old_contents = nullptr;
|
||||
};
|
||||
|
||||
@@ -452,43 +482,6 @@ void GLGSRender::end()
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
std::chrono::time_point<steady_clock> textures_start = steady_clock::now();
|
||||
|
||||
//Setup textures
|
||||
//Setting unused texture to 0 is not needed, but makes program validation happy if we choose to enforce it
|
||||
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
|
||||
{
|
||||
int location;
|
||||
if (rsx::method_registers.fragment_textures[i].enabled() && m_program->uniforms.has_location("tex" + std::to_string(i), &location))
|
||||
{
|
||||
m_gl_texture_cache.upload_and_bind_texture(i, get_gl_target_for_texture(rsx::method_registers.fragment_textures[i]), rsx::method_registers.fragment_textures[i], m_rtts);
|
||||
|
||||
if (m_textures_dirty[i])
|
||||
{
|
||||
m_gl_sampler_states[i].apply(rsx::method_registers.fragment_textures[i]);
|
||||
m_textures_dirty[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Vertex textures
|
||||
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
|
||||
{
|
||||
int texture_index = i + rsx::limits::fragment_textures_count;
|
||||
int location;
|
||||
|
||||
if (!rsx::method_registers.vertex_textures[i].enabled())
|
||||
continue;
|
||||
|
||||
if (m_program->uniforms.has_location("vtex" + std::to_string(i), &location))
|
||||
{
|
||||
m_gl_texture_cache.upload_and_bind_texture(texture_index, GL_TEXTURE_2D, rsx::method_registers.vertex_textures[i], m_rtts);
|
||||
}
|
||||
}
|
||||
|
||||
std::chrono::time_point<steady_clock> textures_end = steady_clock::now();
|
||||
m_textures_upload_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(textures_end - textures_start).count();
|
||||
|
||||
std::chrono::time_point<steady_clock> draw_start = steady_clock::now();
|
||||
|
||||
if (g_cfg.video.debug_output)
|
||||
@@ -497,14 +490,15 @@ void GLGSRender::end()
|
||||
}
|
||||
|
||||
const GLenum draw_mode = gl::draw_mode(rsx::method_registers.current_draw_clause.primitive);
|
||||
bool single_draw = rsx::method_registers.current_draw_clause.first_count_commands.size() <= 1 || rsx::method_registers.current_draw_clause.is_disjoint_primitive;
|
||||
bool single_draw = !supports_multidraw || (rsx::method_registers.current_draw_clause.first_count_commands.size() <= 1 || rsx::method_registers.current_draw_clause.is_disjoint_primitive);
|
||||
|
||||
if (indexed_draw_info)
|
||||
{
|
||||
const GLenum index_type = std::get<0>(indexed_draw_info.value());
|
||||
const u32 index_offset = std::get<1>(indexed_draw_info.value());
|
||||
const bool restarts_valid = gl::is_primitive_native(rsx::method_registers.current_draw_clause.primitive) && !rsx::method_registers.current_draw_clause.is_disjoint_primitive;
|
||||
|
||||
if (gl_state.enable(rsx::method_registers.restart_index_enabled(), GL_PRIMITIVE_RESTART))
|
||||
if (gl_state.enable(restarts_valid && rsx::method_registers.restart_index_enabled(), GL_PRIMITIVE_RESTART))
|
||||
{
|
||||
glPrimitiveRestartIndex((index_type == GL_UNSIGNED_SHORT)? 0xffff: 0xffffffff);
|
||||
}
|
||||
@@ -545,21 +539,32 @@ void GLGSRender::end()
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<GLint> firsts;
|
||||
std::vector<GLsizei> counts;
|
||||
const auto draw_count = rsx::method_registers.current_draw_clause.first_count_commands.size();
|
||||
|
||||
firsts.reserve(draw_count);
|
||||
counts.reserve(draw_count);
|
||||
|
||||
u32 base_index = rsx::method_registers.current_draw_clause.first_count_commands.front().first;
|
||||
for (const auto &range : rsx::method_registers.current_draw_clause.first_count_commands)
|
||||
if (gl::get_driver_caps().vendor_AMD == false)
|
||||
{
|
||||
firsts.push_back(range.first - base_index);
|
||||
counts.push_back(range.second);
|
||||
}
|
||||
std::vector<GLint> firsts;
|
||||
std::vector<GLsizei> counts;
|
||||
const auto draw_count = rsx::method_registers.current_draw_clause.first_count_commands.size();
|
||||
|
||||
glMultiDrawArrays(draw_mode, firsts.data(), counts.data(), (GLsizei)draw_count);
|
||||
firsts.reserve(draw_count);
|
||||
counts.reserve(draw_count);
|
||||
|
||||
for (const auto &range : rsx::method_registers.current_draw_clause.first_count_commands)
|
||||
{
|
||||
firsts.push_back(range.first - base_index);
|
||||
counts.push_back(range.second);
|
||||
}
|
||||
|
||||
glMultiDrawArrays(draw_mode, firsts.data(), counts.data(), (GLsizei)draw_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
//MultiDrawArrays is broken on some primitive types using AMD. One known type is GL_TRIANGLE_STRIP but there could be more
|
||||
for (const auto &range : rsx::method_registers.current_draw_clause.first_count_commands)
|
||||
{
|
||||
glDrawArrays(draw_mode, range.first - base_index, range.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,6 +619,9 @@ void GLGSRender::on_init_thread()
|
||||
{
|
||||
GSRender::on_init_thread();
|
||||
|
||||
m_frame->disable_wm_event_queue();
|
||||
m_frame->hide();
|
||||
|
||||
gl::init();
|
||||
|
||||
//Enable adaptive vsync if vsync is requested
|
||||
@@ -754,12 +762,13 @@ void GLGSRender::on_init_thread()
|
||||
m_thread_id = std::this_thread::get_id();
|
||||
|
||||
m_shaders_cache->load();
|
||||
|
||||
m_frame->enable_wm_event_queue();
|
||||
m_frame->show();
|
||||
}
|
||||
|
||||
void GLGSRender::on_exit()
|
||||
{
|
||||
glFinish();
|
||||
|
||||
m_prog_buffer.clear();
|
||||
|
||||
if (draw_fbo)
|
||||
@@ -827,13 +836,15 @@ void GLGSRender::on_exit()
|
||||
glDeleteQueries(1, &query.handle);
|
||||
}
|
||||
|
||||
return GSRender::on_exit();
|
||||
glFlush();
|
||||
glFinish();
|
||||
|
||||
GSRender::on_exit();
|
||||
}
|
||||
|
||||
void GLGSRender::clear_surface(u32 arg)
|
||||
{
|
||||
if (skip_frame || !framebuffer_status_valid) return;
|
||||
if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return;
|
||||
if ((arg & 0xf3) == 0) return;
|
||||
|
||||
GLbitfield mask = 0;
|
||||
@@ -925,49 +936,23 @@ bool GLGSRender::do_method(u32 cmd, u32 arg)
|
||||
|
||||
bool GLGSRender::check_program_state()
|
||||
{
|
||||
auto rtt_lookup_func = [this](u32 texaddr, rsx::fragment_texture &tex, bool is_depth) -> std::tuple<bool, u16>
|
||||
{
|
||||
gl::render_target *surface = nullptr;
|
||||
if (!is_depth)
|
||||
surface = m_rtts.get_texture_from_render_target_if_applicable(texaddr);
|
||||
else
|
||||
{
|
||||
surface = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr);
|
||||
|
||||
if (!surface && m_gl_texture_cache.is_depth_texture(texaddr, (u32)get_texture_size(tex)))
|
||||
return std::make_tuple(true, 0);
|
||||
}
|
||||
|
||||
if (!surface)
|
||||
{
|
||||
auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, 0, 0, tex.pitch());
|
||||
if (!rsc.surface || rsc.is_depth_surface != is_depth)
|
||||
return std::make_tuple(false, 0);
|
||||
|
||||
surface = rsc.surface;
|
||||
}
|
||||
|
||||
return std::make_tuple(true, surface->get_native_pitch());
|
||||
};
|
||||
|
||||
get_current_fragment_program(rtt_lookup_func);
|
||||
|
||||
if (current_fragment_program.valid == false)
|
||||
return false;
|
||||
|
||||
get_current_vertex_program();
|
||||
return true;
|
||||
return (rsx::method_registers.shader_program_address() != 0);
|
||||
}
|
||||
|
||||
void GLGSRender::load_program(u32 vertex_base, u32 vertex_count)
|
||||
{
|
||||
get_current_fragment_program(fs_sampler_state);
|
||||
verify(HERE), current_fragment_program.valid;
|
||||
|
||||
get_current_vertex_program();
|
||||
|
||||
auto &fragment_program = current_fragment_program;
|
||||
auto &vertex_program = current_vertex_program;
|
||||
|
||||
vertex_program.skip_vertex_input_check = true; //not needed for us since decoding is done server side
|
||||
fragment_program.unnormalized_coords = 0; //unused
|
||||
void* pipeline_properties = nullptr;
|
||||
|
||||
auto old_program = m_program;
|
||||
m_program = &m_prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, pipeline_properties);
|
||||
m_program->use();
|
||||
|
||||
@@ -1034,6 +1019,122 @@ void GLGSRender::load_program(u32 vertex_base, u32 vertex_count)
|
||||
m_transform_constants_dirty = false;
|
||||
}
|
||||
|
||||
void GLGSRender::update_draw_state()
|
||||
{
|
||||
std::chrono::time_point<steady_clock> then = steady_clock::now();
|
||||
|
||||
bool color_mask_b = rsx::method_registers.color_mask_b();
|
||||
bool color_mask_g = rsx::method_registers.color_mask_g();
|
||||
bool color_mask_r = rsx::method_registers.color_mask_r();
|
||||
bool color_mask_a = rsx::method_registers.color_mask_a();
|
||||
|
||||
gl_state.color_mask(color_mask_r, color_mask_g, color_mask_b, color_mask_a);
|
||||
gl_state.depth_mask(rsx::method_registers.depth_write_enabled());
|
||||
gl_state.stencil_mask(rsx::method_registers.stencil_mask());
|
||||
|
||||
if (gl_state.enable(rsx::method_registers.depth_test_enabled(), GL_DEPTH_TEST))
|
||||
{
|
||||
gl_state.depth_func(comparison_op(rsx::method_registers.depth_func()));
|
||||
|
||||
float range_near = rsx::method_registers.clip_min();
|
||||
float range_far = rsx::method_registers.clip_max();
|
||||
|
||||
//Workaround to preserve depth precision but respect z direction
|
||||
//Ni no Kuni sets a very restricted z range (0.9x - 1.) and depth reads / tests are broken
|
||||
if (range_near <= range_far)
|
||||
gl_state.depth_range(0.f, 1.f);
|
||||
else
|
||||
gl_state.depth_range(1.f, 0.f);
|
||||
}
|
||||
|
||||
if (glDepthBoundsEXT && (gl_state.enable(rsx::method_registers.depth_bounds_test_enabled(), GL_DEPTH_BOUNDS_TEST_EXT)))
|
||||
{
|
||||
gl_state.depth_bounds(rsx::method_registers.depth_bounds_min(), rsx::method_registers.depth_bounds_max());
|
||||
}
|
||||
|
||||
gl_state.enable(rsx::method_registers.dither_enabled(), GL_DITHER);
|
||||
|
||||
if (gl_state.enable(rsx::method_registers.blend_enabled(), GL_BLEND))
|
||||
{
|
||||
glBlendFuncSeparate(blend_factor(rsx::method_registers.blend_func_sfactor_rgb()),
|
||||
blend_factor(rsx::method_registers.blend_func_dfactor_rgb()),
|
||||
blend_factor(rsx::method_registers.blend_func_sfactor_a()),
|
||||
blend_factor(rsx::method_registers.blend_func_dfactor_a()));
|
||||
|
||||
auto blend_colors = rsx::get_constant_blend_colors();
|
||||
glBlendColor(blend_colors[0], blend_colors[1], blend_colors[2], blend_colors[3]);
|
||||
|
||||
glBlendEquationSeparate(blend_equation(rsx::method_registers.blend_equation_rgb()),
|
||||
blend_equation(rsx::method_registers.blend_equation_a()));
|
||||
}
|
||||
|
||||
if (gl_state.enable(rsx::method_registers.stencil_test_enabled(), GL_STENCIL_TEST))
|
||||
{
|
||||
glStencilFunc(comparison_op(rsx::method_registers.stencil_func()),
|
||||
rsx::method_registers.stencil_func_ref(),
|
||||
rsx::method_registers.stencil_func_mask());
|
||||
|
||||
glStencilOp(stencil_op(rsx::method_registers.stencil_op_fail()), stencil_op(rsx::method_registers.stencil_op_zfail()),
|
||||
stencil_op(rsx::method_registers.stencil_op_zpass()));
|
||||
|
||||
if (rsx::method_registers.two_sided_stencil_test_enabled())
|
||||
{
|
||||
glStencilMaskSeparate(GL_BACK, rsx::method_registers.back_stencil_mask());
|
||||
|
||||
glStencilFuncSeparate(GL_BACK, comparison_op(rsx::method_registers.back_stencil_func()),
|
||||
rsx::method_registers.back_stencil_func_ref(), rsx::method_registers.back_stencil_func_mask());
|
||||
|
||||
glStencilOpSeparate(GL_BACK, stencil_op(rsx::method_registers.back_stencil_op_fail()),
|
||||
stencil_op(rsx::method_registers.back_stencil_op_zfail()), stencil_op(rsx::method_registers.back_stencil_op_zpass()));
|
||||
}
|
||||
}
|
||||
|
||||
gl_state.enablei(rsx::method_registers.blend_enabled_surface_1(), GL_BLEND, 1);
|
||||
gl_state.enablei(rsx::method_registers.blend_enabled_surface_2(), GL_BLEND, 2);
|
||||
gl_state.enablei(rsx::method_registers.blend_enabled_surface_3(), GL_BLEND, 3);
|
||||
|
||||
if (gl_state.enable(rsx::method_registers.logic_op_enabled(), GL_COLOR_LOGIC_OP))
|
||||
{
|
||||
gl_state.logic_op(logic_op(rsx::method_registers.logic_operation()));
|
||||
}
|
||||
|
||||
gl_state.line_width(rsx::method_registers.line_width());
|
||||
gl_state.enable(rsx::method_registers.line_smooth_enabled(), GL_LINE_SMOOTH);
|
||||
|
||||
gl_state.enable(rsx::method_registers.poly_offset_point_enabled(), GL_POLYGON_OFFSET_POINT);
|
||||
gl_state.enable(rsx::method_registers.poly_offset_line_enabled(), GL_POLYGON_OFFSET_LINE);
|
||||
gl_state.enable(rsx::method_registers.poly_offset_fill_enabled(), GL_POLYGON_OFFSET_FILL);
|
||||
|
||||
//offset_bias is the constant factor, multiplied by the implementation factor R
|
||||
//offst_scale is the slope factor, multiplied by the triangle slope factor M
|
||||
gl_state.polygon_offset(rsx::method_registers.poly_offset_scale(), rsx::method_registers.poly_offset_bias());
|
||||
|
||||
if (gl_state.enable(rsx::method_registers.cull_face_enabled(), GL_CULL_FACE))
|
||||
{
|
||||
gl_state.cull_face(cull_face(rsx::method_registers.cull_face_mode()));
|
||||
}
|
||||
|
||||
gl_state.front_face(front_face(rsx::method_registers.front_face_mode()));
|
||||
|
||||
//TODO
|
||||
//NV4097_SET_ANISO_SPREAD
|
||||
//NV4097_SET_SPECULAR_ENABLE
|
||||
//NV4097_SET_TWO_SIDE_LIGHT_EN
|
||||
//NV4097_SET_FLAT_SHADE_OP
|
||||
//NV4097_SET_EDGE_FLAG
|
||||
|
||||
|
||||
|
||||
//NV4097_SET_COLOR_KEY_COLOR
|
||||
//NV4097_SET_SHADER_CONTROL
|
||||
//NV4097_SET_ZMIN_MAX_CONTROL
|
||||
//NV4097_SET_ANTI_ALIASING_CONTROL
|
||||
//NV4097_SET_CLIP_ID_TEST_ENABLE
|
||||
|
||||
std::chrono::time_point<steady_clock> now = steady_clock::now();
|
||||
m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
|
||||
}
|
||||
|
||||
void GLGSRender::flip(int buffer)
|
||||
{
|
||||
if (skip_frame)
|
||||
@@ -1156,7 +1257,9 @@ void GLGSRender::flip(int buffer)
|
||||
m_text_printer.print_text(0, 72, m_frame->client_width(), m_frame->client_height(), "draw call execution: " + std::to_string(m_draw_time) + "us");
|
||||
|
||||
auto num_dirty_textures = m_gl_texture_cache.get_unreleased_textures_count();
|
||||
auto texture_memory_size = m_gl_texture_cache.get_texture_memory_in_use() / (1024 * 1024);
|
||||
m_text_printer.print_text(0, 108, m_frame->client_width(), m_frame->client_height(), "Unreleased textures: " + std::to_string(num_dirty_textures));
|
||||
m_text_printer.print_text(0, 126, m_frame->client_width(), m_frame->client_height(), "Texture memory: " + std::to_string(texture_memory_size) + "M");
|
||||
}
|
||||
|
||||
m_frame->flip(m_context);
|
||||
@@ -1169,10 +1272,6 @@ void GLGSRender::flip(int buffer)
|
||||
tex->remove();
|
||||
|
||||
m_rtts.invalidated_resources.clear();
|
||||
|
||||
if (g_cfg.video.invalidate_surface_cache_every_frame)
|
||||
m_rtts.invalidate_surface_cache_data(nullptr);
|
||||
|
||||
m_vertex_cache->purge();
|
||||
|
||||
//If we are skipping the next frame, do not reset perf counters
|
||||
@@ -1195,38 +1294,45 @@ u64 GLGSRender::timestamp() const
|
||||
|
||||
bool GLGSRender::on_access_violation(u32 address, bool is_writing)
|
||||
{
|
||||
if (is_writing)
|
||||
return m_gl_texture_cache.invalidate_address(address);
|
||||
else
|
||||
bool can_flush = (std::this_thread::get_id() == m_thread_id);
|
||||
auto result = m_gl_texture_cache.invalidate_address(address, is_writing, can_flush);
|
||||
|
||||
if (!result.violation_handled)
|
||||
return false;
|
||||
|
||||
{
|
||||
if (std::this_thread::get_id() != m_thread_id)
|
||||
{
|
||||
bool flushable;
|
||||
gl::cached_texture_section* section_to_post;
|
||||
|
||||
std::tie(flushable, section_to_post) = m_gl_texture_cache.address_is_flushable(address);
|
||||
if (!flushable) return false;
|
||||
|
||||
work_item &task = post_flush_request(address, section_to_post);
|
||||
|
||||
vm::temporary_unlock();
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(task.guard_mutex);
|
||||
task.cv.wait(lock, [&task] { return task.processed; });
|
||||
}
|
||||
|
||||
task.received = true;
|
||||
return task.result;
|
||||
}
|
||||
|
||||
return m_gl_texture_cache.flush_address(address);
|
||||
std::lock_guard<std::mutex> lock(m_sampler_mutex);
|
||||
m_samplers_dirty.store(true);
|
||||
}
|
||||
|
||||
if (result.num_flushable > 0)
|
||||
{
|
||||
work_item &task = post_flush_request(address, result);
|
||||
|
||||
vm::temporary_unlock();
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(task.guard_mutex);
|
||||
task.cv.wait(lock, [&task] { return task.processed; });
|
||||
}
|
||||
|
||||
task.received = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLGSRender::on_notify_memory_unmapped(u32 address_base, u32 size)
|
||||
{
|
||||
if (m_gl_texture_cache.invalidate_range(address_base, size, false))
|
||||
//Discard all memory in that range without bothering with writeback (Force it for strict?)
|
||||
if (m_gl_texture_cache.invalidate_range(address_base, size, true, true, false).violation_handled)
|
||||
{
|
||||
m_gl_texture_cache.purge_dirty();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_sampler_mutex);
|
||||
m_samplers_dirty.store(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLGSRender::do_local_task()
|
||||
@@ -1242,20 +1348,7 @@ void GLGSRender::do_local_task()
|
||||
if (q.processed) continue;
|
||||
|
||||
std::unique_lock<std::mutex> lock(q.guard_mutex);
|
||||
|
||||
//Check if the suggested section is valid
|
||||
if (!q.section_to_flush->is_flushed())
|
||||
{
|
||||
m_gl_texture_cache.flush_address(q.address_to_flush);
|
||||
q.result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Another thread has unlocked this memory region already
|
||||
//Return success
|
||||
q.result = true;
|
||||
}
|
||||
|
||||
q.result = m_gl_texture_cache.flush_all(q.section_data);
|
||||
q.processed = true;
|
||||
|
||||
//Notify thread waiting on this
|
||||
@@ -1264,14 +1357,14 @@ void GLGSRender::do_local_task()
|
||||
}
|
||||
}
|
||||
|
||||
work_item& GLGSRender::post_flush_request(u32 address, gl::cached_texture_section *section)
|
||||
work_item& GLGSRender::post_flush_request(u32 address, gl::texture_cache::thrashed_set& flush_data)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(queue_guard);
|
||||
|
||||
work_queue.emplace_back();
|
||||
work_item &result = work_queue.back();
|
||||
result.address_to_flush = address;
|
||||
result.section_to_flush = section;
|
||||
result.section_data = std::move(flush_data);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1286,9 +1379,18 @@ void GLGSRender::synchronize_buffers()
|
||||
|
||||
bool GLGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate)
|
||||
{
|
||||
m_samplers_dirty.store(true);
|
||||
return m_gl_texture_cache.blit(src, dst, interpolate, m_rtts);
|
||||
}
|
||||
|
||||
void GLGSRender::notify_tile_unbound(u32 tile)
|
||||
{
|
||||
//TODO: Handle texture writeback
|
||||
//u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location);
|
||||
//on_notify_memory_unmapped(addr, tiles[tile].size);
|
||||
//m_rtts.invalidate_surface_address(addr, false);
|
||||
}
|
||||
|
||||
void GLGSRender::check_zcull_status(bool framebuffer_swap, bool force_read)
|
||||
{
|
||||
if (g_cfg.video.disable_zcull_queries)
|
||||
|
||||
@@ -28,7 +28,7 @@ struct work_item
|
||||
std::mutex guard_mutex;
|
||||
|
||||
u32 address_to_flush = 0;
|
||||
gl::cached_texture_section *section_to_flush = nullptr;
|
||||
gl::texture_cache::thrashed_set section_data;
|
||||
|
||||
volatile bool processed = false;
|
||||
volatile bool result = false;
|
||||
@@ -310,33 +310,6 @@ struct driver_state
|
||||
}
|
||||
};
|
||||
|
||||
struct sw_ring_buffer
|
||||
{
|
||||
std::vector<u8> data;
|
||||
u32 ring_pos = 0;
|
||||
u32 ring_length = 0;
|
||||
|
||||
sw_ring_buffer(u32 size)
|
||||
{
|
||||
data.resize(size);
|
||||
ring_length = size;
|
||||
}
|
||||
|
||||
void* get(u32 dwords)
|
||||
{
|
||||
const u32 required = (dwords << 2);
|
||||
if ((ring_pos + required) > ring_length)
|
||||
{
|
||||
ring_pos = 0;
|
||||
return data.data();
|
||||
}
|
||||
|
||||
void *result = data.data() + ring_pos;
|
||||
ring_pos += required;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
class GLGSRender : public GSRender
|
||||
{
|
||||
private:
|
||||
@@ -405,6 +378,12 @@ private:
|
||||
const u32 occlusion_query_count = 128;
|
||||
std::array<occlusion_query_info, 128> occlusion_query_data = {};
|
||||
|
||||
std::mutex m_sampler_mutex;
|
||||
u64 surface_store_tag = 0;
|
||||
std::atomic_bool m_samplers_dirty = {true};
|
||||
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count> fs_sampler_state = {};
|
||||
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count> vs_sampler_state = {};
|
||||
|
||||
public:
|
||||
GLGSRender();
|
||||
|
||||
@@ -422,13 +401,15 @@ private:
|
||||
bool check_program_state();
|
||||
void load_program(u32 vertex_base, u32 vertex_count);
|
||||
|
||||
void update_draw_state();
|
||||
|
||||
public:
|
||||
void read_buffers();
|
||||
void write_buffers();
|
||||
void set_viewport();
|
||||
|
||||
void synchronize_buffers();
|
||||
work_item& post_flush_request(u32 address, gl::cached_texture_section *section);
|
||||
work_item& post_flush_request(u32 address, gl::texture_cache::thrashed_set& flush_data);
|
||||
|
||||
bool scaled_image_from_memory(rsx::blit_src_info& src_info, rsx::blit_dst_info& dst_info, bool interpolate) override;
|
||||
|
||||
@@ -453,6 +434,7 @@ protected:
|
||||
|
||||
bool on_access_violation(u32 address, bool is_writing) override;
|
||||
void on_notify_memory_unmapped(u32 address_base, u32 size) override;
|
||||
void notify_tile_unbound(u32 tile) override;
|
||||
|
||||
virtual std::array<std::vector<gsl::byte>, 4> copy_render_targets_to_memory() override;
|
||||
virtual std::array<std::vector<gsl::byte>, 2> copy_depth_stencil_buffer_to_memory() override;
|
||||
|
||||
@@ -84,6 +84,7 @@ namespace gl
|
||||
bool NV_texture_barrier_supported = false;
|
||||
bool initialized = false;
|
||||
bool vendor_INTEL = false;
|
||||
bool vendor_AMD = false;
|
||||
|
||||
void initialize()
|
||||
{
|
||||
@@ -192,6 +193,12 @@ namespace gl
|
||||
if (!EXT_dsa_supported && glGetTextureImageEXT && glTextureBufferRangeEXT)
|
||||
EXT_dsa_supported = true;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
else if (vendor_string.find("amd") != std::string::npos || vendor_string.find("ati") != std::string::npos)
|
||||
{
|
||||
vendor_AMD = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@@ -165,21 +165,36 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
|
||||
const u16 clip_horizontal = rsx::method_registers.surface_clip_width();
|
||||
const u16 clip_vertical = rsx::method_registers.surface_clip_height();
|
||||
const u16 clip_x = rsx::method_registers.surface_clip_origin_x();
|
||||
const u16 clip_y = rsx::method_registers.surface_clip_origin_y();
|
||||
|
||||
framebuffer_status_valid = false;
|
||||
|
||||
if (clip_horizontal == 0 || clip_vertical == 0)
|
||||
{
|
||||
LOG_ERROR(RSX, "Invalid framebuffer setup, w=%d, h=%d", clip_horizontal, clip_vertical);
|
||||
framebuffer_status_valid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto surface_addresses = get_color_surface_addresses();
|
||||
const auto depth_address = get_zeta_surface_address();
|
||||
|
||||
for (const auto &addr: surface_addresses)
|
||||
{
|
||||
if (addr)
|
||||
{
|
||||
framebuffer_status_valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!framebuffer_status_valid && !depth_address)
|
||||
return;
|
||||
|
||||
const auto pitchs = get_pitchs();
|
||||
const auto surface_format = rsx::method_registers.surface_color();
|
||||
const auto depth_format = rsx::method_registers.surface_depth_fmt();
|
||||
|
||||
const auto surface_addresses = get_color_surface_addresses();
|
||||
const auto depth_address = get_zeta_surface_address();
|
||||
|
||||
m_rtts.prepare_render_target(nullptr, surface_format, depth_format, clip_horizontal, clip_vertical,
|
||||
rsx::method_registers.surface_color_target(),
|
||||
surface_addresses, depth_address);
|
||||
@@ -189,6 +204,11 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
bool old_format_found = false;
|
||||
gl::texture::format old_format;
|
||||
|
||||
const auto color_offsets = get_offsets();
|
||||
const auto color_locations = get_locations();
|
||||
const auto aa_mode = rsx::method_registers.surface_antialias();
|
||||
const auto bpp = get_format_block_size_in_bytes(surface_format);
|
||||
|
||||
for (int i = 0; i < rsx::limits::color_buffers_count; ++i)
|
||||
{
|
||||
if (surface_info[i].pitch && g_cfg.video.write_color_buffers)
|
||||
@@ -204,14 +224,15 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
|
||||
if (std::get<0>(m_rtts.m_bound_render_targets[i]))
|
||||
{
|
||||
__glcheck draw_fbo.color[i] = *std::get<1>(m_rtts.m_bound_render_targets[i]);
|
||||
auto rtt = std::get<1>(m_rtts.m_bound_render_targets[i]);
|
||||
draw_fbo.color[i] = *rtt;
|
||||
|
||||
std::get<1>(m_rtts.m_bound_render_targets[i])->set_rsx_pitch(pitchs[i]);
|
||||
rtt->set_rsx_pitch(pitchs[i]);
|
||||
surface_info[i] = { surface_addresses[i], pitchs[i], false, surface_format, depth_format, clip_horizontal, clip_vertical };
|
||||
|
||||
//Verify pitch given is correct if pitch <= 64 (especially 64)
|
||||
if (pitchs[i] <= 64)
|
||||
{
|
||||
{
|
||||
const u16 native_pitch = std::get<1>(m_rtts.m_bound_render_targets[i])->get_native_pitch();
|
||||
if (native_pitch > pitchs[i])
|
||||
{
|
||||
@@ -223,6 +244,14 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
surface_info[i].pitch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
rtt->tile = find_tile(color_offsets[i], color_locations[i]);
|
||||
rtt->aa_mode = aa_mode;
|
||||
rtt->set_raster_offset(clip_x, clip_y, bpp);
|
||||
m_gl_texture_cache.notify_surface_changed(surface_addresses[i]);
|
||||
|
||||
if (surface_info[i].pitch)
|
||||
m_gl_texture_cache.tag_framebuffer(surface_addresses[i] + rtt->raster_address_offset);
|
||||
}
|
||||
else
|
||||
surface_info[i] = {};
|
||||
@@ -230,10 +259,16 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
|
||||
if (std::get<0>(m_rtts.m_bound_depth_stencil))
|
||||
{
|
||||
auto ds = std::get<1>(m_rtts.m_bound_depth_stencil);
|
||||
u8 texel_size = 2;
|
||||
|
||||
if (depth_format == rsx::surface_depth_format::z24s8)
|
||||
__glcheck draw_fbo.depth_stencil = *std::get<1>(m_rtts.m_bound_depth_stencil);
|
||||
{
|
||||
draw_fbo.depth_stencil = *ds;
|
||||
texel_size = 4;
|
||||
}
|
||||
else
|
||||
__glcheck draw_fbo.depth = *std::get<1>(m_rtts.m_bound_depth_stencil);
|
||||
draw_fbo.depth = *ds;
|
||||
|
||||
const u32 depth_surface_pitch = rsx::method_registers.surface_z_pitch();
|
||||
std::get<1>(m_rtts.m_bound_depth_stencil)->set_rsx_pitch(rsx::method_registers.surface_z_pitch());
|
||||
@@ -253,6 +288,13 @@ void GLGSRender::init_buffers(bool skip_reading)
|
||||
depth_surface_info.pitch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ds->aa_mode = aa_mode;
|
||||
ds->set_raster_offset(clip_x, clip_y, texel_size);
|
||||
m_gl_texture_cache.notify_surface_changed(depth_address);
|
||||
|
||||
if (depth_surface_info.pitch)
|
||||
m_gl_texture_cache.tag_framebuffer(depth_address + ds->raster_address_offset);
|
||||
}
|
||||
else
|
||||
depth_surface_info = {};
|
||||
@@ -390,7 +432,7 @@ void GLGSRender::read_buffers()
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gl_texture_cache.invalidate_range(texaddr, range);
|
||||
m_gl_texture_cache.invalidate_range(texaddr, range, false, false, true);
|
||||
|
||||
std::unique_ptr<u8[]> buffer(new u8[pitch * height]);
|
||||
color_buffer.read(buffer.get(), width, height, pitch);
|
||||
|
||||
@@ -253,6 +253,10 @@ struct gl_render_target_traits
|
||||
static void invalidate_rtt_surface_contents(void *, gl::render_target *rtt, gl::render_target* /*old*/, bool forced) { if (forced) rtt->set_cleared(false); }
|
||||
static void invalidate_depth_surface_contents(void *, gl::render_target *ds, gl::render_target* /*old*/, bool) { ds->set_cleared(false); }
|
||||
|
||||
static
|
||||
void notify_surface_invalidated(const std::unique_ptr<gl::render_target>&)
|
||||
{}
|
||||
|
||||
static
|
||||
bool rtt_has_format_width_height(const std::unique_ptr<gl::render_target> &rtt, rsx::surface_color_format format, size_t width, size_t height, bool check_refs=false)
|
||||
{
|
||||
|
||||
@@ -473,6 +473,7 @@ namespace gl
|
||||
|
||||
glBindTexture(target, id);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
|
||||
|
||||
|
||||
@@ -386,6 +386,8 @@ namespace gl
|
||||
|
||||
bool flush()
|
||||
{
|
||||
if (flushed) return true; //Already written, ignore
|
||||
|
||||
if (!copied)
|
||||
{
|
||||
LOG_WARNING(RSX, "Cache miss at address 0x%X. This is gonna hurt...", cpu_address_base);
|
||||
@@ -399,7 +401,6 @@ namespace gl
|
||||
}
|
||||
}
|
||||
|
||||
protect(utils::protection::rw);
|
||||
m_fence.wait_for_signal();
|
||||
flushed = true;
|
||||
|
||||
@@ -443,22 +444,21 @@ namespace gl
|
||||
{
|
||||
//Read-only texture, destroy texture memory
|
||||
glDeleteTextures(1, &vram_texture);
|
||||
vram_texture = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Destroy pbo cache since vram texture is managed elsewhere
|
||||
glDeleteBuffers(1, &pbo_id);
|
||||
pbo_id = 0;
|
||||
pbo_size = 0;
|
||||
|
||||
if (scaled_texture)
|
||||
{
|
||||
glDeleteTextures(1, &scaled_texture);
|
||||
scaled_texture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
vram_texture = 0;
|
||||
scaled_texture = 0;
|
||||
pbo_id = 0;
|
||||
pbo_size = 0;
|
||||
|
||||
if (!m_fence.is_empty())
|
||||
m_fence.destroy();
|
||||
}
|
||||
@@ -571,7 +571,7 @@ namespace gl
|
||||
m_temporary_surfaces.resize(0);
|
||||
}
|
||||
|
||||
u32 create_temporary_subresource(u32 src_id, GLenum sized_internal_fmt, u16 x, u16 y, u16 width, u16 height)
|
||||
u32 create_temporary_subresource_impl(u32 src_id, GLenum sized_internal_fmt, const GLenum dst_type, u16 x, u16 y, u16 width, u16 height)
|
||||
{
|
||||
u32 dst_id = 0;
|
||||
|
||||
@@ -589,19 +589,23 @@ namespace gl
|
||||
}
|
||||
|
||||
glGenTextures(1, &dst_id);
|
||||
glBindTexture(GL_TEXTURE_2D, dst_id);
|
||||
glBindTexture(dst_type, dst_id);
|
||||
|
||||
glTexStorage2D(GL_TEXTURE_2D, 1, sized_internal_fmt, width, height);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
if (dst_type == GL_TEXTURE_2D)
|
||||
glTexStorage2D(GL_TEXTURE_2D, 1, sized_internal_fmt, width, height);
|
||||
else if (dst_type == GL_TEXTURE_1D)
|
||||
glTexStorage1D(GL_TEXTURE_1D, 1, sized_internal_fmt, width);
|
||||
|
||||
glTexParameteri(dst_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(dst_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(dst_type, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(dst_type, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
|
||||
//Empty GL_ERROR
|
||||
glGetError();
|
||||
|
||||
glCopyImageSubData(src_id, GL_TEXTURE_2D, 0, x, y, 0,
|
||||
dst_id, GL_TEXTURE_2D, 0, 0, 0, 0, width, height, 1);
|
||||
dst_id, dst_type, 0, 0, 0, 0, width, height, 1);
|
||||
|
||||
m_temporary_surfaces.push_back(dst_id);
|
||||
|
||||
@@ -625,22 +629,59 @@ namespace gl
|
||||
u32 create_temporary_subresource_view(void*&, u32* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override
|
||||
{
|
||||
const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
|
||||
return create_temporary_subresource(*src, ifmt, x, y, w, h);
|
||||
return create_temporary_subresource_impl(*src, ifmt, GL_TEXTURE_2D, x, y, w, h);
|
||||
}
|
||||
|
||||
u32 create_temporary_subresource_view(void*&, gl::texture* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override
|
||||
{
|
||||
if (auto as_rtt = dynamic_cast<gl::render_target*>(src))
|
||||
{
|
||||
return create_temporary_subresource(src->id(), (GLenum)as_rtt->get_compatible_internal_format(), x, y, w, h);
|
||||
return create_temporary_subresource_impl(src->id(), (GLenum)as_rtt->get_compatible_internal_format(), GL_TEXTURE_2D, x, y, w, h);
|
||||
}
|
||||
else
|
||||
{
|
||||
const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
|
||||
return create_temporary_subresource(src->id(), ifmt, x, y, w, h);
|
||||
return create_temporary_subresource_impl(src->id(), ifmt, GL_TEXTURE_2D, x, y, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
u32 generate_cubemap_from_images(void*&, const u32 gcm_format, u16 size, std::array<u32, 6>& sources) override
|
||||
{
|
||||
const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
|
||||
GLuint dst_id = 0;
|
||||
|
||||
glGenTextures(1, &dst_id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, dst_id);
|
||||
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, ifmt, size, size);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
|
||||
|
||||
//Empty GL_ERROR
|
||||
glGetError();
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
if (sources[i] != 0)
|
||||
{
|
||||
glCopyImageSubData(sources[i], GL_TEXTURE_2D, 0, 0, 0, 0,
|
||||
dst_id, GL_TEXTURE_CUBE_MAP, 0, 0, 0, i, size, size, 1);
|
||||
}
|
||||
}
|
||||
|
||||
m_temporary_surfaces.push_back(dst_id);
|
||||
|
||||
if (GLenum err = glGetError())
|
||||
{
|
||||
LOG_WARNING(RSX, "Failed to copy image subresource with GL error 0x%X", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dst_id;
|
||||
}
|
||||
|
||||
cached_texture_section* create_new_texture(void*&, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, const u32 gcm_format,
|
||||
const rsx::texture_upload_context context, const rsx::texture_dimension_extended type, const rsx::texture_create_flags flags,
|
||||
std::pair<std::array<u8, 4>, std::array<u8, 4>>& /*remap_vector*/) override
|
||||
@@ -670,10 +711,14 @@ namespace gl
|
||||
cached.set_depth_flag(depth_flag);
|
||||
cached.set_view_flags(flags);
|
||||
cached.set_context(context);
|
||||
cached.set_image_type(type);
|
||||
|
||||
//Its not necessary to lock blit dst textures as they are just reused as necessary
|
||||
if (context != rsx::texture_upload_context::blit_engine_dst || g_cfg.video.strict_rendering_mode)
|
||||
{
|
||||
cached.protect(utils::protection::ro);
|
||||
update_cache_tag();
|
||||
}
|
||||
|
||||
return &cached;
|
||||
}
|
||||
@@ -773,6 +818,7 @@ namespace gl
|
||||
}
|
||||
|
||||
clear_temporary_subresources();
|
||||
m_temporary_subresource_cache.clear();
|
||||
}
|
||||
|
||||
bool blit(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool linear_interpolate, gl_render_targets& m_rtts)
|
||||
@@ -780,15 +826,5 @@ namespace gl
|
||||
void* unused = nullptr;
|
||||
return upload_scaled_image(src, dst, linear_interpolate, unused, m_rtts, m_hw_blitter);
|
||||
}
|
||||
|
||||
template<typename RsxTextureType>
|
||||
void upload_and_bind_texture(int index, GLenum target, RsxTextureType &tex, gl_render_targets &m_rtts)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
void* unused = nullptr;
|
||||
|
||||
auto id = upload_texture(unused, tex, m_rtts);
|
||||
glBindTexture(target, id);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace
|
||||
u32 block_sz = vertex_draw_count * type_size;
|
||||
|
||||
gsl::span<gsl::byte> dst{ reinterpret_cast<gsl::byte*>(ptr), ::narrow<u32>(block_sz) };
|
||||
std::tie(min_index, max_index) = write_index_array_data_to_buffer(dst, raw_index_buffer,
|
||||
std::tie(min_index, max_index, vertex_draw_count) = write_index_array_data_to_buffer(dst, raw_index_buffer,
|
||||
type, draw_mode, rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index(), first_count_commands,
|
||||
[](auto prim) { return !gl::is_primitive_native(prim); });
|
||||
|
||||
|
||||
@@ -18,10 +18,9 @@ std::string GLVertexDecompilerThread::getIntTypeName(size_t elementCount)
|
||||
return "ivec4";
|
||||
}
|
||||
|
||||
|
||||
std::string GLVertexDecompilerThread::getFunction(FUNCTION f)
|
||||
{
|
||||
return gl::getFunctionImpl(f);
|
||||
return glsl::getFunctionImpl(f);
|
||||
}
|
||||
|
||||
std::string GLVertexDecompilerThread::compareFunction(COMPARE f, const std::string &Op0, const std::string &Op1)
|
||||
|
||||
+12
-11
@@ -4,16 +4,6 @@
|
||||
|
||||
#include "GSRender.h"
|
||||
|
||||
draw_context_t GSFrameBase::new_context()
|
||||
{
|
||||
if (void* context = make_context())
|
||||
{
|
||||
return std::shared_ptr<void>(context, [this](void* ctxt) { delete_context(ctxt); });
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GSRender::GSRender()
|
||||
{
|
||||
m_frame = Emu.GetCallbacks().get_gs_frame().release();
|
||||
@@ -42,11 +32,22 @@ void GSRender::on_init_thread()
|
||||
{
|
||||
if (m_frame)
|
||||
{
|
||||
m_context = m_frame->new_context();
|
||||
m_context = m_frame->make_context();
|
||||
m_frame->set_current(m_context);
|
||||
}
|
||||
}
|
||||
|
||||
void GSRender::on_exit()
|
||||
{
|
||||
if (m_frame)
|
||||
{
|
||||
m_frame->delete_context(m_context);
|
||||
m_context = nullptr;
|
||||
}
|
||||
|
||||
rsx::thread::on_exit();
|
||||
}
|
||||
|
||||
void GSRender::flip(int buffer)
|
||||
{
|
||||
if (m_frame)
|
||||
|
||||
@@ -24,12 +24,15 @@ enum wm_event
|
||||
geometry_change_notice, //about to start resizing and/or moving the window
|
||||
geometry_change_in_progress, //window being resized and/or moved
|
||||
window_resized, //window was resized
|
||||
window_moved //window moved without resize
|
||||
window_minimized, //window was minimized
|
||||
window_restored, //window was restored from a minimized state
|
||||
window_moved, //window moved without resize
|
||||
window_visibility_changed
|
||||
};
|
||||
|
||||
using RSXDebuggerPrograms = std::vector<RSXDebuggerProgram>;
|
||||
|
||||
using draw_context_t = std::shared_ptr<void>;
|
||||
using draw_context_t = void*;
|
||||
|
||||
class GSFrameBase
|
||||
{
|
||||
@@ -42,8 +45,8 @@ public:
|
||||
virtual void hide() = 0;
|
||||
virtual void show() = 0;
|
||||
|
||||
draw_context_t new_context();
|
||||
|
||||
virtual void delete_context(draw_context_t ctx) = 0;
|
||||
virtual draw_context_t make_context() = 0;
|
||||
virtual void set_current(draw_context_t ctx) = 0;
|
||||
virtual void flip(draw_context_t ctx, bool skip_frame=false) = 0;
|
||||
virtual int client_width() = 0;
|
||||
@@ -52,12 +55,11 @@ public:
|
||||
virtual void* handle() const = 0;
|
||||
|
||||
protected:
|
||||
virtual void delete_context(void* ctx) = 0;
|
||||
virtual void* make_context() = 0;
|
||||
|
||||
//window manager event management
|
||||
wm_event m_raised_event;
|
||||
std::atomic_bool wm_event_raised = {};
|
||||
std::atomic_bool wm_event_queue_enabled = {};
|
||||
|
||||
public:
|
||||
//synchronize native window access
|
||||
@@ -83,6 +85,16 @@ public:
|
||||
|
||||
return get_default_wm_event();
|
||||
}
|
||||
|
||||
void disable_wm_event_queue()
|
||||
{
|
||||
wm_event_queue_enabled.store(false);
|
||||
}
|
||||
|
||||
void enable_wm_event_queue()
|
||||
{
|
||||
wm_event_queue_enabled.store(true);
|
||||
}
|
||||
};
|
||||
|
||||
class GSRender : public rsx::thread
|
||||
@@ -97,6 +109,7 @@ public:
|
||||
|
||||
void on_init_rsx() override;
|
||||
void on_init_thread() override;
|
||||
void on_exit() override;
|
||||
|
||||
void flip(int buffer) override;
|
||||
};
|
||||
|
||||
@@ -243,13 +243,10 @@ struct RSXFragmentProgram
|
||||
|
||||
void set_texture_dimension(const std::array<rsx::texture_dimension_extended, 16> &dimensions)
|
||||
{
|
||||
size_t id = 0;
|
||||
for (const rsx::texture_dimension_extended &dim : dimensions)
|
||||
texture_dimensions = 0;
|
||||
for (u32 i = 0, offset = 0; i < 16; ++i, offset += 2)
|
||||
{
|
||||
texture_dimensions &= ~(0x3 << (id * 2));
|
||||
u8 d = (u8)dim;
|
||||
texture_dimensions |= ((d & 0x3) << (id * 2));
|
||||
id++;
|
||||
texture_dimensions |= (u32)dimensions[i] << offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+125
-28
@@ -7,6 +7,7 @@
|
||||
#include "Emu/Cell/PPUCallback.h"
|
||||
|
||||
#include "Common/BufferUtils.h"
|
||||
#include "Common/texture_cache.h"
|
||||
#include "rsx_methods.h"
|
||||
#include "rsx_utils.h"
|
||||
|
||||
@@ -243,6 +244,7 @@ namespace rsx
|
||||
};
|
||||
m_rtts_dirty = true;
|
||||
memset(m_textures_dirty, -1, sizeof(m_textures_dirty));
|
||||
memset(m_vertex_textures_dirty, -1, sizeof(m_vertex_textures_dirty));
|
||||
m_transform_constants_dirty = true;
|
||||
}
|
||||
|
||||
@@ -477,10 +479,10 @@ namespace rsx
|
||||
//Execute backend-local tasks first
|
||||
do_local_task();
|
||||
|
||||
const u32 get = ctrl->get;
|
||||
ctrl->get.store(internal_get.load());
|
||||
const u32 put = ctrl->put;
|
||||
|
||||
if (put == get || !Emu.IsRunning())
|
||||
if (put == internal_get || !Emu.IsRunning())
|
||||
{
|
||||
if (has_deferred_call)
|
||||
flush_command_queue();
|
||||
@@ -491,16 +493,16 @@ namespace rsx
|
||||
|
||||
//Validate put and get registers
|
||||
//TODO: Who should handle graphics exceptions??
|
||||
const u32 get_address = RSXIOMem.RealAddr(get);
|
||||
const u32 get_address = RSXIOMem.RealAddr(internal_get);
|
||||
|
||||
if (!get_address)
|
||||
{
|
||||
LOG_ERROR(RSX, "Invalid FIFO queue get/put registers found, get=0x%X, put=0x%X", get, put);
|
||||
LOG_ERROR(RSX, "Invalid FIFO queue get/put registers found, get=0x%X, put=0x%X", internal_get.load(), put);
|
||||
|
||||
if (mem_faults_count >= 3)
|
||||
{
|
||||
LOG_ERROR(RSX, "Application has failed to recover, discarding FIFO queue");
|
||||
ctrl->get = put;
|
||||
internal_get = put;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -512,29 +514,29 @@ namespace rsx
|
||||
continue;
|
||||
}
|
||||
|
||||
const u32 cmd = ReadIO32(get);
|
||||
const u32 cmd = ReadIO32(internal_get);
|
||||
const u32 count = (cmd >> 18) & 0x7ff;
|
||||
|
||||
if ((cmd & RSX_METHOD_OLD_JUMP_CMD_MASK) == RSX_METHOD_OLD_JUMP_CMD)
|
||||
{
|
||||
u32 offs = cmd & 0x1ffffffc;
|
||||
//LOG_WARNING(RSX, "rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put);
|
||||
ctrl->get = offs;
|
||||
internal_get = offs;
|
||||
continue;
|
||||
}
|
||||
if ((cmd & RSX_METHOD_NEW_JUMP_CMD_MASK) == RSX_METHOD_NEW_JUMP_CMD)
|
||||
{
|
||||
u32 offs = cmd & 0xfffffffc;
|
||||
//LOG_WARNING(RSX, "rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put);
|
||||
ctrl->get = offs;
|
||||
internal_get = offs;
|
||||
continue;
|
||||
}
|
||||
if ((cmd & RSX_METHOD_CALL_CMD_MASK) == RSX_METHOD_CALL_CMD)
|
||||
{
|
||||
m_call_stack.push(get + 4);
|
||||
m_call_stack.push(internal_get + 4);
|
||||
u32 offs = cmd & ~3;
|
||||
//LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x", offs, cmd, get);
|
||||
ctrl->get = offs;
|
||||
internal_get = offs;
|
||||
continue;
|
||||
}
|
||||
if (cmd == RSX_METHOD_RETURN_CMD)
|
||||
@@ -542,26 +544,26 @@ namespace rsx
|
||||
u32 get = m_call_stack.top();
|
||||
m_call_stack.pop();
|
||||
//LOG_WARNING(RSX, "rsx return(0x%x)", get);
|
||||
ctrl->get = get;
|
||||
internal_get = get;
|
||||
continue;
|
||||
}
|
||||
if (cmd == 0) //nop
|
||||
{
|
||||
ctrl->get = get + 4;
|
||||
internal_get += 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
//Validate the args ptr if the command attempts to read from it
|
||||
const u32 args_address = RSXIOMem.RealAddr(get + 4);
|
||||
const u32 args_address = RSXIOMem.RealAddr(internal_get + 4);
|
||||
|
||||
if (!args_address && count)
|
||||
{
|
||||
LOG_ERROR(RSX, "Invalid FIFO queue args ptr found, get=0x%X, cmd=0x%X, count=%d", get, cmd, count);
|
||||
LOG_ERROR(RSX, "Invalid FIFO queue args ptr found, get=0x%X, cmd=0x%X, count=%d", internal_get.load(), cmd, count);
|
||||
|
||||
if (mem_faults_count >= 3)
|
||||
{
|
||||
LOG_ERROR(RSX, "Application has failed to recover, discarding FIFO queue");
|
||||
ctrl->get = put;
|
||||
internal_get = put;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -595,6 +597,7 @@ namespace rsx
|
||||
|
||||
bool execute_method_call = true;
|
||||
|
||||
//TODO: Flatten draw calls when multidraw is not supported to simplify checking in the end() methods
|
||||
if (supports_multidraw)
|
||||
{
|
||||
//TODO: Make this cleaner
|
||||
@@ -713,11 +716,11 @@ namespace rsx
|
||||
{
|
||||
//This is almost guaranteed to be heap corruption at this point
|
||||
//Ignore the rest of the chain
|
||||
ctrl->get = put;
|
||||
internal_get = put;
|
||||
continue;
|
||||
}
|
||||
|
||||
ctrl->get = get + (count + 1) * 4;
|
||||
internal_get += (count + 1) * 4;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1320,7 +1323,99 @@ namespace rsx
|
||||
return result;
|
||||
}
|
||||
|
||||
void thread::get_current_fragment_program(std::function<std::tuple<bool, u16>(u32, fragment_texture&, bool)> get_surface_info)
|
||||
void thread::get_current_fragment_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count>& sampler_descriptors)
|
||||
{
|
||||
auto &result = current_fragment_program = {};
|
||||
|
||||
const u32 shader_program = rsx::method_registers.shader_program_address();
|
||||
if (shader_program == 0)
|
||||
return;
|
||||
|
||||
const u32 program_location = (shader_program & 0x3) - 1;
|
||||
const u32 program_offset = (shader_program & ~0x3);
|
||||
|
||||
result.offset = program_offset;
|
||||
result.addr = vm::base(rsx::get_address(program_offset, program_location));
|
||||
result.valid = true;
|
||||
result.ctrl = rsx::method_registers.shader_control();
|
||||
result.unnormalized_coords = 0;
|
||||
result.front_back_color_enabled = !rsx::method_registers.two_side_light_en();
|
||||
result.back_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE);
|
||||
result.back_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR);
|
||||
result.front_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE);
|
||||
result.front_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR);
|
||||
result.redirected_textures = 0;
|
||||
result.shadow_textures = 0;
|
||||
|
||||
std::array<texture_dimension_extended, 16> texture_dimensions;
|
||||
const auto resolution_scale = rsx::get_resolution_scale();
|
||||
|
||||
for (u32 i = 0; i < rsx::limits::fragment_textures_count; ++i)
|
||||
{
|
||||
auto &tex = rsx::method_registers.fragment_textures[i];
|
||||
result.texture_scale[i][0] = sampler_descriptors[i]->scale_x;
|
||||
result.texture_scale[i][1] = sampler_descriptors[i]->scale_y;
|
||||
result.textures_alpha_kill[i] = 0;
|
||||
result.textures_zfunc[i] = 0;
|
||||
|
||||
if (!tex.enabled())
|
||||
{
|
||||
texture_dimensions[i] = texture_dimension_extended::texture_dimension_2d;
|
||||
}
|
||||
else
|
||||
{
|
||||
texture_dimensions[i] = sampler_descriptors[i]->image_type;
|
||||
|
||||
if (tex.alpha_kill_enabled())
|
||||
{
|
||||
//alphakill can be ignored unless a valid comparison function is set
|
||||
const rsx::comparison_function func = (rsx::comparison_function)tex.zfunc();
|
||||
if (func < rsx::comparison_function::always && func > rsx::comparison_function::never)
|
||||
{
|
||||
result.textures_alpha_kill[i] = 1;
|
||||
result.textures_zfunc[i] = (u8)func;
|
||||
}
|
||||
}
|
||||
|
||||
const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
|
||||
const u32 raw_format = tex.format();
|
||||
|
||||
if (raw_format & CELL_GCM_TEXTURE_UN)
|
||||
result.unnormalized_coords |= (1 << i);
|
||||
|
||||
if (sampler_descriptors[i]->is_depth_texture)
|
||||
{
|
||||
const u32 format = raw_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
|
||||
switch (format)
|
||||
{
|
||||
case CELL_GCM_TEXTURE_A8R8G8B8:
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8:
|
||||
case CELL_GCM_TEXTURE_A4R4G4B4:
|
||||
case CELL_GCM_TEXTURE_R5G6B5:
|
||||
result.redirected_textures |= (1 << i);
|
||||
break;
|
||||
case CELL_GCM_TEXTURE_DEPTH16:
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||
{
|
||||
const auto compare_mode = (rsx::comparison_function)tex.zfunc();
|
||||
if (result.textures_alpha_kill[i] == 0 &&
|
||||
compare_mode < rsx::comparison_function::always &&
|
||||
compare_mode > rsx::comparison_function::never)
|
||||
result.shadow_textures |= (1 << i);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR(RSX, "Depth texture bound to pipeline with unexpected format 0x%X", format);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.set_texture_dimension(texture_dimensions);
|
||||
}
|
||||
|
||||
void thread::get_current_fragment_program_legacy(std::function<std::tuple<bool, u16>(u32, fragment_texture&, bool)> get_surface_info)
|
||||
{
|
||||
auto &result = current_fragment_program = {};
|
||||
|
||||
@@ -1411,8 +1506,8 @@ namespace rsx
|
||||
case CELL_GCM_TEXTURE_D8R8G8B8:
|
||||
case CELL_GCM_TEXTURE_A4R4G4B4:
|
||||
case CELL_GCM_TEXTURE_R5G6B5:
|
||||
result.redirected_textures |= (1 << i);
|
||||
break;
|
||||
result.redirected_textures |= (1 << i);
|
||||
break;
|
||||
case CELL_GCM_TEXTURE_DEPTH16:
|
||||
case CELL_GCM_TEXTURE_DEPTH24_D8:
|
||||
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
|
||||
@@ -1425,7 +1520,7 @@ namespace rsx
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR(RSX, "Depth texture bound to pipeline with unexpected format 0x%X", format);
|
||||
LOG_ERROR(RSX, "Depth texture bound to pipeline with unexpected format 0x%X", format);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1458,7 +1553,7 @@ namespace rsx
|
||||
{
|
||||
for (GcmTileInfo &tile : tiles)
|
||||
{
|
||||
if (!tile.binded || tile.location != location)
|
||||
if (!tile.binded || (tile.location & 1) != (location & 1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1570,6 +1665,7 @@ namespace rsx
|
||||
u32 volatile_offset = 0;
|
||||
u32 persistent_offset = 0;
|
||||
|
||||
//NOTE: Order is important! Transient ayout is always push_buffers followed by register data
|
||||
if (rsx::method_registers.current_draw_clause.is_immediate_draw)
|
||||
{
|
||||
for (const auto &info : layout.volatile_blocks)
|
||||
@@ -1764,12 +1860,7 @@ namespace rsx
|
||||
return;
|
||||
}
|
||||
|
||||
for (const u8 index : layout.referenced_registers)
|
||||
{
|
||||
memcpy(transient, rsx::method_registers.register_vertex_info[index].data.data(), 16);
|
||||
transient += 16;
|
||||
}
|
||||
|
||||
//NOTE: Order is important! Transient ayout is always push_buffers followed by register data
|
||||
if (draw_call.is_immediate_draw)
|
||||
{
|
||||
//NOTE: It is possible for immediate draw to only contain index data, so vertex data can be in persistent memory
|
||||
@@ -1779,6 +1870,12 @@ namespace rsx
|
||||
transient += info.second;
|
||||
}
|
||||
}
|
||||
|
||||
for (const u8 index : layout.referenced_registers)
|
||||
{
|
||||
memcpy(transient, rsx::method_registers.register_vertex_info[index].data.data(), 16);
|
||||
transient += 16;
|
||||
}
|
||||
}
|
||||
|
||||
if (persistent != nullptr)
|
||||
|
||||
@@ -135,6 +135,8 @@ namespace rsx
|
||||
std::array<attribute_buffer_placement, 16> attribute_placement;
|
||||
};
|
||||
|
||||
struct sampled_image_descriptor_base;
|
||||
|
||||
class thread : public named_thread
|
||||
{
|
||||
std::shared_ptr<thread_ctrl> m_vblank_thread;
|
||||
@@ -151,6 +153,7 @@ namespace rsx
|
||||
|
||||
public:
|
||||
RsxDmaControl* ctrl = nullptr;
|
||||
atomic_t<u32> internal_get{ 0 };
|
||||
|
||||
Timer timer_sync;
|
||||
|
||||
@@ -187,6 +190,7 @@ namespace rsx
|
||||
bool m_rtts_dirty;
|
||||
bool m_transform_constants_dirty;
|
||||
bool m_textures_dirty[16];
|
||||
bool m_vertex_textures_dirty[4];
|
||||
|
||||
protected:
|
||||
std::array<u32, 4> get_color_surface_addresses() const;
|
||||
@@ -207,7 +211,9 @@ namespace rsx
|
||||
* get_surface_info is a helper takes 2 parameters: rsx_texture_address and surface_is_depth
|
||||
* returns whether surface is a render target and surface pitch in native format
|
||||
*/
|
||||
void get_current_fragment_program(std::function<std::tuple<bool, u16>(u32, fragment_texture&, bool)> get_surface_info);
|
||||
void get_current_fragment_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count>& sampler_descriptors);
|
||||
void get_current_fragment_program_legacy(std::function<std::tuple<bool, u16>(u32, fragment_texture&, bool)> get_surface_info);
|
||||
|
||||
public:
|
||||
double fps_limit = 59.94;
|
||||
|
||||
@@ -257,6 +263,7 @@ namespace rsx
|
||||
virtual u64 timestamp() const;
|
||||
virtual bool on_access_violation(u32 /*address*/, bool /*is_writing*/) { return false; }
|
||||
virtual void on_notify_memory_unmapped(u32 /*address_base*/, u32 /*size*/) {}
|
||||
virtual void notify_tile_unbound(u32 /*tile*/) {}
|
||||
|
||||
//zcull
|
||||
virtual void notify_zcull_info_changed() {}
|
||||
|
||||
@@ -8,69 +8,6 @@ namespace vk
|
||||
{
|
||||
static TBuiltInResource g_default_config;
|
||||
|
||||
std::string getFunctionImpl(FUNCTION f)
|
||||
{
|
||||
switch (f)
|
||||
{
|
||||
default:
|
||||
abort();
|
||||
case FUNCTION::FUNCTION_DP2:
|
||||
return "vec4(dot($0.xy, $1.xy))";
|
||||
case FUNCTION::FUNCTION_DP2A:
|
||||
return "vec4(dot($0.xy, $1.xy) + $2.x)";
|
||||
case FUNCTION::FUNCTION_DP3:
|
||||
return "vec4(dot($0.xyz, $1.xyz))";
|
||||
case FUNCTION::FUNCTION_DP4:
|
||||
return "vec4(dot($0, $1))";
|
||||
case FUNCTION::FUNCTION_DPH:
|
||||
return "vec4(dot(vec4($0.xyz, 1.0), $1))";
|
||||
case FUNCTION::FUNCTION_SFL:
|
||||
return "vec4(0., 0., 0., 0.)";
|
||||
case FUNCTION::FUNCTION_STR:
|
||||
return "vec4(1., 1., 1., 1.)";
|
||||
case FUNCTION::FUNCTION_FRACT:
|
||||
return "fract($0)";
|
||||
case FUNCTION::FUNCTION_REFL:
|
||||
return "vec4($0 - 2.0 * (dot($0, $1)) * $1)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D:
|
||||
return "texture($t, $0.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ:
|
||||
return "textureProj($t, $0.x, $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD:
|
||||
return "textureLod($t, $0.x, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD:
|
||||
return "textureGrad($t, $0.x, $1.x, $2.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D:
|
||||
return "texture($t, $0.xy * texture_parameters[$_i].xy)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ:
|
||||
return "textureProj($t, $0, $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD:
|
||||
return "textureLod($t, $0.xy * texture_parameters[$_i].xy, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD:
|
||||
return "textureGrad($t, $0.xy * texture_parameters[$_i].xy, $1.xy, $2.xy)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D:
|
||||
return "texture($t, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ:
|
||||
return "textureProj($t, $0, $1.x)"; // Note: $1.x is bias
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE:
|
||||
return "texture($t, $0.xyz)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ:
|
||||
return "texture($t, ($0.xyz / $0.w))";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD:
|
||||
return "textureLod($t, $0.xyz, $1.x)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD:
|
||||
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
|
||||
case FUNCTION::FUNCTION_DFDX:
|
||||
return "dFdx($0)";
|
||||
case FUNCTION::FUNCTION_DFDY:
|
||||
return "dFdy($0)";
|
||||
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D:
|
||||
return "textureLod($t, $0.xy, 0)";
|
||||
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA:
|
||||
return "texture2DReconstruct($t, $0.xy)";
|
||||
}
|
||||
}
|
||||
|
||||
void init_default_resources(TBuiltInResource &rsc)
|
||||
{
|
||||
rsc.maxLights = 32;
|
||||
|
||||
@@ -12,9 +12,6 @@ namespace vk
|
||||
int reg_location;
|
||||
};
|
||||
|
||||
//Decompiler function lookup
|
||||
std::string getFunctionImpl(FUNCTION f);
|
||||
|
||||
const varying_register_t& get_varying_register(const std::string& name);
|
||||
bool compile_glsl_to_spv(std::string& shader, program_domain domain, std::vector<u32> &spv);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ std::string VKFragmentDecompilerThread::getFloatTypeName(size_t elementCount)
|
||||
|
||||
std::string VKFragmentDecompilerThread::getFunction(FUNCTION f)
|
||||
{
|
||||
return vk::getFunctionImpl(f);
|
||||
return glsl::getFunctionImpl(f);
|
||||
}
|
||||
|
||||
std::string VKFragmentDecompilerThread::saturate(const std::string & code)
|
||||
@@ -118,11 +118,7 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
|
||||
|
||||
const auto mask = (1 << index);
|
||||
|
||||
if (m_prog.unnormalized_coords & mask)
|
||||
{
|
||||
samplerType = "sampler2DRect";
|
||||
}
|
||||
else if (m_prog.shadow_textures & mask)
|
||||
if (m_prog.shadow_textures & mask)
|
||||
{
|
||||
if (m_shadow_sampled_textures & mask)
|
||||
{
|
||||
@@ -458,7 +454,7 @@ void VKFragmentProgram::Decompile(const RSXFragmentProgram& prog)
|
||||
void VKFragmentProgram::Compile()
|
||||
{
|
||||
fs::create_path(fs::get_config_dir() + "/shaderlog");
|
||||
fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram.spirv", fs::rewrite).write(shader);
|
||||
fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader);
|
||||
|
||||
std::vector<u32> spir_v;
|
||||
if (!vk::compile_glsl_to_spv(shader, glsl::glsl_fragment_program, spir_v))
|
||||
@@ -474,8 +470,6 @@ void VKFragmentProgram::Compile()
|
||||
|
||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||
vkCreateShaderModule(dev, &fs_info, nullptr, &handle);
|
||||
|
||||
id = UINT32_MAX;
|
||||
}
|
||||
|
||||
void VKFragmentProgram::Delete()
|
||||
|
||||
+475
-289
File diff suppressed because it is too large
Load Diff
@@ -129,6 +129,17 @@ private:
|
||||
|
||||
std::unique_ptr<vk::text_writer> m_text_writer;
|
||||
|
||||
std::mutex m_sampler_mutex;
|
||||
u64 surface_store_tag = 0;
|
||||
std::atomic_bool m_samplers_dirty = { true };
|
||||
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count> fs_sampler_state = {};
|
||||
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count> vs_sampler_state = {};
|
||||
std::array<std::unique_ptr<vk::sampler>, rsx::limits::fragment_textures_count> fs_sampler_handles;
|
||||
std::array<std::unique_ptr<vk::sampler>, rsx::limits::vertex_textures_count> vs_sampler_handles;
|
||||
|
||||
VkBufferView m_persistent_attribute_storage;
|
||||
VkBufferView m_volatile_attribute_storage;
|
||||
|
||||
public:
|
||||
//vk::fbo draw_fbo;
|
||||
std::unique_ptr<vk::vertex_cache> m_vertex_cache;
|
||||
@@ -295,6 +306,8 @@ private:
|
||||
void begin_render_pass();
|
||||
void close_render_pass();
|
||||
|
||||
void update_draw_state();
|
||||
|
||||
/// returns primitive topology, index_count, allocated_verts, vertex_base_index, (offset in index buffer, index type)
|
||||
std::tuple<VkPrimitiveTopology, u32, u32, u32, std::optional<std::tuple<VkDeviceSize, VkIndexType> > > upload_vertex_data();
|
||||
public:
|
||||
@@ -316,6 +329,7 @@ protected:
|
||||
|
||||
void do_local_task() override;
|
||||
bool scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate) override;
|
||||
void notify_tile_unbound(u32 tile) override;
|
||||
|
||||
bool on_access_violation(u32 address, bool is_writing) override;
|
||||
void on_notify_memory_unmapped(u32 address_base, u32 size) override;
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace vk
|
||||
VkSampler g_null_sampler = nullptr;
|
||||
|
||||
bool g_cb_no_interrupt_flag = false;
|
||||
bool g_drv_no_primitive_restart_flag = false;
|
||||
|
||||
u64 g_num_processed_frames = 0;
|
||||
u64 g_num_total_frames = 0;
|
||||
@@ -257,6 +258,34 @@ namespace vk
|
||||
void set_current_renderer(const vk::render_device &device)
|
||||
{
|
||||
g_current_renderer = device;
|
||||
|
||||
const std::array<std::string, 8> black_listed =
|
||||
{
|
||||
// Black list all polaris unless its proven they dont have a problem with primitive restart
|
||||
"RX 580",
|
||||
"RX 570",
|
||||
"RX 560",
|
||||
"RX 550",
|
||||
"RX 480",
|
||||
"RX 470",
|
||||
"RX 460",
|
||||
"RX Vega",
|
||||
};
|
||||
|
||||
const auto gpu_name = g_current_renderer.gpu().name();
|
||||
for (const auto& test : black_listed)
|
||||
{
|
||||
if (gpu_name.find(test) != std::string::npos)
|
||||
{
|
||||
g_drv_no_primitive_restart_flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool emulate_primitive_restart()
|
||||
{
|
||||
return g_drv_no_primitive_restart_flag;
|
||||
}
|
||||
|
||||
void change_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range)
|
||||
@@ -453,8 +482,8 @@ namespace vk
|
||||
case VK_ERROR_OUT_OF_POOL_MEMORY_KHR:
|
||||
error_message = "Out of pool memory (VK_ERROR_OUT_OF_POOL_MEMORY_KHR)";
|
||||
break;
|
||||
case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX:
|
||||
error_message = "Invalid external handle (VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX)";
|
||||
case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR:
|
||||
error_message = "Invalid external handle (VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR)";
|
||||
break;
|
||||
default:
|
||||
error_message = fmt::format("Unknown Code (%Xh, %d)%s", (s32)error_code, (s32&)error_code, faulting_addr);
|
||||
|
||||
@@ -66,6 +66,8 @@ namespace vk
|
||||
vk::render_device *get_current_renderer();
|
||||
void set_current_renderer(const vk::render_device &device);
|
||||
|
||||
bool emulate_primitive_restart();
|
||||
|
||||
VkComponentMapping default_component_map();
|
||||
VkImageSubresource default_image_subresource();
|
||||
VkImageSubresourceRange get_image_subresource_range(uint32_t base_layer, uint32_t base_mip, uint32_t layer_count, uint32_t level_count, VkImageAspectFlags aspect);
|
||||
@@ -574,7 +576,7 @@ namespace vk
|
||||
VkSamplerCreateInfo info = {};
|
||||
|
||||
sampler(VkDevice dev, VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,
|
||||
bool unnormalized_coordinates, float mipLodBias, float max_anisotropy, float min_lod, float max_lod,
|
||||
VkBool32 unnormalized_coordinates, float mipLodBias, float max_anisotropy, float min_lod, float max_lod,
|
||||
VkFilter min_filter, VkFilter mag_filter, VkSamplerMipmapMode mipmap_mode, VkBorderColor border_color,
|
||||
VkBool32 depth_compare = false, VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER)
|
||||
: m_device(dev)
|
||||
@@ -605,6 +607,21 @@ namespace vk
|
||||
vkDestroySampler(m_device, value, nullptr);
|
||||
}
|
||||
|
||||
bool matches(VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,
|
||||
VkBool32 unnormalized_coordinates, float mipLodBias, float max_anisotropy, float min_lod, float max_lod,
|
||||
VkFilter min_filter, VkFilter mag_filter, VkSamplerMipmapMode mipmap_mode, VkBorderColor border_color,
|
||||
VkBool32 depth_compare = false, VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER)
|
||||
{
|
||||
if (info.magFilter != mag_filter || info.minFilter != min_filter || info.mipmapMode != mipmap_mode ||
|
||||
info.addressModeU != clamp_u || info.addressModeV != clamp_v || info.addressModeW != clamp_w ||
|
||||
info.compareEnable != depth_compare || info.unnormalizedCoordinates != unnormalized_coordinates ||
|
||||
info.mipLodBias != mipLodBias || info.maxAnisotropy != max_anisotropy || info.maxLod != max_lod ||
|
||||
info.minLod != min_lod || info.compareOp != depth_compare_mode || info.borderColor != border_color)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
sampler(const sampler&) = delete;
|
||||
sampler(sampler&&) = delete;
|
||||
private:
|
||||
@@ -807,7 +824,7 @@ namespace vk
|
||||
}
|
||||
}
|
||||
|
||||
void init_swapchain(u32 width, u32 height)
|
||||
bool init_swapchain(u32 width, u32 height)
|
||||
{
|
||||
VkSwapchainKHR old_swapchain = m_vk_swapchain;
|
||||
vk::physical_device& gpu = const_cast<vk::physical_device&>(dev.gpu());
|
||||
@@ -815,8 +832,16 @@ namespace vk
|
||||
VkSurfaceCapabilitiesKHR surface_descriptors = {};
|
||||
CHECK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, m_surface, &surface_descriptors));
|
||||
|
||||
VkExtent2D swapchainExtent;
|
||||
if (surface_descriptors.maxImageExtent.width < width ||
|
||||
surface_descriptors.maxImageExtent.height < height)
|
||||
{
|
||||
LOG_ERROR(RSX, "Swapchain: Swapchain creation failed because dimensions cannot fit. Max = %d, %d, Requested = %d, %d",
|
||||
surface_descriptors.maxImageExtent.width, surface_descriptors.maxImageExtent.height, width, height);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
VkExtent2D swapchainExtent;
|
||||
if (surface_descriptors.currentExtent.width == (uint32_t)-1)
|
||||
{
|
||||
swapchainExtent.width = width;
|
||||
@@ -824,6 +849,12 @@ namespace vk
|
||||
}
|
||||
else
|
||||
{
|
||||
if (surface_descriptors.currentExtent.width == 0 || surface_descriptors.currentExtent.height == 0)
|
||||
{
|
||||
LOG_WARNING(RSX, "Swapchain: Current surface extent is a null region. Is the window minimized?");
|
||||
return false;
|
||||
}
|
||||
|
||||
swapchainExtent = surface_descriptors.currentExtent;
|
||||
width = surface_descriptors.currentExtent.width;
|
||||
height = surface_descriptors.currentExtent.height;
|
||||
@@ -930,6 +961,8 @@ namespace vk
|
||||
{
|
||||
m_swap_images[i].create(dev, swap_images[i], m_surface_format);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 get_swap_image_count()
|
||||
@@ -1011,6 +1044,14 @@ namespace vk
|
||||
vk::command_pool *pool = nullptr;
|
||||
VkCommandBuffer commands = nullptr;
|
||||
|
||||
public:
|
||||
enum access_type_hint
|
||||
{
|
||||
flush_only, //Only to be submitted/opened/closed via command flush
|
||||
all //Auxilliary, can be sumitted/opened/closed at any time
|
||||
}
|
||||
access_hint = flush_only;
|
||||
|
||||
public:
|
||||
command_buffer() {}
|
||||
~command_buffer() {}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace vk
|
||||
if (memcmp(&att_state[0], &other.att_state[0], sizeof(VkPipelineColorBlendAttachmentState)))
|
||||
return false;
|
||||
|
||||
if (render_pass != other.render_pass)
|
||||
if (render_pass_location != other.render_pass_location)
|
||||
return false;
|
||||
|
||||
if (memcmp(&rs, &other.rs, sizeof(VkPipelineRasterizationStateCreateInfo)))
|
||||
@@ -83,16 +83,16 @@ struct VKTraits
|
||||
void recompile_fragment_program(const RSXFragmentProgram &RSXFP, fragment_program_type& fragmentProgramData, size_t ID)
|
||||
{
|
||||
fragmentProgramData.Decompile(RSXFP);
|
||||
fragmentProgramData.Compile();
|
||||
fragmentProgramData.id = static_cast<u32>(ID);
|
||||
fragmentProgramData.Compile();
|
||||
}
|
||||
|
||||
static
|
||||
void recompile_vertex_program(const RSXVertexProgram &RSXVP, vertex_program_type& vertexProgramData, size_t ID)
|
||||
{
|
||||
vertexProgramData.Decompile(RSXVP);
|
||||
vertexProgramData.Compile();
|
||||
vertexProgramData.id = static_cast<u32>(ID);
|
||||
vertexProgramData.Compile();
|
||||
}
|
||||
|
||||
static
|
||||
|
||||
@@ -22,10 +22,15 @@ namespace vk
|
||||
bool dirty = false;
|
||||
u16 native_pitch = 0;
|
||||
u16 rsx_pitch = 0;
|
||||
|
||||
u16 surface_width = 0;
|
||||
u16 surface_height = 0;
|
||||
|
||||
VkImageAspectFlags attachment_aspect_flag = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
std::unique_ptr<vk::image_view> view;
|
||||
|
||||
render_target *old_contents = nullptr; //Data occupying the memory location that this surface is replacing
|
||||
u64 frame_tag = 0; //frame id when invalidated, 0 if not invalid
|
||||
|
||||
render_target(vk::render_device &dev,
|
||||
uint32_t memory_type_index,
|
||||
@@ -60,12 +65,12 @@ namespace vk
|
||||
|
||||
u16 get_surface_width() const override
|
||||
{
|
||||
return rsx::apply_inverse_resolution_scale(width(), true);
|
||||
return surface_width;
|
||||
}
|
||||
|
||||
u16 get_surface_height() const override
|
||||
{
|
||||
return rsx::apply_inverse_resolution_scale(height(), true);
|
||||
return surface_height;
|
||||
}
|
||||
|
||||
u16 get_rsx_pitch() const override
|
||||
@@ -142,6 +147,8 @@ namespace rsx
|
||||
|
||||
rtt->native_component_map = fmt.second;
|
||||
rtt->native_pitch = (u16)width * get_format_block_size_in_bytes(format);
|
||||
rtt->surface_width = (u16)width;
|
||||
rtt->surface_height = (u16)height;
|
||||
|
||||
if (old_surface != nullptr && old_surface->info.format == requested_format)
|
||||
{
|
||||
@@ -196,6 +203,8 @@ namespace rsx
|
||||
ds->native_pitch *= 2;
|
||||
|
||||
ds->attachment_aspect_flag = range.aspectMask;
|
||||
ds->surface_width = (u16)width;
|
||||
ds->surface_height = (u16)height;
|
||||
|
||||
if (old_surface != nullptr && old_surface->info.format == requested_format)
|
||||
{
|
||||
@@ -223,6 +232,7 @@ namespace rsx
|
||||
|
||||
//Reset deref count
|
||||
surface->deref_count = 0;
|
||||
surface->frame_tag = 0;
|
||||
}
|
||||
|
||||
static void prepare_rtt_for_sampling(vk::command_buffer* pcmd, vk::render_target *surface)
|
||||
@@ -238,6 +248,7 @@ namespace rsx
|
||||
|
||||
//Reset deref count
|
||||
surface->deref_count = 0;
|
||||
surface->frame_tag = 0;
|
||||
}
|
||||
|
||||
static void prepare_ds_for_sampling(vk::command_buffer* pcmd, vk::render_target *surface)
|
||||
@@ -261,6 +272,13 @@ namespace rsx
|
||||
ds->old_contents = old_surface;
|
||||
}
|
||||
|
||||
static
|
||||
void notify_surface_invalidated(const std::unique_ptr<vk::render_target> &surface)
|
||||
{
|
||||
surface->frame_tag = vk::get_current_frame_id();
|
||||
if (!surface->frame_tag) surface->frame_tag = 1;
|
||||
}
|
||||
|
||||
static bool rtt_has_format_width_height(const std::unique_ptr<vk::render_target> &rtt, surface_color_format format, size_t width, size_t height, bool check_refs=false)
|
||||
{
|
||||
if (check_refs && rtt->deref_count == 0) //Surface may still have read refs from data 'copy'
|
||||
@@ -337,9 +355,13 @@ namespace rsx
|
||||
|
||||
void free_invalidated()
|
||||
{
|
||||
invalidated_resources.remove_if([](std::unique_ptr<vk::render_target> &rtt)
|
||||
const u64 last_finished_frame = vk::get_last_completed_frame_id();
|
||||
invalidated_resources.remove_if([&](std::unique_ptr<vk::render_target> &rtt)
|
||||
{
|
||||
if (rtt->deref_count >= 2) return true;
|
||||
verify(HERE), rtt->frame_tag != 0;
|
||||
|
||||
if (rtt->deref_count >= 2 && rtt->frame_tag < last_finished_frame)
|
||||
return true;
|
||||
|
||||
rtt->deref_count++;
|
||||
return false;
|
||||
|
||||
@@ -20,6 +20,7 @@ namespace vk
|
||||
//DMA relevant data
|
||||
VkFence dma_fence = VK_NULL_HANDLE;
|
||||
bool synchronized = false;
|
||||
bool flushed = false;
|
||||
u64 sync_timestamp = 0;
|
||||
u64 last_use_timestamp = 0;
|
||||
vk::render_device* m_device = nullptr;
|
||||
@@ -46,10 +47,17 @@ namespace vk
|
||||
this->depth = depth;
|
||||
this->mipmaps = mipmaps;
|
||||
|
||||
uploaded_image_view.reset(view);
|
||||
vram_texture = image;
|
||||
if (managed)
|
||||
{
|
||||
managed_texture.reset(image);
|
||||
uploaded_image_view.reset(view);
|
||||
}
|
||||
else
|
||||
{
|
||||
verify(HERE), uploaded_image_view.get() == nullptr;
|
||||
}
|
||||
|
||||
if (managed) managed_texture.reset(image);
|
||||
vram_texture = image;
|
||||
|
||||
//TODO: Properly compute these values
|
||||
if (rsx_pitch > 0)
|
||||
@@ -62,6 +70,7 @@ namespace vk
|
||||
//Even if we are managing the same vram section, we cannot guarantee contents are static
|
||||
//The create method is only invoked when a new mangaged session is required
|
||||
synchronized = false;
|
||||
flushed = false;
|
||||
sync_timestamp = 0ull;
|
||||
last_use_timestamp = get_system_time();
|
||||
}
|
||||
@@ -80,6 +89,12 @@ namespace vk
|
||||
}
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
vram_texture = nullptr;
|
||||
release_dma_resources();
|
||||
}
|
||||
|
||||
bool exists() const
|
||||
{
|
||||
return (vram_texture != nullptr);
|
||||
@@ -97,7 +112,10 @@ namespace vk
|
||||
|
||||
vk::image_view* get_raw_view()
|
||||
{
|
||||
return uploaded_image_view.get();
|
||||
if (context != rsx::texture_upload_context::framebuffer_storage)
|
||||
return uploaded_image_view.get();
|
||||
else
|
||||
return static_cast<vk::render_target*>(vram_texture)->get_view();
|
||||
}
|
||||
|
||||
vk::image* get_raw_texture()
|
||||
@@ -149,15 +167,27 @@ namespace vk
|
||||
const u16 internal_width = std::min(width, rsx::apply_resolution_scale(width, true));
|
||||
const u16 internal_height = std::min(height, rsx::apply_resolution_scale(height, true));
|
||||
|
||||
VkImageAspectFlags aspect_flag = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
switch (vram_texture->info.format)
|
||||
{
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
aspect_flag = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
break;
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
aspect_flag = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
VkBufferImageCopy copyRegion = {};
|
||||
copyRegion.bufferOffset = 0;
|
||||
copyRegion.bufferRowLength = internal_width;
|
||||
copyRegion.bufferImageHeight = internal_height;
|
||||
copyRegion.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
|
||||
copyRegion.imageSubresource = {aspect_flag, 0, 0, 1};
|
||||
copyRegion.imageOffset = {};
|
||||
copyRegion.imageExtent = {internal_width, internal_height, 1};
|
||||
|
||||
VkImageSubresourceRange subresource_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
|
||||
VkImageSubresourceRange subresource_range = { aspect_flag & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 };
|
||||
|
||||
VkImageLayout layout = vram_texture->current_layout;
|
||||
change_image_layout(cmd, vram_texture, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range);
|
||||
@@ -173,13 +203,16 @@ namespace vk
|
||||
CHECK_RESULT(vkWaitForFences(*m_device, 1, &dma_fence, VK_TRUE, UINT64_MAX));
|
||||
CHECK_RESULT(vkResetCommandBuffer(cmd, 0));
|
||||
CHECK_RESULT(vkResetFences(*m_device, 1, &dma_fence));
|
||||
|
||||
if (cmd.access_hint != vk::command_buffer::access_type_hint::all)
|
||||
cmd.begin();
|
||||
}
|
||||
|
||||
synchronized = true;
|
||||
sync_timestamp = get_system_time();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T, bool swapped>
|
||||
void do_memory_transfer(void *pixels_dst, const void *pixels_src)
|
||||
{
|
||||
if (sizeof(T) == 1)
|
||||
@@ -187,17 +220,30 @@ namespace vk
|
||||
else
|
||||
{
|
||||
const u32 block_size = width * height;
|
||||
|
||||
auto typed_dst = (be_t<T> *)pixels_dst;
|
||||
auto typed_src = (T *)pixels_src;
|
||||
|
||||
for (u32 px = 0; px < block_size; ++px)
|
||||
typed_dst[px] = typed_src[px];
|
||||
if (swapped)
|
||||
{
|
||||
auto typed_dst = (be_t<T> *)pixels_dst;
|
||||
auto typed_src = (T *)pixels_src;
|
||||
|
||||
for (u32 px = 0; px < block_size; ++px)
|
||||
typed_dst[px] = typed_src[px];
|
||||
}
|
||||
else
|
||||
{
|
||||
auto typed_dst = (T *)pixels_dst;
|
||||
auto typed_src = (T *)pixels_src;
|
||||
|
||||
for (u32 px = 0; px < block_size; ++px)
|
||||
typed_dst[px] = typed_src[px];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool flush(vk::render_device& dev, vk::command_buffer& cmd, vk::memory_type_mapping& memory_types, VkQueue submit_queue)
|
||||
{
|
||||
if (flushed) return true;
|
||||
|
||||
if (m_device == nullptr)
|
||||
m_device = &dev;
|
||||
|
||||
@@ -211,31 +257,54 @@ namespace vk
|
||||
result = false;
|
||||
}
|
||||
|
||||
protect(utils::protection::rw);
|
||||
flushed = true;
|
||||
|
||||
void* pixels_src = dma_buffer->map(0, cpu_address_range);
|
||||
void* pixels_dst = vm::base(cpu_address_base);
|
||||
|
||||
const u8 bpp = real_pitch / width;
|
||||
|
||||
//We have to do our own byte swapping since the driver doesnt do it for us
|
||||
bool swap_bytes = false;
|
||||
switch (vram_texture->info.format)
|
||||
{
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
//TODO: Hardware tests to determine correct memory layout
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||
case VK_FORMAT_R32G32B32A32_SFLOAT:
|
||||
case VK_FORMAT_R32_SFLOAT:
|
||||
swap_bytes = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (real_pitch == rsx_pitch)
|
||||
{
|
||||
//We have to do our own byte swapping since the driver doesnt do it for us
|
||||
switch (bpp)
|
||||
{
|
||||
default:
|
||||
LOG_ERROR(RSX, "Invalid bpp %d", bpp);
|
||||
case 1:
|
||||
do_memory_transfer<u8>(pixels_dst, pixels_src);
|
||||
do_memory_transfer<u8, false>(pixels_dst, pixels_src);
|
||||
break;
|
||||
case 2:
|
||||
do_memory_transfer<u16>(pixels_dst, pixels_src);
|
||||
if (swap_bytes)
|
||||
do_memory_transfer<u16, true>(pixels_dst, pixels_src);
|
||||
else
|
||||
do_memory_transfer<u16, false>(pixels_dst, pixels_src);
|
||||
break;
|
||||
case 4:
|
||||
do_memory_transfer<u32>(pixels_dst, pixels_src);
|
||||
if (swap_bytes)
|
||||
do_memory_transfer<u32, true>(pixels_dst, pixels_src);
|
||||
else
|
||||
do_memory_transfer<u32, false>(pixels_dst, pixels_src);
|
||||
break;
|
||||
case 8:
|
||||
do_memory_transfer<u64>(pixels_dst, pixels_src);
|
||||
if (swap_bytes)
|
||||
do_memory_transfer<u64, true>(pixels_dst, pixels_src);
|
||||
else
|
||||
do_memory_transfer<u64, false>(pixels_dst, pixels_src);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -245,7 +314,7 @@ namespace vk
|
||||
//usually we can just get away with nearest filtering
|
||||
const u8 samples = rsx_pitch / real_pitch;
|
||||
|
||||
rsx::scale_image_nearest(pixels_dst, pixels_src, width, height, rsx_pitch, real_pitch, bpp, samples, true);
|
||||
rsx::scale_image_nearest(pixels_dst, pixels_src, width, height, rsx_pitch, real_pitch, bpp, samples, swap_bytes);
|
||||
}
|
||||
|
||||
dma_buffer->unmap();
|
||||
@@ -269,6 +338,19 @@ namespace vk
|
||||
return vram_texture->info.format == tex->info.format;
|
||||
}
|
||||
|
||||
bool is_depth_texture() const
|
||||
{
|
||||
switch (vram_texture->info.format)
|
||||
{
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
u64 get_sync_timestamp() const
|
||||
{
|
||||
return sync_timestamp;
|
||||
@@ -280,6 +362,10 @@ namespace vk
|
||||
std::unique_ptr<vk::image_view> view;
|
||||
std::unique_ptr<vk::image> img;
|
||||
|
||||
//Memory held by this temp storage object
|
||||
u32 block_size = 0;
|
||||
|
||||
//Frame id tag
|
||||
const u64 frame_tag = vk::get_current_frame_id();
|
||||
|
||||
discarded_storage(std::unique_ptr<vk::image_view>& _view)
|
||||
@@ -302,6 +388,7 @@ namespace vk
|
||||
{
|
||||
view = std::move(tex.get_view());
|
||||
img = std::move(tex.get_texture());
|
||||
block_size = tex.get_section_size();
|
||||
}
|
||||
|
||||
const bool test(u64 ref_frame) const
|
||||
@@ -323,7 +410,8 @@ namespace vk
|
||||
|
||||
//Stuff that has been dereferenced goes into these
|
||||
std::list<discarded_storage> m_discardable_storage;
|
||||
|
||||
std::atomic<u32> m_discarded_memory_size = { 0 };
|
||||
|
||||
void purge_cache()
|
||||
{
|
||||
for (auto &address_range : m_cache)
|
||||
@@ -347,17 +435,20 @@ namespace vk
|
||||
|
||||
m_discardable_storage.clear();
|
||||
m_unreleased_texture_objects = 0;
|
||||
m_texture_memory_in_use = 0;
|
||||
m_discarded_memory_size = 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void free_texture_section(cached_texture_section& tex) override
|
||||
{
|
||||
m_discarded_memory_size += tex.get_section_size();
|
||||
m_discardable_storage.push_back(tex);
|
||||
tex.release_dma_resources();
|
||||
tex.destroy();
|
||||
}
|
||||
|
||||
vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image* source, u32 /*gcm_format*/, u16 x, u16 y, u16 w, u16 h) override
|
||||
vk::image_view* create_temporary_subresource_view_impl(vk::command_buffer& cmd, vk::image* source, VkImageType image_type, VkImageViewType view_type, u16 x, u16 y, u16 w, u16 h)
|
||||
{
|
||||
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
@@ -378,13 +469,13 @@ namespace vk
|
||||
std::unique_ptr<vk::image_view> view;
|
||||
|
||||
image.reset(new vk::image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
source->info.imageType,
|
||||
image_type,
|
||||
source->info.format,
|
||||
w, h, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, source->info.flags));
|
||||
|
||||
VkImageSubresourceRange view_range = { aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 };
|
||||
view.reset(new vk::image_view(*vk::get_current_renderer(), image->value, VK_IMAGE_VIEW_TYPE_2D, source->info.format, source->native_component_map, view_range));
|
||||
view.reset(new vk::image_view(*vk::get_current_renderer(), image->value, view_type, source->info.format, source->native_component_map, view_range));
|
||||
|
||||
VkImageLayout old_src_layout = source->current_layout;
|
||||
|
||||
@@ -393,7 +484,7 @@ namespace vk
|
||||
|
||||
VkImageCopy copy_rgn;
|
||||
copy_rgn.srcOffset = { (s32)x, (s32)y, 0 };
|
||||
copy_rgn.dstOffset = { (s32)x, (s32)y, 0 };
|
||||
copy_rgn.dstOffset = { (s32)0, (s32)0, 0 };
|
||||
copy_rgn.dstSubresource = { aspect, 0, 0, 1 };
|
||||
copy_rgn.srcSubresource = { aspect, 0, 0, 1 };
|
||||
copy_rgn.extent = { w, h, 1 };
|
||||
@@ -402,15 +493,96 @@ namespace vk
|
||||
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range);
|
||||
vk::change_image_layout(cmd, source, old_src_layout, subresource_range);
|
||||
|
||||
const u32 resource_memory = w * h * 4; //Rough approximate
|
||||
m_discardable_storage.push_back({ image, view });
|
||||
m_discardable_storage.back().block_size = resource_memory;
|
||||
m_discarded_memory_size += resource_memory;
|
||||
|
||||
return m_discardable_storage.back().view.get();
|
||||
}
|
||||
|
||||
vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image* source, u32 /*gcm_format*/, u16 x, u16 y, u16 w, u16 h) override
|
||||
{
|
||||
return create_temporary_subresource_view_impl(cmd, source, source->info.imageType, VK_IMAGE_VIEW_TYPE_2D, x, y, w, h);
|
||||
}
|
||||
|
||||
vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image** source, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override
|
||||
{
|
||||
return create_temporary_subresource_view(cmd, *source, gcm_format, x, y, w, h);
|
||||
}
|
||||
|
||||
vk::image_view* generate_cubemap_from_images(vk::command_buffer& cmd, const u32 gcm_format, u16 size, std::array<vk::image*, 6>& sources) override
|
||||
{
|
||||
std::unique_ptr<vk::image> image;
|
||||
std::unique_ptr<vk::image_view> view;
|
||||
|
||||
image.reset(new vk::image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||
VK_IMAGE_TYPE_2D,
|
||||
vk::get_compatible_sampler_format(gcm_format),
|
||||
size, size, 1, 1, 6, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT));
|
||||
|
||||
VkImageSubresourceRange subresource_range = {};
|
||||
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
|
||||
for (u32 n = 0; n < 6; ++n)
|
||||
{
|
||||
if (!view)
|
||||
{
|
||||
switch (sources[0]->info.format)
|
||||
{
|
||||
case VK_FORMAT_D16_UNORM:
|
||||
aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||
break;
|
||||
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||
aspect = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||
break;
|
||||
}
|
||||
|
||||
VkImageSubresourceRange view_range = { aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 6 };
|
||||
view.reset(new vk::image_view(*vk::get_current_renderer(), image->value, VK_IMAGE_VIEW_TYPE_CUBE, image->info.format, image->native_component_map, view_range));
|
||||
subresource_range = view_range;
|
||||
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range);
|
||||
subresource_range.layerCount = 1;
|
||||
}
|
||||
|
||||
if (sources[n])
|
||||
{
|
||||
VkImageLayout old_src_layout = sources[n]->current_layout;
|
||||
vk::change_image_layout(cmd, sources[n], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range);
|
||||
|
||||
VkImageCopy copy_rgn;
|
||||
copy_rgn.srcOffset = { 0, 0, 0 };
|
||||
copy_rgn.dstOffset = { 0, 0, 0 };
|
||||
copy_rgn.dstSubresource = { aspect, 0, n, 1 };
|
||||
copy_rgn.srcSubresource = { aspect, 0, 0, 1 };
|
||||
copy_rgn.extent = { size, size, 1 };
|
||||
|
||||
vkCmdCopyImage(cmd, sources[n]->value, sources[n]->current_layout, image->value, image->current_layout, 1, ©_rgn);
|
||||
vk::change_image_layout(cmd, sources[n], old_src_layout, subresource_range);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Clear to black
|
||||
VkClearColorValue clear_color{};
|
||||
auto range = subresource_range;
|
||||
range.baseArrayLayer = n;
|
||||
vkCmdClearColorImage(cmd, image->value, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &range);
|
||||
}
|
||||
}
|
||||
|
||||
subresource_range.layerCount = 6;
|
||||
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range);
|
||||
|
||||
const u32 resource_memory = size * size * 6 * 4; //Rough approximate
|
||||
m_discardable_storage.push_back({ image, view });
|
||||
m_discardable_storage.back().block_size = resource_memory;
|
||||
m_discarded_memory_size += resource_memory;
|
||||
|
||||
return m_discardable_storage.back().view.get();
|
||||
}
|
||||
|
||||
cached_texture_section* create_new_texture(vk::command_buffer& cmd, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, const u32 gcm_format,
|
||||
const rsx::texture_upload_context context, const rsx::texture_dimension_extended type, const rsx::texture_create_flags flags,
|
||||
std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
|
||||
@@ -523,10 +695,14 @@ namespace vk
|
||||
region.create(width, height, section_depth, mipmaps, view, image);
|
||||
region.set_dirty(false);
|
||||
region.set_context(context);
|
||||
region.set_image_type(type);
|
||||
|
||||
//Its not necessary to lock blit dst textures as they are just reused as necessary
|
||||
if (context != rsx::texture_upload_context::blit_engine_dst || g_cfg.video.strict_rendering_mode)
|
||||
{
|
||||
region.protect(utils::protection::ro);
|
||||
update_cache_tag();
|
||||
}
|
||||
|
||||
read_only_range = region.get_min_max(read_only_range);
|
||||
return ®ion;
|
||||
@@ -660,13 +836,30 @@ namespace vk
|
||||
|
||||
void on_frame_end() override
|
||||
{
|
||||
if (m_unreleased_texture_objects >= m_max_zombie_objects)
|
||||
if (m_unreleased_texture_objects >= m_max_zombie_objects ||
|
||||
m_discarded_memory_size > 0x4000000) //If already holding over 64M in discardable memory, be frugal with memory resources
|
||||
{
|
||||
purge_dirty();
|
||||
}
|
||||
|
||||
const u64 last_complete_frame = vk::get_last_completed_frame_id();
|
||||
m_discardable_storage.remove_if([&](const discarded_storage& o) {return o.test(last_complete_frame);});
|
||||
m_discardable_storage.remove_if([&](const discarded_storage& o)
|
||||
{
|
||||
if (o.test(last_complete_frame))
|
||||
{
|
||||
m_discarded_memory_size -= o.block_size;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
m_temporary_subresource_cache.clear();
|
||||
}
|
||||
|
||||
template<typename RsxTextureType>
|
||||
sampled_image_descriptor _upload_texture(vk::command_buffer& cmd, RsxTextureType& tex, rsx::vk_render_targets& m_rtts)
|
||||
{
|
||||
return upload_texture(cmd, tex, m_rtts, *m_device, cmd, m_memory_types, const_cast<const VkQueue>(m_submit_queue));
|
||||
}
|
||||
|
||||
bool blit(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate, rsx::vk_render_targets& m_rtts, vk::command_buffer& cmd)
|
||||
@@ -707,12 +900,22 @@ namespace vk
|
||||
}
|
||||
helper(&cmd);
|
||||
|
||||
return upload_scaled_image(src, dst, interpolate, cmd, m_rtts, helper, *m_device, cmd, m_memory_types, m_submit_queue);
|
||||
return upload_scaled_image(src, dst, interpolate, cmd, m_rtts, helper, *m_device, cmd, m_memory_types, const_cast<const VkQueue>(m_submit_queue));
|
||||
}
|
||||
|
||||
const u32 get_unreleased_textures_count() const override
|
||||
{
|
||||
return std::max(m_unreleased_texture_objects, 0) + (u32)m_discardable_storage.size();
|
||||
return m_unreleased_texture_objects + (u32)m_discardable_storage.size();
|
||||
}
|
||||
|
||||
const u32 get_texture_memory_in_use() const override
|
||||
{
|
||||
return m_texture_memory_in_use;
|
||||
}
|
||||
|
||||
const u32 get_temporary_memory_in_use()
|
||||
{
|
||||
return m_discarded_memory_size;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -141,18 +141,43 @@ namespace
|
||||
VkDeviceSize offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size);
|
||||
void* buf = m_index_buffer_ring_info.map(offset_in_index_buffer, upload_size);
|
||||
|
||||
gsl::span<gsl::byte> dst;
|
||||
std::vector<gsl::byte> tmp;
|
||||
if (rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart())
|
||||
{
|
||||
tmp.resize(upload_size);
|
||||
dst = tmp;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = gsl::span<gsl::byte>(static_cast<gsl::byte*>(buf), upload_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload index (and expands it if primitive type is not natively supported).
|
||||
*/
|
||||
u32 min_index, max_index;
|
||||
std::tie(min_index, max_index) = write_index_array_data_to_buffer(
|
||||
gsl::span<gsl::byte>(static_cast<gsl::byte*>(buf), index_count * type_size),
|
||||
std::tie(min_index, max_index, index_count) = write_index_array_data_to_buffer(
|
||||
dst,
|
||||
command.raw_index_buffer, index_type,
|
||||
rsx::method_registers.current_draw_clause.primitive,
|
||||
rsx::method_registers.restart_index_enabled(),
|
||||
rsx::method_registers.restart_index(), command.ranges_to_fetch_in_index_buffer,
|
||||
[](auto prim) { return !vk::is_primitive_native(prim); });
|
||||
|
||||
if (rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart())
|
||||
{
|
||||
//Emulate primitive restart by breaking up the draw calls
|
||||
rsx::method_registers.current_draw_clause.alternate_first_count_commands.resize(0);
|
||||
|
||||
if (index_type == rsx::index_array_type::u16)
|
||||
rsx::split_index_list(reinterpret_cast<u16*>(tmp.data()), index_count, (u16)UINT16_MAX, rsx::method_registers.current_draw_clause.alternate_first_count_commands);
|
||||
else
|
||||
rsx::split_index_list(reinterpret_cast<u32*>(tmp.data()), index_count, (u32)UINT32_MAX, rsx::method_registers.current_draw_clause.alternate_first_count_commands);
|
||||
|
||||
memcpy(buf, tmp.data(), tmp.size());
|
||||
}
|
||||
|
||||
m_index_buffer_ring_info.unmap();
|
||||
|
||||
std::optional<std::tuple<VkDeviceSize, VkIndexType>> index_info =
|
||||
@@ -212,7 +237,8 @@ VKGSRender::upload_vertex_data()
|
||||
auto required = calculate_memory_requirements(m_vertex_layout, vertex_count);
|
||||
size_t persistent_offset = UINT64_MAX, volatile_offset = UINT64_MAX;
|
||||
|
||||
VkBufferView persistent_view = VK_NULL_HANDLE, volatile_view = VK_NULL_HANDLE;
|
||||
m_persistent_attribute_storage = VK_NULL_HANDLE;
|
||||
m_volatile_attribute_storage = VK_NULL_HANDLE;
|
||||
|
||||
if (required.first > 0)
|
||||
{
|
||||
@@ -252,11 +278,11 @@ VKGSRender::upload_vertex_data()
|
||||
}
|
||||
}
|
||||
|
||||
persistent_view = m_current_frame->buffer_views_to_clean.back()->value;
|
||||
m_persistent_attribute_storage = m_current_frame->buffer_views_to_clean.back()->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
persistent_view = null_buffer_view->value;
|
||||
m_persistent_attribute_storage = null_buffer_view->value;
|
||||
}
|
||||
|
||||
if (required.second > 0)
|
||||
@@ -265,16 +291,13 @@ VKGSRender::upload_vertex_data()
|
||||
m_current_frame->buffer_views_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device,
|
||||
m_attrib_ring_info.heap->value, VK_FORMAT_R8_UINT, volatile_offset, required.second));
|
||||
|
||||
volatile_view = m_current_frame->buffer_views_to_clean.back()->value;
|
||||
m_volatile_attribute_storage = m_current_frame->buffer_views_to_clean.back()->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
volatile_view = null_buffer_view->value;
|
||||
m_volatile_attribute_storage = null_buffer_view->value;
|
||||
}
|
||||
|
||||
m_program->bind_uniform(persistent_view, "persistent_input_stream", m_current_frame->descriptor_set);
|
||||
m_program->bind_uniform(volatile_view, "volatile_input_stream", m_current_frame->descriptor_set);
|
||||
|
||||
//Write all the data once if possible
|
||||
if (required.first && required.second && volatile_offset > persistent_offset)
|
||||
{
|
||||
|
||||
@@ -15,10 +15,9 @@ std::string VKVertexDecompilerThread::getIntTypeName(size_t elementCount)
|
||||
return "ivec4";
|
||||
}
|
||||
|
||||
|
||||
std::string VKVertexDecompilerThread::getFunction(FUNCTION f)
|
||||
{
|
||||
return vk::getFunctionImpl(f);
|
||||
return glsl::getFunctionImpl(f);
|
||||
}
|
||||
|
||||
std::string VKVertexDecompilerThread::compareFunction(COMPARE f, const std::string &Op0, const std::string &Op1)
|
||||
@@ -339,7 +338,7 @@ void VKVertexProgram::Decompile(const RSXVertexProgram& prog)
|
||||
void VKVertexProgram::Compile()
|
||||
{
|
||||
fs::create_path(fs::get_config_dir() + "/shaderlog");
|
||||
fs::file(fs::get_config_dir() + "shaderlog/VertexProgram.spirv", fs::rewrite).write(shader);
|
||||
fs::file(fs::get_config_dir() + "shaderlog/VertexProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader);
|
||||
|
||||
std::vector<u32> spir_v;
|
||||
if (!vk::compile_glsl_to_spv(shader, glsl::glsl_vertex_program, spir_v))
|
||||
@@ -354,8 +353,6 @@ void VKVertexProgram::Compile()
|
||||
|
||||
VkDevice dev = (VkDevice)*vk::get_current_renderer();
|
||||
vkCreateShaderModule(dev, &vs_info, nullptr, &handle);
|
||||
|
||||
id = UINT32_MAX;
|
||||
}
|
||||
|
||||
void VKVertexProgram::Delete()
|
||||
|
||||
+26
-26
@@ -157,7 +157,7 @@ namespace rsx
|
||||
case comparison_function::greater_or_equal: return "Greater_equal";
|
||||
case comparison_function::always: return "Always";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(stencil_op op)
|
||||
@@ -173,7 +173,7 @@ namespace rsx
|
||||
case stencil_op::decr_wrap: return "Decr_wrap";
|
||||
case stencil_op::invert: return "Invert";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(fog_mode op)
|
||||
@@ -187,7 +187,7 @@ namespace rsx
|
||||
case fog_mode::linear: return "linear";
|
||||
case fog_mode::linear_abs: return "linear(abs)";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(logic_op op)
|
||||
@@ -211,7 +211,7 @@ namespace rsx
|
||||
case logic_op::logic_or_inverted: return "Or_inverted";
|
||||
case logic_op::logic_nand: return "Nand";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(front_face op)
|
||||
@@ -221,7 +221,7 @@ namespace rsx
|
||||
case front_face::ccw: return "counter clock wise";
|
||||
case front_face::cw: return "clock wise";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(cull_face op)
|
||||
@@ -232,7 +232,7 @@ namespace rsx
|
||||
case cull_face::front: return "front";
|
||||
case cull_face::front_and_back: return "front and back";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(surface_target target)
|
||||
@@ -246,7 +246,7 @@ namespace rsx
|
||||
case surface_target::surfaces_a_b_c: return "surfaces A, B and C";
|
||||
case surface_target::surfaces_a_b_c_d: return "surfaces A,B, C and D";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(primitive_type draw_mode)
|
||||
@@ -265,7 +265,7 @@ namespace rsx
|
||||
case primitive_type::quad_strip: return "Quad_strip";
|
||||
case primitive_type::polygon: return "Polygon";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(blit_engine::transfer_operation op)
|
||||
@@ -279,7 +279,7 @@ namespace rsx
|
||||
case blit_engine::transfer_operation::srccopy_and: return "srccopy_and";
|
||||
case blit_engine::transfer_operation::srccopy_premult: return "srccopy_premult";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(blit_engine::transfer_source_format op)
|
||||
@@ -300,7 +300,7 @@ namespace rsx
|
||||
case blit_engine::transfer_source_format::y8: return "y8";
|
||||
case blit_engine::transfer_source_format::yb8cr8ya8cb8: return "yb8cr8ya8cb8";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(blit_engine::context_surface op)
|
||||
@@ -310,7 +310,7 @@ namespace rsx
|
||||
case blit_engine::context_surface::surface2d: return "surface 2d";
|
||||
case blit_engine::context_surface::swizzle2d: return "swizzle 2d";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(blit_engine::transfer_destination_format op)
|
||||
@@ -321,7 +321,7 @@ namespace rsx
|
||||
case blit_engine::transfer_destination_format::r5g6b5: return "r5g6b5";
|
||||
case blit_engine::transfer_destination_format::y32: return "y32";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
|
||||
@@ -338,7 +338,7 @@ namespace rsx
|
||||
case blend_equation::reverse_add_signed: return "Reverse_add_signed";
|
||||
case blend_equation::reverse_substract_signed: return "Reverse_substract_signed";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(blend_factor factor)
|
||||
@@ -361,7 +361,7 @@ namespace rsx
|
||||
case blend_factor::constant_alpha: return "const.a";
|
||||
case blend_factor::one_minus_constant_alpha: return "(1 - const.a)";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(window_origin origin)
|
||||
@@ -371,7 +371,7 @@ namespace rsx
|
||||
case window_origin::bottom: return "bottom";
|
||||
case window_origin::top: return "top";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(window_pixel_center in)
|
||||
@@ -381,7 +381,7 @@ namespace rsx
|
||||
case window_pixel_center::half: return "half";
|
||||
case window_pixel_center::integer: return "integer";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(user_clip_plane_op op)
|
||||
@@ -392,7 +392,7 @@ namespace rsx
|
||||
case user_clip_plane_op::greater_or_equal: return "greater or equal";
|
||||
case user_clip_plane_op::less_than: return "less than";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
|
||||
@@ -404,7 +404,7 @@ namespace rsx
|
||||
case surface_depth_format::z16: return "CELL_GCM_SURFACE_Z16";
|
||||
case surface_depth_format::z24s8: return "CELL_GCM_SURFACE_Z24S8";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(surface_antialiasing format)
|
||||
@@ -416,7 +416,7 @@ namespace rsx
|
||||
case surface_antialiasing::square_centered_4_samples: return "4 samples square centered";
|
||||
case surface_antialiasing::square_rotated_4_samples: return "4 samples diagonal rotated";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(surface_color_format format)
|
||||
@@ -438,7 +438,7 @@ namespace rsx
|
||||
case surface_color_format::x8b8g8r8_o8b8g8r8: return "CELL_GCM_SURFACE_X8B8G8R8_O8B8G8R8";
|
||||
case surface_color_format::a8b8g8r8: return "CELL_GCM_SURFACE_A8B8G8R8";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(index_array_type arg)
|
||||
@@ -448,7 +448,7 @@ namespace rsx
|
||||
case index_array_type::u16: return "unsigned short";
|
||||
case index_array_type::u32: return "unsigned int";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(blit_engine::context_dma op)
|
||||
@@ -459,7 +459,7 @@ namespace rsx
|
||||
case blit_engine::context_dma::to_memory_get_report: return "to memory get report";
|
||||
case blit_engine::context_dma::memory_host_buffer: return "memory host buffer";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(blit_engine::transfer_origin op)
|
||||
@@ -469,7 +469,7 @@ namespace rsx
|
||||
case blit_engine::transfer_origin::center: return "center";
|
||||
case blit_engine::transfer_origin::corner: return "corner";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(blit_engine::transfer_interpolator op)
|
||||
@@ -479,7 +479,7 @@ namespace rsx
|
||||
case blit_engine::transfer_interpolator::foh: return "foh";
|
||||
case blit_engine::transfer_interpolator::zoh: return "zoh";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(shading_mode op)
|
||||
@@ -489,7 +489,7 @@ namespace rsx
|
||||
case shading_mode::flat: return "flat";
|
||||
case shading_mode::smooth: return "smooth";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
std::string to_string(polygon_mode op)
|
||||
@@ -500,7 +500,7 @@ namespace rsx
|
||||
case polygon_mode::line: return "line";
|
||||
case polygon_mode::point: return "point";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
|
||||
} // end namespace rsx
|
||||
|
||||
@@ -238,6 +238,11 @@ namespace rsx
|
||||
|
||||
return std::make_pair(min, max);
|
||||
}
|
||||
|
||||
utils::protection get_protection() const
|
||||
{
|
||||
return protection;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename pipeline_storage_type, typename backend_storage>
|
||||
@@ -328,12 +333,16 @@ namespace rsx
|
||||
dlg->Create("Preloading cached shaders from disk.\nPlease wait...");
|
||||
});
|
||||
|
||||
const auto prefix_length = version_prefix.length();
|
||||
u32 processed = 0;
|
||||
while (root.read(tmp) && !Emu.IsStopped())
|
||||
{
|
||||
if (tmp.name == "." || tmp.name == "..")
|
||||
continue;
|
||||
|
||||
if (tmp.name.compare(0, prefix_length, version_prefix) != 0)
|
||||
continue;
|
||||
|
||||
std::vector<u8> bytes;
|
||||
fs::file f(directory_path + "/" + tmp.name);
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "Utilities/types.h"
|
||||
#include "Utilities/BitField.h"
|
||||
#include "Utilities/StrFmt.h"
|
||||
#include <tuple>
|
||||
#include "gcm_enums.h"
|
||||
#pragma warning(disable:4503)
|
||||
@@ -27,7 +28,7 @@ namespace
|
||||
case rsx::vertex_base_type::cmp: return "CMP";
|
||||
case rsx::vertex_base_type::ub256: return "Unsigned byte unormalized";
|
||||
}
|
||||
throw;
|
||||
fmt::throw_exception("Unexpected enum found" HERE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -469,6 +469,15 @@ namespace rsx
|
||||
rsx->m_textures_dirty[index] = true;
|
||||
}
|
||||
};
|
||||
|
||||
template<u32 index>
|
||||
struct set_vertex_texture_dirty_bit
|
||||
{
|
||||
static void impl(thread* rsx, u32 _reg, u32 arg)
|
||||
{
|
||||
rsx->m_vertex_textures_dirty[index] = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace nv308a
|
||||
@@ -486,7 +495,8 @@ namespace rsx
|
||||
LOG_ERROR(RSX, "%s: y is not null (0x%x)", __FUNCTION__, y);
|
||||
}
|
||||
|
||||
u32 address = get_address(method_registers.blit_engine_output_offset_nv3062() + (x << 2) + index * 4, method_registers.blit_engine_output_location_nv3062());
|
||||
const u32 pixel_offset = (method_registers.blit_engine_output_pitch_nv3062() * y) + (x << 2);
|
||||
u32 address = get_address(method_registers.blit_engine_output_offset_nv3062() + pixel_offset + index * 4, method_registers.blit_engine_output_location_nv3062());
|
||||
vm::ps3::write32(address, arg);
|
||||
}
|
||||
};
|
||||
@@ -626,6 +636,12 @@ namespace rsx
|
||||
u32 convert_w = (u32)(scale_x * in_w);
|
||||
u32 convert_h = (u32)(scale_y * in_h);
|
||||
|
||||
if (convert_w == 0 || convert_h == 0)
|
||||
{
|
||||
LOG_ERROR(RSX, "NV3089_IMAGE_IN: Invalid dimensions or scaling factor. Request ignored");
|
||||
return;
|
||||
}
|
||||
|
||||
u32 slice_h = clip_h;
|
||||
blit_src_info src_info = {};
|
||||
blit_dst_info dst_info = {};
|
||||
@@ -1538,6 +1554,14 @@ namespace rsx
|
||||
bind_range<NV4097_SET_TEXTURE_FILTER, 8, 16, nv4097::set_texture_dirty_bit>();
|
||||
bind_range<NV4097_SET_TEXTURE_IMAGE_RECT, 8, 16, nv4097::set_texture_dirty_bit>();
|
||||
bind_range<NV4097_SET_TEXTURE_BORDER_COLOR, 8, 16, nv4097::set_texture_dirty_bit>();
|
||||
bind_range<NV4097_SET_VERTEX_TEXTURE_OFFSET, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
|
||||
bind_range<NV4097_SET_VERTEX_TEXTURE_FORMAT, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
|
||||
bind_range<NV4097_SET_VERTEX_TEXTURE_ADDRESS, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
|
||||
bind_range<NV4097_SET_VERTEX_TEXTURE_CONTROL0, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
|
||||
bind_range<NV4097_SET_VERTEX_TEXTURE_CONTROL3, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
|
||||
bind_range<NV4097_SET_VERTEX_TEXTURE_FILTER, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
|
||||
bind_range<NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
|
||||
bind_range<NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
|
||||
bind<NV4097_SET_RENDER_ENABLE, nv4097::set_render_mode>();
|
||||
bind<NV4097_SET_ZCULL_EN, nv4097::set_zcull_render_enable>();
|
||||
bind<NV4097_SET_ZCULL_STATS_ENABLE, nv4097::set_zcull_stats_enable>();
|
||||
|
||||
@@ -38,6 +38,11 @@ namespace rsx
|
||||
*/
|
||||
std::vector<std::pair<u32, u32> > first_count_commands;
|
||||
|
||||
/**
|
||||
* Optionally split first-count pairs for disjoint range rendering. Valid when emulating primitive restart
|
||||
*/
|
||||
std::vector<std::pair<u32, u32> > alternate_first_count_commands;
|
||||
|
||||
/**
|
||||
* Returns how many vertex or index will be consumed by the draw clause.
|
||||
*/
|
||||
@@ -1166,6 +1171,26 @@ namespace rsx
|
||||
{
|
||||
return registers[NV4097_SET_TRANSFORM_BRANCH_BITS];
|
||||
}
|
||||
|
||||
u16 msaa_sample_mask()
|
||||
{
|
||||
return decode<NV4097_SET_ANTI_ALIASING_CONTROL>().msaa_sample_mask();
|
||||
}
|
||||
|
||||
bool msaa_enabled()
|
||||
{
|
||||
return decode<NV4097_SET_ANTI_ALIASING_CONTROL>().msaa_enabled();
|
||||
}
|
||||
|
||||
bool msaa_alpha_to_coverage_enabled()
|
||||
{
|
||||
return decode<NV4097_SET_ANTI_ALIASING_CONTROL>().msaa_alpha_to_coverage();
|
||||
}
|
||||
|
||||
bool msaa_alpha_to_one_enabled()
|
||||
{
|
||||
return decode<NV4097_SET_ANTI_ALIASING_CONTROL>().msaa_alpha_to_one();
|
||||
}
|
||||
};
|
||||
|
||||
extern rsx_state method_registers;
|
||||
|
||||
@@ -251,4 +251,33 @@ namespace rsx
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void split_index_list(T* indices, int index_count, T restart_index, std::vector<std::pair<u32, u32>>& out)
|
||||
{
|
||||
int last_valid_index = -1;
|
||||
int last_start = -1;
|
||||
|
||||
for (int i = 0; i < index_count; ++i)
|
||||
{
|
||||
if (indices[i] == UINT16_MAX)
|
||||
{
|
||||
if (last_start >= 0)
|
||||
{
|
||||
out.push_back(std::make_pair(last_start, i - last_start));
|
||||
last_start = -1;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (last_start < 0)
|
||||
last_start = i;
|
||||
|
||||
last_valid_index = i;
|
||||
}
|
||||
|
||||
if (last_start >= 0)
|
||||
out.push_back(std::make_pair(last_start, last_valid_index - last_start + 1));
|
||||
}
|
||||
}
|
||||
|
||||
+32
-13
@@ -190,7 +190,7 @@ void Emulator::Init()
|
||||
{
|
||||
g_tty.open(fs::get_config_dir() + "TTY.log", fs::rewrite + fs::append);
|
||||
}
|
||||
|
||||
|
||||
idm::init();
|
||||
fxm::init();
|
||||
|
||||
@@ -308,10 +308,13 @@ void Emulator::Load(bool add_only)
|
||||
{
|
||||
return sfov;
|
||||
}
|
||||
else
|
||||
|
||||
if (Emu.disc.size())
|
||||
{
|
||||
return fs::file(elf_dir + "/../PARAM.SFO");
|
||||
return fs::file{Emu.disc + "/PS3_GAME/PARAM.SFO"};
|
||||
}
|
||||
|
||||
return fs::file(elf_dir + "/../PARAM.SFO");
|
||||
}());
|
||||
m_title = psf::get_string(_psf, "TITLE", m_path);
|
||||
m_title_id = psf::get_string(_psf, "TITLE_ID");
|
||||
@@ -370,7 +373,7 @@ void Emulator::Load(bool add_only)
|
||||
const std::string hdd0_game = vfs::get("/dev_hdd0/game/");
|
||||
const std::string hdd0_disc = vfs::get("/dev_hdd0/disc/");
|
||||
|
||||
if (_cat == "DG" && m_path.find(hdd0_game) != -1)
|
||||
if (_cat == "DG" && m_path.find(hdd0_game) != -1 && Emu.disc.empty())
|
||||
{
|
||||
// Booting disc game from wrong location
|
||||
LOG_ERROR(LOADER, "Disc game %s found at invalid location /dev_hdd0/game/", m_title_id);
|
||||
@@ -389,7 +392,7 @@ void Emulator::Load(bool add_only)
|
||||
}
|
||||
|
||||
// Booting disc game
|
||||
if (_cat == "DG" && bdvd_dir.empty())
|
||||
if (_cat == "DG" && bdvd_dir.empty() && Emu.disc.empty())
|
||||
{
|
||||
// Mount /dev_bdvd/ if necessary
|
||||
if (auto pos = elf_dir.rfind("/PS3_GAME/") + 1)
|
||||
@@ -399,7 +402,7 @@ void Emulator::Load(bool add_only)
|
||||
}
|
||||
|
||||
// Booting patch data
|
||||
if (_cat == "GD" && bdvd_dir.empty())
|
||||
if (_cat == "GD" && bdvd_dir.empty() && Emu.disc.empty())
|
||||
{
|
||||
// Load /dev_bdvd/ from game list if available
|
||||
if (auto node = games[m_title_id])
|
||||
@@ -413,7 +416,7 @@ void Emulator::Load(bool add_only)
|
||||
}
|
||||
|
||||
// Check /dev_bdvd/
|
||||
if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
|
||||
if (Emu.disc.empty() && !bdvd_dir.empty() && fs::is_dir(bdvd_dir))
|
||||
{
|
||||
fs::file sfb_file;
|
||||
|
||||
@@ -440,6 +443,11 @@ void Emulator::Load(bool add_only)
|
||||
out << games;
|
||||
fs::file(fs::get_config_dir() + "/games.yml", fs::rewrite).write(out.c_str(), out.size());
|
||||
}
|
||||
else if (!Emu.disc.empty())
|
||||
{
|
||||
vfs::mount("dev_bdvd", Emu.disc);
|
||||
LOG_NOTICE(LOADER, "Disk: %s", vfs::get("/dev_bdvd"));
|
||||
}
|
||||
else if (_cat == "DG" || _cat == "GD")
|
||||
{
|
||||
LOG_ERROR(LOADER, "Failed to mount disc directory for the disc game %s", m_title_id);
|
||||
@@ -493,7 +501,7 @@ void Emulator::Load(bool add_only)
|
||||
else
|
||||
{
|
||||
// Decrypt SELF
|
||||
elf_file = decrypt_self(std::move(elf_file));
|
||||
elf_file = decrypt_self(std::move(elf_file), klic.empty() ? nullptr : klic.data());
|
||||
|
||||
if (fs::file elf_out{decrypted_path, fs::rewrite})
|
||||
{
|
||||
@@ -528,21 +536,26 @@ void Emulator::Load(bool add_only)
|
||||
vm::ps3::init();
|
||||
|
||||
if (argv.empty())
|
||||
{
|
||||
argv.resize(1);
|
||||
}
|
||||
|
||||
if (argv[0].empty())
|
||||
{
|
||||
if (m_path.find(hdd0_game) != -1)
|
||||
{
|
||||
argv.emplace_back("/dev_hdd0/game/" + m_path.substr(hdd0_game.size()));
|
||||
argv[0] = "/dev_hdd0/game/" + m_path.substr(hdd0_game.size());
|
||||
}
|
||||
else if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
|
||||
{
|
||||
// Disc games are on /dev_bdvd/
|
||||
const std::size_t pos = m_path.rfind("PS3_GAME");
|
||||
argv.emplace_back("/dev_bdvd/" + m_path.substr(pos));
|
||||
argv[0] = "/dev_bdvd/" + m_path.substr(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
// For homebrew
|
||||
argv.emplace_back("/host_root/" + m_path);
|
||||
argv[0] = "/host_root/" + m_path;
|
||||
}
|
||||
|
||||
LOG_NOTICE(LOADER, "Elf path: %s", argv[0]);
|
||||
@@ -581,7 +594,12 @@ void Emulator::Load(bool add_only)
|
||||
|
||||
if (argv.empty())
|
||||
{
|
||||
argv.emplace_back("host_root:" + m_path);
|
||||
argv.resize(1);
|
||||
}
|
||||
|
||||
if (argv[0].empty())
|
||||
{
|
||||
argv[0] = "host_root:" + m_path;
|
||||
LOG_NOTICE(LOADER, "Elf path: %s", argv[0]);
|
||||
}
|
||||
|
||||
@@ -631,7 +649,6 @@ void Emulator::Run()
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
GetCallbacks().on_run();
|
||||
|
||||
m_pause_start_time = 0;
|
||||
@@ -829,6 +846,8 @@ void Emulator::Stop()
|
||||
argv.clear();
|
||||
envp.clear();
|
||||
data.clear();
|
||||
disc.clear();
|
||||
klic.clear();
|
||||
}
|
||||
|
||||
s32 error_code::error_report(const fmt_type_info* sup, u64 arg, const fmt_type_info* sup2, u64 arg2)
|
||||
|
||||
+5
-1
@@ -165,6 +165,7 @@ struct EmuCallbacks
|
||||
std::function<std::shared_ptr<class AudioThread>()> get_audio;
|
||||
std::function<std::shared_ptr<class MsgDialogBase>()> get_msg_dialog;
|
||||
std::function<std::unique_ptr<class SaveDialogBase>()> get_save_dialog;
|
||||
std::function<std::unique_ptr<class TrophyNotificationBase>()> get_trophy_notification_dialog;
|
||||
};
|
||||
|
||||
class Emulator final
|
||||
@@ -213,6 +214,8 @@ public:
|
||||
std::vector<std::string> argv;
|
||||
std::vector<std::string> envp;
|
||||
std::vector<u8> data;
|
||||
std::vector<u8> klic;
|
||||
std::string disc;
|
||||
|
||||
const std::string& GetBoot() const
|
||||
{
|
||||
@@ -324,7 +327,6 @@ struct cfg_root : cfg::node
|
||||
cfg::_bool use_gpu_texture_scaling{this, "Use GPU texture scaling", true};
|
||||
cfg::_bool stretch_to_display_area{this, "Stretch To Display Area"};
|
||||
cfg::_bool force_high_precision_z_buffer{this, "Force High Precision Z buffer"};
|
||||
cfg::_bool invalidate_surface_cache_every_frame{this, "Invalidate Cache Every Frame", true};
|
||||
cfg::_bool strict_rendering_mode{this, "Strict Rendering Mode"};
|
||||
cfg::_bool disable_zcull_queries{this, "Disable ZCull Occlusion Queries", false};
|
||||
cfg::_bool disable_vertex_cache{this, "Disable Vertex Cache", false};
|
||||
@@ -363,6 +365,7 @@ struct cfg_root : cfg::node
|
||||
cfg::_bool dump_to_file{this, "Dump to file"};
|
||||
cfg::_bool convert_to_u16{this, "Convert to 16 bit"};
|
||||
cfg::_bool downmix_to_2ch{this, "Downmix to Stereo", true};
|
||||
cfg::_int<2, 128> frames{this, "Buffer Count", 32};
|
||||
|
||||
} audio{this};
|
||||
|
||||
@@ -403,6 +406,7 @@ struct cfg_root : cfg::node
|
||||
cfg::_bool autoexit{this, "Exit RPCS3 when process finishes"};
|
||||
cfg::_bool start_fullscreen{ this, "Start games in fullscreen mode" };
|
||||
cfg::_bool show_fps_in_title{ this, "Show FPS counter in window title", true};
|
||||
cfg::_bool show_trophy_popups{ this, "Show trophy popups", true};
|
||||
cfg::_int<1, 65535> gdb_server_port{this, "Port", 2345};
|
||||
|
||||
} misc{this};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"audio": {
|
||||
"audioOutBox": "Windows: Always use XAudio, no exceptions.\n\nLinux: ALSA uses the native Linux sound system to output sound.\nThis option has good compatibility and sound quality.\nOpenAL uses a cross-platform approach but will have poor audio quality and stuttering sound in most games.\nIf unsure, use ALSA.",
|
||||
"audioOutBox": "Always use XAudio, no exceptions.\nOpenAL uses a cross-platform approach but will have poor audio quality and stuttering sound in most games.",
|
||||
"audioOutBox_Linux": "PulseAudio uses the recommended native Linux sound system and has good compatibility and sound quality. If it is unavailable on your system, ALSA is the next best alternative. \nOpenAL uses a cross-platform approach but will have poor audio quality and stuttering sound in most games.",
|
||||
"audioDump": "Saves all audio as a raw wave file. If unsure, leave this unchecked.",
|
||||
"convert": "Uses 16-bit audio samples instead of default 32-bit floating point.\nUse with buggy audio drivers if you have no sound or completely broken sound.",
|
||||
"downmix": "Uses stereo audio output instead of default 7.1 surround sound.\nUse with stereo audio devices. Disable it only if you are using a surround sound audio system."
|
||||
@@ -30,7 +31,7 @@
|
||||
"spuLoopDetection": "Try to detect loop conditions in SPU kernels and use them as scheduling hints.\nImproves performance and reduces CPU usage.\nMay cause severe audio stuttering in rare cases."
|
||||
},
|
||||
"comboboxes": {
|
||||
"preferredSPUThreads": "Preferred number of threads allowed to enter some sensitive SPU stages.\nSome SPU stages are sensitive to race conditions and allowing a limited number at a time helps alleviate performance stalls.\nSetting this to a smaller value might improve performance and reduce stuttering in some games.\nLeave this on auto if performance is negatively affected when setting a small value."
|
||||
"preferredSPUThreads": "Some SPU stages are sensitive to race conditions and allowing a limited number at a time helps alleviate performance stalls.\nSetting this to a smaller value might improve performance and reduce stuttering in some games.\nLeave this on auto if performance is negatively affected when setting a small value."
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
@@ -46,12 +47,12 @@
|
||||
"logProg": "Dump game shaders to file. Only useful to developers.\nIf unsure, don't use this option.",
|
||||
"disableOcclusionQueries": "Disables running occlusion queries. Minor to moderate performance boost.\nMight introduce issues with broken occlusion e.g missing geometry and extreme pop-in.",
|
||||
"disableVertexCache": "Disables the vertex cache.\nMight resolve missing or flickering graphics output.\nMay degrade performance.",
|
||||
"forceCpuBlitEmulation": "Forces emulation of all blit and image manipulation operations on the cpu.\nRequires 'Write Color Buffers' option to also be enabled in most cases to avoid missing graphics.\nSignificatly degrades performance but is more accurate in some cases.\nThis setting overrides the 'GPU texture scaling' option."
|
||||
"forceCpuBlitEmulation": "Forces emulation of all blit and image manipulation operations on the CPU.\nRequires 'Write Color Buffers' option to also be enabled in most cases to avoid missing graphics.\nSignificantly degrades performance but is more accurate in some cases.\nThis setting overrides the 'GPU texture scaling' option."
|
||||
},
|
||||
"emulator": {
|
||||
"gui": {
|
||||
"configs": "Only useful to developers.\nIf unsure, don't use this option.",
|
||||
"stylesheets": "Only useful to developers.\nIf unsure, don't use this option.",
|
||||
"stylesheets": "Changes the overall look of RPCS3.\nChoose a stylesheet and click Apply to change between styles.",
|
||||
"show_welcome": "Shows the initial welcome screen upon starting RPCS3.",
|
||||
"custom_colors": "Prioritize custom user interface colors over properties set in stylesheet."
|
||||
},
|
||||
@@ -61,15 +62,17 @@
|
||||
"startGameFullscreen": "Automatically puts the game window in fullscreen.\nDouble click on the game window or press alt+enter to toggle fullscreen and windowed mode.",
|
||||
"showFPSInTitle": "Shows the framerate in the game window title. May cause buggy or outdated recording software to not notice RPCS3.",
|
||||
"gs_resizeOnBoot": "Automatically resizes the game window on boot.\nThis does not change the internal game resolution.",
|
||||
"showTrophyPopups": "Show trophy popups when a trophy is unlocked.",
|
||||
"gs_disableMouse": "Disables the activation of fullscreen mode per doubleclick while the game screen is active.\nCheck this if you want to play with mouse and keyboard (for example with UCR)."
|
||||
}
|
||||
},
|
||||
"gpu": {
|
||||
"comboboxes": {
|
||||
"renderBox": "Vulkan is the fastest renderer. OpenGL is the most accurate renderer.\nIf unsure, use Vulkan. Should you have any compatibility issues, fall back to OpenGL.\nDirectX 12 is deprecated and should never be used.",
|
||||
"resBox": "This setting will be ignored if the Resolution Scale is set to anything other than 100%!\nLeave this on 1280x720, every PS3 game is compatible with this resolution.\nSet it to 1920x1080 only if supported by the game. Lower resolutions may work but are not practical.\nHowever rarely due to emulation bugs some games will only render at low resolutions like 480p.",
|
||||
"renderBox_Linux": "Vulkan is the fastest renderer. OpenGL is the most accurate renderer.\nIf unsure, use Vulkan. Should you have any compatibility issues, fall back to OpenGL.",
|
||||
"resBox": "This setting will be ignored if the Resolution Scale is set to anything other than 100%!\nLeave this on 1280x720, every PS3 game is compatible with this resolution.\nOnly use 1920x1080 if the game supports it.\nRarely due to emulation bugs some games will only render at low resolutions like 480p.",
|
||||
"graphicsAdapterBox": "On multi GPU systems select which GPU to use in RPCS3 when using Vulkan or DirectX 12.\nThis is not needed when using OpenGL.",
|
||||
"aspectBox": "Leave this on 16:9 unless you have a 4:3 monitor.\nAuto also works well especially if you use a resolution that is not 720p.",
|
||||
"aspectBox": "Leave this on 16:9 unless you have a 4:3 monitor.\nAuto also works well, especially if you use a resolution that is not 720p.",
|
||||
"frameLimitBox": "Off is the best option as it performs faster.\nUsing the frame limiter will add extra overhead and slow down the game.\nHowever, some games will crash if the framerate is too high.\nIf that happens, set value to anything other than Off.",
|
||||
"anisotropicFilterOverride": "Higher values increase sharpness of textures on sloped surfaces at the cost of GPU resources.\nModern GPUs can handle this setting just fine even at 16x.\nKeep this on Automatic if you want to use the original setting used by a real PS3."
|
||||
},
|
||||
@@ -80,14 +83,14 @@
|
||||
"main": {
|
||||
"dumpColor": "Enable this option if you get missing graphics or broken lighting ingame.\nMight degrade performance and introduce stuttering in some cases.\nRequired for Demon's Souls.",
|
||||
"vsync": "By having this off you might obtain a higher frame rate at the cost of tearing artifacts in the game.",
|
||||
"autoInvalidateCache": "Enable this option if the game has broken shadows. May slightly degrade performance.",
|
||||
"gpuTextureScaling": "Small to significant performance boost in most games and rarely with side effects.\nMay cause texture corruption in rare cases.",
|
||||
"scrictModeRendering": "Enforces strict compliance to the API specification.\nMight result in degraded performance in some games.\nCan resolve rare cases of missing graphics and flickering.\nIf unsure, don't use this option.",
|
||||
"stretchToDisplayArea": "Overrides the aspect ratio and stretches the image to the full display area."
|
||||
}
|
||||
},
|
||||
"input": {
|
||||
"padHandlerBox": "If you want to use the keyboard to control, select the Keyboard option.\nYou can change the button mappings in Configuration --> Controls.\nIf you have a DualShock 4, select DualShock 4.\nWindows: If you have an Xbox controller, or another compatible device, use XInput.\nOlder controllers such as PS2 controllers with an adapter usually work fine with MMJoystick.\nCheck button mappings in the Windows control panel.\n\nLinux: evdev input is WIP.",
|
||||
"padHandlerBox": "If you want to use the keyboard to control, select the Keyboard option.\nIf you have a DualShock 4, select DualShock 4.\nIf you have an Xbox controller, or another compatible device, use XInput.\nOlder controllers such as PS2 controllers with an adapter usually work fine with MMJoystick.\nCheck button mappings in the Windows control panel.",
|
||||
"padHandlerBox_Linux": "If you want to use the keyboard to control, select the Keyboard option.\nIf you have a DualShock 4, select DualShock 4.\nevdev input is WIP.",
|
||||
"keyboardHandlerBox": "Some games support native keyboard input.\nBasic will work in these cases.",
|
||||
"mouseHandlerBox": "Some games support native mouse input.\nBasic will work in these cases.",
|
||||
"cameraBox": "Camera support is not implemented, leave this on null.",
|
||||
|
||||
@@ -9,14 +9,12 @@ bool TROPUSRLoader::Load(const std::string& filepath, const std::string& configp
|
||||
{
|
||||
const std::string& path = vfs::get(filepath);
|
||||
|
||||
if (!Generate(filepath, configpath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_file.open(path, fs::read))
|
||||
{
|
||||
return false;
|
||||
if (!Generate(filepath, configpath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!LoadHeader() || !LoadTableHeaders() || !LoadTables())
|
||||
@@ -209,6 +207,7 @@ u32 TROPUSRLoader::GetTrophyUnlockState(u32 id)
|
||||
if (id >= m_table6.size())
|
||||
{
|
||||
LOG_WARNING(LOADER, "TROPUSRLoader::GetUnlockState: Invalid id=%d", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return m_table6[id].trophy_state; // Let's assume the trophies are stored ordered
|
||||
@@ -219,6 +218,7 @@ u64 TROPUSRLoader::GetTrophyTimestamp(u32 id)
|
||||
if (id >= m_table6.size())
|
||||
{
|
||||
LOG_WARNING(LOADER, "TROPUSRLoader::GetTrophyTimestamp: Invalid id=%d", id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: What timestamp does sceNpTrophyGetTrophyInfo want, timestamp1 or timestamp2?
|
||||
|
||||
@@ -119,16 +119,16 @@ bool evdev_joystick_handler::try_open_dev(u32 index)
|
||||
pads[index]->m_port_status |= CELL_PAD_STATUS_ASSIGN_CHANGES;
|
||||
pads[index]->m_port_status |= CELL_PAD_STATUS_CONNECTED;
|
||||
|
||||
int buttons=0;
|
||||
for (u32 i=BTN_JOYSTICK; i<KEY_MAX; i++)
|
||||
int buttons = 0;
|
||||
for (u32 i = BTN_JOYSTICK; i < KEY_MAX; i++)
|
||||
if (libevdev_has_event_code(dev, EV_KEY, i))
|
||||
{
|
||||
LOG_NOTICE(GENERAL, "Joystick #%d has button %d as %d", index, i, buttons);
|
||||
joy_button_maps[index][i - BTN_MISC] = buttons++;
|
||||
}
|
||||
|
||||
int axes=0;
|
||||
for (u32 i=ABS_X; i<=ABS_RZ; i++)
|
||||
int axes = 0;
|
||||
for (u32 i = ABS_X; i <= ABS_RZ; i++)
|
||||
{
|
||||
|
||||
if (libevdev_has_event_code(dev, EV_ABS, i))
|
||||
@@ -144,7 +144,7 @@ bool evdev_joystick_handler::try_open_dev(u32 index)
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i=ABS_HAT0X; i<=ABS_HAT3Y; i+=2)
|
||||
for (u32 i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2)
|
||||
if (libevdev_has_event_code(dev, EV_ABS, i) ||
|
||||
libevdev_has_event_code(dev, EV_ABS, i+1))
|
||||
{
|
||||
@@ -351,7 +351,7 @@ void evdev_joystick_handler::ThreadProc()
|
||||
{
|
||||
update_devs();
|
||||
|
||||
for (int i=0; i<joy_devs.size(); i++)
|
||||
for (int i = 0; i<joy_devs.size(); i++)
|
||||
{
|
||||
auto pad = pads[i];
|
||||
auto& dev = joy_devs[i];
|
||||
@@ -413,10 +413,41 @@ void evdev_joystick_handler::ThreadProc()
|
||||
break;
|
||||
}
|
||||
case EV_ABS:
|
||||
LOG_NOTICE(GENERAL, "Joystick #%d EV_ABS: %d %d", i, evt.code, evt.value);
|
||||
{
|
||||
|
||||
if (evt.code >= ABS_HAT0X && evt.code <= ABS_HAT3Y) {
|
||||
int hat = evt.code - ABS_HAT0X;
|
||||
LOG_NOTICE(GENERAL, "Joystick #%d EV_ABS: %d %d", i, evt.code, evt.value);
|
||||
//duplicate the evt.code and evt.value, so that they're still available
|
||||
//for the analog input
|
||||
int code2 = evt.code;
|
||||
int value2 = evt.value;
|
||||
if (g_evdev_joystick_config.left_analog_to_dpad)
|
||||
{
|
||||
//some gamepad have a -32767 to +32767 range; others have a 0 to 255
|
||||
float center2 = (axis_ranges[evt.code].second + axis_ranges[evt.code].first) / 2;
|
||||
//arbitrary decision: when the value is higher than a 1/3 of the range, we simulate a dpad press
|
||||
float threshold2 = (axis_ranges[evt.code].second-center2)/3;
|
||||
if (code2 == 0 || code2 == 1)
|
||||
{
|
||||
value2 = 0;
|
||||
if (evt.value > center2 + threshold2)
|
||||
value2 = 1;
|
||||
else if (evt.value < center2 - threshold2)
|
||||
value2 = -1;
|
||||
if (revaxis[code2])
|
||||
value2 = -value2;
|
||||
if (g_evdev_joystick_config.lxstick < g_evdev_joystick_config.lystick)
|
||||
{
|
||||
code2 = (code2 == 0) ? ABS_HAT0X : ABS_HAT0Y;
|
||||
}
|
||||
else
|
||||
{
|
||||
code2 = (code2 == 0) ? ABS_HAT0Y : ABS_HAT0X;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (code2 >= ABS_HAT0X && code2 <= ABS_HAT3Y)
|
||||
{
|
||||
int hat = code2 - ABS_HAT0X;
|
||||
if (hat != joy_hat_ids[i] && hat-1 != joy_hat_ids[i])
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Joystick #%d sent HAT event for invalid hat %d (expected %d)", i, hat, joy_hat_ids[i]);
|
||||
@@ -429,7 +460,7 @@ void evdev_joystick_handler::ThreadProc()
|
||||
{
|
||||
if (bt.m_keyCode != source_axis) continue;
|
||||
|
||||
if (evt.value == 0)
|
||||
if (value2 == 0)
|
||||
{
|
||||
bt.m_pressed = false;
|
||||
bt.m_value = 0;
|
||||
@@ -439,13 +470,12 @@ void evdev_joystick_handler::ThreadProc()
|
||||
int code;
|
||||
if (source_axis == EVDEV_DPAD_HAT_AXIS_X)
|
||||
{
|
||||
code = evt.value > 0 ? CELL_PAD_CTRL_RIGHT : CELL_PAD_CTRL_LEFT;
|
||||
code = value2 > 0 ? CELL_PAD_CTRL_RIGHT : CELL_PAD_CTRL_LEFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
code = evt.value > 0 ? CELL_PAD_CTRL_DOWN : CELL_PAD_CTRL_UP;
|
||||
code = value2 > 0 ? CELL_PAD_CTRL_DOWN : CELL_PAD_CTRL_UP;
|
||||
}
|
||||
|
||||
if (bt.m_outKeyCode == code)
|
||||
{
|
||||
bt.m_pressed = true;
|
||||
@@ -457,7 +487,7 @@ void evdev_joystick_handler::ThreadProc()
|
||||
else if (axistrigger && (evt.code == ABS_Z || evt.code == ABS_RZ))
|
||||
{
|
||||
// For Xbox controllers, a third axis represent the left/right triggers.
|
||||
int which_trigger=0;
|
||||
int which_trigger = 0;
|
||||
|
||||
if (evt.code == ABS_Z)
|
||||
{
|
||||
@@ -486,7 +516,7 @@ void evdev_joystick_handler::ThreadProc()
|
||||
which_button->m_pressed = value > 0;
|
||||
which_button->m_value = value;
|
||||
}
|
||||
else if (evt.code >= ABS_X && evt.code <= ABS_RZ)
|
||||
if (evt.code >= ABS_X && evt.code <= ABS_RZ)
|
||||
{
|
||||
int axis = joy_axis_maps[i][evt.code - ABS_X];
|
||||
|
||||
@@ -531,6 +561,7 @@ void evdev_joystick_handler::ThreadProc()
|
||||
pad->m_sticks[axis].m_value = scale_axis(evt.code, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR(GENERAL, "Unknown joystick #%d event %d", i, evt.type);
|
||||
break;
|
||||
|
||||
@@ -46,7 +46,8 @@ struct evdev_joystick_config final : cfg::node
|
||||
cfg::_bool axistrigger{this, "Z axis triggers", true};
|
||||
cfg::_bool squirclejoysticks{this, "Squircle Joysticks", true};
|
||||
cfg::int32 squirclefactor{this, "Squircle Factor", 5000};
|
||||
cfg::int32 deadzone{this, "Deadzone", 10};
|
||||
cfg::int32 deadzone{this, "Deadzone", 10};
|
||||
cfg::_bool left_analog_to_dpad{this, "Left Analog to Dpad", false};
|
||||
|
||||
bool load()
|
||||
{
|
||||
|
||||
+20
-3
@@ -47,16 +47,33 @@ int main(int argc, char** argv)
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Welcome to RPCS3 command line.");
|
||||
parser.addPositionalArgument("(S)ELF", "Path for directly executing a (S)ELF");
|
||||
parser.addPositionalArgument("[Args...]", "Optional args for the executable");
|
||||
parser.addHelpOption();
|
||||
parser.process(app);
|
||||
|
||||
app.Init();
|
||||
|
||||
if (parser.positionalArguments().length() > 0)
|
||||
QStringList args = parser.positionalArguments();
|
||||
|
||||
if (args.length() > 0)
|
||||
{
|
||||
// Ugly workaround
|
||||
QTimer::singleShot(2, [path = sstr(QFileInfo(parser.positionalArguments().at(0)).canonicalFilePath())]
|
||||
// Propagate command line arguments
|
||||
std::vector<std::string> argv;
|
||||
|
||||
if (args.length() > 1)
|
||||
{
|
||||
argv.emplace_back();
|
||||
|
||||
for (std::size_t i = 1; i < args.length(); i++)
|
||||
{
|
||||
argv.emplace_back(args[i].toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
// Ugly workaround
|
||||
QTimer::singleShot(2, [path = sstr(QFileInfo(args.at(0)).canonicalFilePath()), argv = std::move(argv)]() mutable
|
||||
{
|
||||
Emu.argv = std::move(argv);
|
||||
Emu.BootGame(path, true);
|
||||
Emu.Run();
|
||||
});
|
||||
|
||||
+51
-5
@@ -144,7 +144,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>..\hidapi.lib;winmm.lib;OpenAL.lib;XAudio.lib;D3D12GSRender.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;VKstatic.1.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;HLSL.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng.lib;asmjit.lib;yaml-cpp.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmain.lib;shell32.lib;opengl32.lib;$(QTDIR)\lib\Qt5OpenGL.lib;$(QTDIR)\lib\Qt5Widgets.lib;$(QTDIR)\lib\Qt5Quick.lib;$(QTDIR)\lib\Qt5Gui.lib;$(QTDIR)\lib\Qt5Qml.lib;$(QTDIR)\lib\Qt5Network.lib;$(QTDIR)\lib\Qt5Core.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5WinExtras.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Release;..\Vulkan\glslang-build\SPIRV\Release;..\Vulkan\glslang-build\OGLCompilersDLL\Release;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Release;..\Vulkan\Vulkan-build\loader\Release;..\Vulkan\glslang-build\glslang\Release;..\lib\$(CONFIGURATION)-$(PLATFORM);..\3rdparty\minidx12\Lib;$(QTDIR)\lib;C:\utils\my_sql\my_sql\lib;C:\utils\postgresql\pgsql\lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Release;..\Vulkan\glslang-build\SPIRV\Release;..\Vulkan\glslang-build\OGLCompilersDLL\Release;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Release;..\Vulkan\Vulkan-build\loader\Release;..\Vulkan\glslang-build\glslang\Release;..\lib\$(CONFIGURATION)-$(PLATFORM);..\3rdparty\minidx12\Lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
|
||||
<DataExecutionPrevention>true</DataExecutionPrevention>
|
||||
<GenerateDebugInformation>Debug</GenerateDebugInformation>
|
||||
@@ -185,7 +185,7 @@
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<PreprocessorDefinitions>_WINDOWS;UNICODE;WIN32;WIN64;QT_NO_DEBUG;QT_OPENGL_LIB;QT_WIDGETS_LIB;QT_QUICK_LIB;QT_GUI_LIB;QT_QML_LIB;QT_NETWORK_LIB;QT_CORE_LIB;NDEBUG;QT_WINEXTRAS_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_WINDOWS;UNICODE;WIN32;WIN64;QT_NO_DEBUG;QT_OPENGL_LIB;QT_WIDGETS_LIB;QT_QUICK_LIB;QT_GUI_LIB;QT_QML_LIB;QT_NETWORK_LIB;QT_CORE_LIB;NDEBUG;QT_WINEXTRAS_LIB;BRANCH=$(BRANCH);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessToFile>false</PreprocessToFile>
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
@@ -196,7 +196,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>..\hidapi.lib;winmm.lib;OpenAL.lib;XAudio.lib;D3D12GSRender.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;VKstatic.1.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;HLSL.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng.lib;asmjit.lib;yaml-cpp.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmain.lib;shell32.lib;opengl32.lib;$(QTDIR)\lib\Qt5OpenGL.lib;$(QTDIR)\lib\Qt5Widgets.lib;$(QTDIR)\lib\Qt5Quick.lib;$(QTDIR)\lib\Qt5Gui.lib;$(QTDIR)\lib\Qt5Qml.lib;$(QTDIR)\lib\Qt5Network.lib;$(QTDIR)\lib\Qt5Core.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5WinExtras.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Release;..\Vulkan\glslang-build\SPIRV\Release;..\Vulkan\glslang-build\OGLCompilersDLL\Release;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Release;..\Vulkan\Vulkan-build\loader\Release;..\Vulkan\glslang-build\glslang\Release;..\lib\$(CONFIGURATION)-$(PLATFORM);..\3rdparty\minidx12\Lib;$(QTDIR)\lib;C:\utils\my_sql\my_sql\lib;C:\utils\postgresql\pgsql\lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Release;..\Vulkan\glslang-build\SPIRV\Release;..\Vulkan\glslang-build\OGLCompilersDLL\Release;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Release;..\Vulkan\Vulkan-build\loader\Release;..\Vulkan\glslang-build\glslang\Release;..\lib\$(CONFIGURATION)-$(PLATFORM);..\3rdparty\minidx12\Lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
|
||||
<DataExecutionPrevention>true</DataExecutionPrevention>
|
||||
<GenerateDebugInformation>Debug</GenerateDebugInformation>
|
||||
@@ -248,7 +248,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>..\hidapi.lib;winmm.lib;OpenAL.lib;XAudio.lib;D3D12GSRender.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;VKstatic.1.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;HLSLd.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng.lib;asmjit.lib;yaml-cpp.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmaind.lib;shell32.lib;opengl32.lib;$(QTDIR)\lib\Qt5OpenGLd.lib;$(QTDIR)\lib\Qt5Widgetsd.lib;$(QTDIR)\lib\Qt5Quickd.lib;$(QTDIR)\lib\Qt5Guid.lib;$(QTDIR)\lib\Qt5Qmld.lib;$(QTDIR)\lib\Qt5Networkd.lib;$(QTDIR)\lib\Qt5Cored.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5WinExtrasd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Debug;..\Vulkan\glslang-build\SPIRV\Debug;..\Vulkan\glslang-build\OGLCompilersDLL\Debug;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Debug;..\Vulkan\Vulkan-build\loader\Debug;..\Vulkan\glslang-build\glslang\Debug;..\3rdparty\minidx12\Lib;..\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;C:\utils\my_sql\my_sql\lib;C:\utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Debug;..\Vulkan\glslang-build\SPIRV\Debug;..\Vulkan\glslang-build\OGLCompilersDLL\Debug;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Debug;..\Vulkan\Vulkan-build\loader\Debug;..\Vulkan\glslang-build\glslang\Debug;..\3rdparty\minidx12\Lib;..\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
|
||||
<DataExecutionPrevention>true</DataExecutionPrevention>
|
||||
<GenerateDebugInformation>Debug</GenerateDebugInformation>
|
||||
@@ -301,7 +301,7 @@
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>..\hidapi.lib;winmm.lib;OpenAL.lib;XAudio.lib;D3D12GSRender.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;VKstatic.1.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;HLSLd.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng.lib;asmjit.lib;yaml-cpp.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmaind.lib;shell32.lib;opengl32.lib;$(QTDIR)\lib\Qt5OpenGLd.lib;$(QTDIR)\lib\Qt5Widgetsd.lib;$(QTDIR)\lib\Qt5Quickd.lib;$(QTDIR)\lib\Qt5Guid.lib;$(QTDIR)\lib\Qt5Qmld.lib;$(QTDIR)\lib\Qt5Networkd.lib;$(QTDIR)\lib\Qt5Cored.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5WinExtrasd.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Debug;..\Vulkan\glslang-build\SPIRV\Debug;..\Vulkan\glslang-build\OGLCompilersDLL\Debug;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Debug;..\Vulkan\Vulkan-build\loader\Debug;..\Vulkan\glslang-build\glslang\Debug;..\3rdparty\minidx12\Lib;..\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;C:\utils\my_sql\my_sql\lib;C:\utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Debug;..\Vulkan\glslang-build\SPIRV\Debug;..\Vulkan\glslang-build\OGLCompilersDLL\Debug;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Debug;..\Vulkan\Vulkan-build\loader\Debug;..\Vulkan\glslang-build\glslang\Debug;..\3rdparty\minidx12\Lib;..\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /VERBOSE %(AdditionalOptions)</AdditionalOptions>
|
||||
<DataExecutionPrevention>true</DataExecutionPrevention>
|
||||
<GenerateDebugInformation>Debug</GenerateDebugInformation>
|
||||
@@ -455,6 +455,11 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_syntax_highlighter.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_vfs_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
@@ -585,6 +590,11 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_syntax_highlighter.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_vfs_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
@@ -725,6 +735,11 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_syntax_highlighter.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_vfs_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
@@ -855,6 +870,11 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_syntax_highlighter.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_vfs_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
@@ -874,8 +894,12 @@
|
||||
<ClCompile Include="rpcs3qt\gamepads_settings_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\game_list_grid.cpp" />
|
||||
<ClCompile Include="rpcs3qt\game_list_grid_delegate.cpp" />
|
||||
<ClCompile Include="rpcs3qt\syntax_highlighter.cpp" />
|
||||
<ClCompile Include="rpcs3qt\save_data_info_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\save_manager_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\trophy_manager_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\trophy_notification_frame.cpp" />
|
||||
<ClCompile Include="rpcs3qt\trophy_notification_helper.cpp" />
|
||||
<ClCompile Include="rpcs3qt\vfs_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\vfs_dialog_tab.cpp" />
|
||||
<ClCompile Include="rpcs3qt\welcome_dialog.cpp" />
|
||||
@@ -1243,6 +1267,24 @@
|
||||
<ClInclude Include="rpcs3qt\game_list_grid_delegate.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="rpcs3qt\gl_gs_frame.h" />
|
||||
<CustomBuild Include="rpcs3qt\syntax_highlighter.h">
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">Moc%27ing syntax_highlighter.h...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing syntax_highlighter.h...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing syntax_highlighter.h...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">Moc%27ing syntax_highlighter.h...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\instruction_editor_dialog.h" />
|
||||
<ClInclude Include="rpcs3qt\memory_viewer_panel.h" />
|
||||
<CustomBuild Include="rpcs3qt\msg_dialog_frame.h">
|
||||
@@ -1392,6 +1434,10 @@
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(NOINHERIT)\."</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\trophy_manager_dialog.h" />
|
||||
<ClInclude Include="rpcs3qt\trophy_notification_frame.h" />
|
||||
<ClInclude Include="rpcs3qt\trophy_notification_helper.h" />
|
||||
<ClInclude Include="rpcs3qt\trophy_tree_widget_item.h" />
|
||||
<ClInclude Include="xinput_pad_handler.h" />
|
||||
<ClInclude Include="\rpcs3qt\*.h" />
|
||||
</ItemGroup>
|
||||
|
||||
+245
-167
@@ -60,9 +60,42 @@
|
||||
<Extensions>ui</Extensions>
|
||||
<ParseFiles>true</ParseFiles>
|
||||
</Filter>
|
||||
<Filter Include="Gui\saves">
|
||||
<Filter Include="Gui\trophy">
|
||||
<UniqueIdentifier>{d49ebf7f-ea65-4006-943a-2c47f25c9aa7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\save">
|
||||
<UniqueIdentifier>{31799965-1274-4c87-83a3-3bff31e8715d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\vfs">
|
||||
<UniqueIdentifier>{e0821fe5-e58f-4ddd-8b30-8c324916b15e}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\debugger">
|
||||
<UniqueIdentifier>{32359024-92ef-44f2-97d8-120a3539c629}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\dev tools">
|
||||
<UniqueIdentifier>{2183c937-7c45-45d5-bab1-c654bba97e15}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\game list">
|
||||
<UniqueIdentifier>{d181920e-98c2-49b9-9ad6-bf3c2caf886a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\game window">
|
||||
<UniqueIdentifier>{92da2292-18f9-4c41-997e-b8d288f03d5a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\log">
|
||||
<UniqueIdentifier>{b90a63fe-afa9-41e1-9f99-1db049864d58}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\message dialog">
|
||||
<UniqueIdentifier>{dae67696-f925-4d24-b1b7-96d1d0176dec}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\settings">
|
||||
<UniqueIdentifier>{ce01674e-ca9e-4fb7-bb4e-cdde3764317d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\misc dialogs">
|
||||
<UniqueIdentifier>{114eef25-61bf-4df5-8867-09156cf51b8a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Gui\syntax highlighter">
|
||||
<UniqueIdentifier>{adb985ae-88db-4274-a6fd-6bcf230451ca}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="\rpcs3qt\*.cpp">
|
||||
@@ -71,9 +104,6 @@
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>rpcs3</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\auto_pause_settings_dialog.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_auto_pause_settings_dialog.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -98,9 +128,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_cg_disasm_window.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\cg_disasm_window.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_debugger_frame.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -113,9 +140,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_debugger_frame.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\debugger_frame.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_emu_settings.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -128,9 +152,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_emu_settings.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\emu_settings.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_game_list_frame.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -143,12 +164,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_game_list_frame.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\game_list_frame.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\gl_gs_frame.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_gs_frame.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -161,9 +176,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_gs_frame.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\gs_frame.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_gui_settings.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -176,9 +188,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_gui_settings.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\gui_settings.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_kernel_explorer.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -191,9 +200,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_kernel_explorer.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\kernel_explorer.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_log_frame.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -206,9 +212,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_log_frame.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\log_frame.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_main_window.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -221,9 +224,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_main_window.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\main_window.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_memory_string_searcher.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -236,9 +236,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_memory_string_searcher.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\memory_string_searcher.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_pad_settings_dialog.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -251,9 +248,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_pad_settings_dialog.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\pad_settings_dialog.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_rsx_debugger.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -266,9 +260,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_rsx_debugger.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\rsx_debugger.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_settings_dialog.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -281,9 +272,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_settings_dialog.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\settings_dialog.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="basic_keyboard_handler.cpp">
|
||||
<Filter>Io\Basic</Filter>
|
||||
</ClCompile>
|
||||
@@ -341,15 +329,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_rpcs3_app.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\instruction_editor_dialog.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\memory_viewer_panel.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\msg_dialog_frame.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_msg_dialog_frame.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -362,15 +341,9 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_msg_dialog_frame.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\register_editor_dialog.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\qrc_resources.cpp">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\welcome_dialog.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_welcome_dialog.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -383,9 +356,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_welcome_dialog.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\game_list_grid.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_game_list_grid.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -398,12 +368,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_game_list_grid.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\game_list_grid_delegate.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\vfs_dialog.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_vfs_dialog.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -416,9 +380,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_vfs_dialog.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\vfs_dialog_tab.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_vfs_dialog_tab.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -431,9 +392,6 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_vfs_dialog_tab.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\about_dialog.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_about_dialog.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
@@ -471,16 +429,19 @@
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\save_data_dialog.cpp">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\save_data_info_dialog.cpp">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\save_data_list_dialog.cpp">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\save_manager_dialog.cpp">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<ClCompile Include="rpcs3qt\trophy_notification_helper.cpp">
|
||||
<Filter>Gui\trophy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\trophy_notification_frame.cpp">
|
||||
<Filter>Gui\trophy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_save_manager_dialog.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
@@ -497,20 +458,113 @@
|
||||
<ClCompile Include="pad_thread.cpp">
|
||||
<Filter>Io</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\about_dialog.cpp">
|
||||
<Filter>Gui\misc dialogs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\welcome_dialog.cpp">
|
||||
<Filter>Gui\misc dialogs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\auto_pause_settings_dialog.cpp">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\cg_disasm_window.cpp">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\debugger_frame.cpp">
|
||||
<Filter>Gui\debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\emu_settings.cpp">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\gui_settings.cpp">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\gl_gs_frame.cpp">
|
||||
<Filter>Gui\game window</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\gs_frame.cpp">
|
||||
<Filter>Gui\game window</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\gamepads_settings_dialog.cpp">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\pad_settings_dialog.cpp">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\log_frame.cpp">
|
||||
<Filter>Gui\log</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\main_window.cpp">
|
||||
<Filter>Gui</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_syntax_highlighter.cpp">
|
||||
<Filter>Generated Files\Release - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_syntax_highlighter.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_syntax_highlighter.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_syntax_highlighter.cpp">
|
||||
<Filter>Generated Files\Debug - LLVM</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\syntax_highlighter.cpp">
|
||||
<Filter>Gui\syntax highlighter</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\kernel_explorer.cpp">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\game_list_frame.cpp">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\game_list_grid.cpp">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\game_list_grid_delegate.cpp">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\memory_string_searcher.cpp">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\memory_viewer_panel.cpp">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\settings_dialog.cpp">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\vfs_dialog.cpp">
|
||||
<Filter>Gui\vfs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\vfs_dialog_tab.cpp">
|
||||
<Filter>Gui\vfs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\rsx_debugger.cpp">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\register_editor_dialog.cpp">
|
||||
<Filter>Gui\debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\instruction_editor_dialog.cpp">
|
||||
<Filter>Gui\debugger</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\msg_dialog_frame.cpp">
|
||||
<Filter>Gui\message dialog</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\syntax_highlighter.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\save_manager_dialog.cpp">
|
||||
<Filter>Gui\save</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\trophy_manager_dialog.cpp">
|
||||
<Filter>Gui\trophy</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="\rpcs3qt\*.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\gl_gs_frame.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\table_item_delegate.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="keyboard_pad_handler.h">
|
||||
<Filter>Io\Basic</Filter>
|
||||
</ClInclude>
|
||||
@@ -523,18 +577,6 @@
|
||||
<ClInclude Include="xinput_pad_handler.h">
|
||||
<Filter>Io\XInput</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\instruction_editor_dialog.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\memory_viewer_panel.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\register_editor_dialog.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\game_list_grid_delegate.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="QTGeneratedFiles\ui_about_dialog.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -550,17 +592,47 @@
|
||||
<ClInclude Include="QTGeneratedFiles\ui_welcome_dialog.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\game_list.h">
|
||||
<Filter>Gui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\save_data_dialog.h">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\trophy_notification_helper.h">
|
||||
<Filter>Gui\trophy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\trophy_notification_frame.h">
|
||||
<Filter>Gui\trophy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pad_thread.h">
|
||||
<Filter>Io</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\gl_gs_frame.h">
|
||||
<Filter>Gui\game window</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\gamepads_settings_dialog.h">
|
||||
<Filter>Gui</Filter>
|
||||
<Filter>Gui\settings</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\game_list.h">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\game_list_grid_delegate.h">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\table_item_delegate.h">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\memory_viewer_panel.h">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\register_editor_dialog.h">
|
||||
<Filter>Gui\debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\instruction_editor_dialog.h">
|
||||
<Filter>Gui\debugger</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\trophy_manager_dialog.h">
|
||||
<Filter>Gui\trophy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\trophy_tree_widget_item.h">
|
||||
<Filter>Gui\trophy</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -570,48 +642,6 @@
|
||||
<CustomBuild Include="release\moc_predefs.h.cbt">
|
||||
<Filter>Generated Files</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\auto_pause_settings_dialog.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\cg_disasm_window.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\debugger_frame.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\emu_settings.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\game_list_frame.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\gs_frame.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\gui_settings.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\kernel_explorer.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\log_frame.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\main_window.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\memory_string_searcher.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\pad_settings_dialog.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\rsx_debugger.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\settings_dialog.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="basic_keyboard_handler.h">
|
||||
<Filter>Io\Basic</Filter>
|
||||
</CustomBuild>
|
||||
@@ -621,27 +651,12 @@
|
||||
<CustomBuild Include="rpcs3_app.h">
|
||||
<Filter>rpcs3</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\msg_dialog_frame.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ClInclude>
|
||||
<CustomBuild Include="resources.qrc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\welcome_dialog.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\game_list_grid.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\vfs_dialog.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\vfs_dialog_tab.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\about_dialog.ui">
|
||||
<Filter>Form Files</Filter>
|
||||
</CustomBuild>
|
||||
@@ -657,17 +672,80 @@
|
||||
<CustomBuild Include="rpcs3qt\welcome_dialog.ui">
|
||||
<Filter>Form Files</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\about_dialog.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\save_data_info_dialog.h">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\save_data_list_dialog.h">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\syntax_highlighter.h">
|
||||
<Filter>Gui\syntax highlighter</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\about_dialog.h">
|
||||
<Filter>Gui\misc dialogs</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\welcome_dialog.h">
|
||||
<Filter>Gui\misc dialogs</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\auto_pause_settings_dialog.h">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\cg_disasm_window.h">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\debugger_frame.h">
|
||||
<Filter>Gui\debugger</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\emu_settings.h">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\gui_settings.h">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\gs_frame.h">
|
||||
<Filter>Gui\game window</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\pad_settings_dialog.h">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\log_frame.h">
|
||||
<Filter>Gui\log</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\main_window.h">
|
||||
<Filter>Gui</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\kernel_explorer.h">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\game_list_frame.h">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\game_list_grid.h">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\memory_string_searcher.h">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\settings_dialog.h">
|
||||
<Filter>Gui\settings</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\vfs_dialog_tab.h">
|
||||
<Filter>Gui\vfs</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\vfs_dialog.h">
|
||||
<Filter>Gui\vfs</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\rsx_debugger.h">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\msg_dialog_frame.h">
|
||||
<Filter>Gui\message dialog</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\syntax_highlighter.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\save_manager_dialog.h">
|
||||
<Filter>Gui\saves</Filter>
|
||||
<Filter>Gui\save</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -6,6 +6,9 @@
|
||||
#include "rpcs3qt/gs_frame.h"
|
||||
#include "rpcs3qt/gl_gs_frame.h"
|
||||
|
||||
#include "Emu/Cell/Modules/sceNpTrophy.h"
|
||||
#include "rpcs3qt/trophy_notification_helper.h"
|
||||
|
||||
#include "Emu/Cell/Modules/cellSaveData.h"
|
||||
#include "rpcs3qt/save_data_dialog.h"
|
||||
|
||||
@@ -241,6 +244,11 @@ void rpcs3_app::InitializeCallbacks()
|
||||
return std::make_unique<save_data_dialog>();
|
||||
};
|
||||
|
||||
callbacks.get_trophy_notification_dialog = [=]() -> std::unique_ptr<TrophyNotificationBase>
|
||||
{
|
||||
return std::make_unique<trophy_notification_helper>(gameWindow);
|
||||
};
|
||||
|
||||
callbacks.on_run = [=]() { OnEmulatorRun(); };
|
||||
callbacks.on_pause = [=]() { OnEmulatorPause(); };
|
||||
callbacks.on_resume = [=]() { OnEmulatorResume(); };
|
||||
|
||||
@@ -9,5 +9,5 @@ namespace rpcs3
|
||||
return RPCS3_GIT_BRANCH;
|
||||
}
|
||||
|
||||
const extern utils::version version{ 0, 0, 3, utils::version_type::alpha, 1, RPCS3_GIT_VERSION };
|
||||
const extern utils::version version{ 0, 0, 4, utils::version_type::alpha, 1, RPCS3_GIT_VERSION };
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ about_dialog::about_dialog(QWidget* parent) : QDialog(parent), ui(new Ui::about_
|
||||
connect(ui->patreon, &QAbstractButton::clicked, [] { QDesktopServices::openUrl(QUrl("https://www.patreon.com/Nekotekina")); });
|
||||
connect(ui->close, &QAbstractButton::clicked, this, &QWidget::close);
|
||||
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
layout()->setSizeConstraint(QLayout::SetFixedSize);
|
||||
}
|
||||
|
||||
|
||||
@@ -210,7 +210,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>863</width>
|
||||
<height>707</height>
|
||||
<height>737</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,1,1,1">
|
||||
@@ -246,7 +246,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="supporters">
|
||||
<property name="text">
|
||||
<string><p><b>Supporters:</b><br><br>Howard Garrison<br>EXPotemkin<br>Marko V.<br>danhp<br>Jake (5315825)<br>Ian Reid<br>Tad Sherlock<br>Tyler Friesen<br>Folzar<br>Payton Williams<br>RedPill Australia<br>yanghong<br>Mohammed El-Serougi<br>Дима ~Ximer13~ Кулин<br>James Reed<br>BaroqueSonata<br>Bonzay0<br>Henrijs Kons<br>eoiz<br>Lena Stöffler<br>Michael Holder<br>Max Bosse<br>Tyler Whisinnand<br>Gato Harvey<br>cain4355<br>Thomas Peltier<br>Loli Co.<br>MapleLoonie<br>Travis McEwen<br>Scott Singratsomboune<br>T.E<br>Lukas Rieger<br>Dane Madsen<br>Jacob Gustin<br>Jonatan R<br>Luke Johnson<br>Thomas Zaorski<br>MyOwnFan<br>Alexandros Mandravillis<br>Socker Bopper<br>Faris Leonhart<br>Fabien Net<br>Raves<br>Barrowsx<br>kilsuton<br>Max Mason<br>Ethan Condon<br>jfidone<br>iaDRM<br>Kazer2.0<br>Bryce Quintin</p></string>
|
||||
<string><p><b>Supporters:</b><br><br>Howard Garrison<br>EXPotemkin<br>Marko V.<br>danhp<br>Jake (5315825)<br>Ian Reid<br>Tad Sherlock<br>Tyler Friesen<br>Folzar<br>Payton Williams<br>RedPill Australia<br>yanghong<br>Mohammed El-Serougi<br>Дима ~Ximer13~ Кулин<br>James Reed<br>BaroqueSonata<br>Bonzay0<br>Henrijs Kons<br>eoiz<br>Lena Stöffler<br>Michael Holder<br>Max Bosse<br>Tyler Whisinnand<br>Gato Harvey<br>cain4355<br>Thomas Peltier<br>Loli Co.<br>MapleLoonie<br>Travis McEwen<br>Scott Singratsomboune<br>T.E<br>Lukas Rieger<br>Dane Madsen<br>Jacob Gustin<br>Jonatan R<br>Luke Johnson<br>Thomas Zaorski<br>MyOwnFan<br>Alexandros Mandravillis<br>Socker Bopper<br>Faris Leonhart<br>Fabien Net<br>Raves<br>Barrowsx<br>kilsuton<br>Max Mason<br>Ethan Condon<br>jfidone<br>iaDRM<br>Kazer2.0<br>Bryce Quintin<br>Yuri Kunde Schlesner</p></string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
|
||||
@@ -5,6 +5,8 @@ constexpr auto qstr = QString::fromStdString;
|
||||
|
||||
auto_pause_settings_dialog::auto_pause_settings_dialog(QWidget *parent) : QDialog(parent)
|
||||
{
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
QLabel *description = new QLabel(tr("To use auto pause: enter the ID(s) of a function or a system call.\nRestart of the game is required to apply. You can enable/disable this in the settings."), this);
|
||||
|
||||
pauseList = new QTableWidget(this);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#include "cg_disasm_window.h"
|
||||
#include "syntax_highlighter.h"
|
||||
|
||||
#include <QSplitter>
|
||||
#include <QMenu>
|
||||
@@ -39,6 +40,119 @@ cg_disasm_window::cg_disasm_window(std::shared_ptr<gui_settings> xSettings): xgu
|
||||
m_glsl_text->setWordWrapMode(QTextOption::NoWrap);
|
||||
m_glsl_text->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
|
||||
|
||||
// m_disasm_text syntax highlighter
|
||||
syntax_highlighter* sh_asm = new syntax_highlighter(m_disasm_text->document());
|
||||
sh_asm->AddCommentRule("#", QColor(Qt::darkGreen));
|
||||
sh_asm->AddCommentRule("\/\*", QColor(Qt::darkGreen), true, "\*\/");
|
||||
sh_asm->AddSimpleRule(QStringList("^([^\\s]+).*$"), QColor(Qt::darkBlue)); // Instructions
|
||||
sh_asm->AddSimpleRule(QStringList(",?\\s(-?R\\d[^,;\\s]*)"), QColor(Qt::darkRed)); // -R0.*
|
||||
sh_asm->AddSimpleRule(QStringList(",?\\s(-?H\\d[^,;\\s]*)"), QColor(Qt::red)); // -H1.*
|
||||
sh_asm->AddSimpleRule(QStringList(",?\\s(-?v\\[\\d\\]*[^,;\\s]*)"), QColor(Qt::darkCyan)); // -v[xyz].*
|
||||
sh_asm->AddSimpleRule(QStringList(",?\\s(-?o\\[\\d\\]*[^,;\\s]*)"), QColor(Qt::darkMagenta)); // -o[xyz].*
|
||||
sh_asm->AddSimpleRule(QStringList(",?\\s(-?c\\[\\d\\]*[^,;\\s]*)"), QColor(Qt::darkYellow)); // -c[xyz].*
|
||||
//sh_asm->AddMultiRule(
|
||||
// "^([^\\s]+)(?:,?\\s*([^,\\;\\s]+))?(?:,?\\s*([^,\\;\\s]+))?(?:,?\\s*([^,\\;\\s]+))?(?:,?\\s*([^,\\;\\s]+))?.*$",
|
||||
// { QColor(Qt::black), QColor(Qt::darkBlue), QColor(Qt::darkRed), QColor(Qt::darkMagenta), QColor(Qt::darkYellow), QColor(Qt::darkCyan) });
|
||||
|
||||
// m_glsl_text syntax highlighter
|
||||
QStringList glsl_syntax = QStringList()
|
||||
// Selection-Iteration-Jump Statements:
|
||||
<< "if" << "else" << "switch" << "case" << "default"
|
||||
<< "for" << "while" << "do" << "foreach" //?
|
||||
<< "return" << "break" << "continue" << "discard"
|
||||
// Misc:
|
||||
<< "void" << "char" << "short" << "long" << "template"
|
||||
<< "class" << "struct" << "union" << "enum"
|
||||
<< "static" << "virtual" << "inline" << "explicit"
|
||||
<< "public" << "private" << "protected" << "namespace"
|
||||
<< "typedef" << "typename" << "signed" << "unsigned"
|
||||
<< "friend" << "operator" << "signals" << "slots"
|
||||
// Qualifiers:
|
||||
<< "in" << "packed" << "precision" << "const" << "smooth" << "sample"
|
||||
<< "out" << "shared" << "highp" << "invariant" << "noperspective" << "centroid"
|
||||
<< "inout" << "std140" << "mediump" << "uniform" << "flat" << "patch"
|
||||
<< "buffer" << "std430" << "lowp"
|
||||
<< "image"
|
||||
// Removed Qualifiers?
|
||||
<< "attribute" << "varying"
|
||||
// Memory Qualifiers
|
||||
<< "coherent" << "volatile" << "restrict" << "readonly" << "writeonly"
|
||||
// Layout Qualifiers:
|
||||
//<< "subroutine" << "layout" << "xfb_buffer" << "textureGrad" << "texture" << "dFdx" << "dFdy"
|
||||
//<< "location" << "component" << "binding" << "offset"
|
||||
//<< "xfb_offset" << "xfb_stride" << "vertices" << "max_vertices"
|
||||
// Scalars and Vectors:
|
||||
<< "bool" << "int" << "uint" << "float" << "double"
|
||||
<< "bvec2" << "ivec2" << "uvec2" << "vec2" << "dvec2"
|
||||
<< "bvec3" << "ivec3" << "uvec3" << "vec3" << "dvec3"
|
||||
<< "bvec4" << "ivec4" << "uvec4" << "vec4" << "dvec4"
|
||||
// Matrices:
|
||||
<< "mat2" << "mat2x3" << "mat2x4"
|
||||
<< "mat3" << "mat3x2" << "mat3x4"
|
||||
<< "mat4" << "mat4x2" << "mat4x3"
|
||||
// Sampler Types:
|
||||
<< "sampler1D" << "isampler1D" << "usampler1D"
|
||||
<< "sampler2D" << "isampler2D" << "usampler2D"
|
||||
<< "sampler3D" << "isampler3D" << "usampler3D"
|
||||
<< "samplerCube" << "isamplerCube" << "usamplerCube"
|
||||
<< "sampler2DRect" << "isampler2DRect" << "usampler2DRect"
|
||||
<< "sampler1DArray" << "isampler1DArray" << "usampler1DArray"
|
||||
<< "sampler2DArray" << "isampler2DArray" << "usampler2DArray"
|
||||
<< "samplerCubeArray" << "isamplerCubeArray" << "usamplerCubeArray"
|
||||
<< "samplerBuffer" << "isamplerBuffer" << "usamplerBuffer"
|
||||
<< "sampler2DMS" << "isampler2DMS" << "usampler2DMS"
|
||||
<< "sampler2DMSArray" << "isampler2DMSArray" << "usampler2DMSArray"
|
||||
// Shadow Samplers:
|
||||
<< "sampler1DShadow"
|
||||
<< "sampler2DShadow"
|
||||
<< "samplerCubeShadow"
|
||||
<< "sampler2DRectShadow"
|
||||
<< "sampler1DArrayShadow"
|
||||
<< "sampler2DArrayShadow"
|
||||
<< "samplerCubeArrayShadow"
|
||||
// Image Types:
|
||||
<< "image1D" << "iimage1D" << "uimage1D"
|
||||
<< "image2D" << "iimage2D" << "uimage2D"
|
||||
<< "image3D" << "iimage3D" << "uimage3D"
|
||||
<< "imageCube" << "iimageCube" << "uimageCube"
|
||||
<< "image2DRect" << "iimage2DRect" << "uimage2DRect"
|
||||
<< "image1DArray" << "iimage1DArray" << "uimage1DArray"
|
||||
<< "image2DArray" << "iimage2DArray" << "uimage2DArray"
|
||||
<< "imageCubeArray" << "iimageCubeArray" << "uimageCubeArray"
|
||||
<< "imageBuffer" << "iimageBuffer" << "uimageBuffer"
|
||||
<< "image2DMS" << "iimage2DMS" << "uimage2DMS"
|
||||
<< "image2DMSArray" << "iimage2DMSArray" << "uimage2DMSArray"
|
||||
// Image Formats:
|
||||
// Floating-point: // Signed integer:
|
||||
<< "rgba32f" << "rgba32i"
|
||||
<< "rgba16f" << "rgba16i"
|
||||
<< "rg32f" << "rgba8i"
|
||||
<< "rg16f" << "rg32i"
|
||||
<< "r11f_g11f_b10f" << "rg16i"
|
||||
<< "r32f" << "rg8i"
|
||||
<< "r16f" << "r32i"
|
||||
<< "rgba16" << "r16i"
|
||||
<< "rgb10_a2" << "r8i"
|
||||
<< "rgba8" << "r8ui"
|
||||
<< "rg16" // Unsigned integer:
|
||||
<< "rg8" << "rgba32ui"
|
||||
<< "r16" << "rgba16ui"
|
||||
<< "r8" << "rgb10_a2ui"
|
||||
<< "rgba16_snorm" << "rgba8ui"
|
||||
<< "rgba8_snorm" << "rg32ui"
|
||||
<< "rg16_snorm" << "rg16ui"
|
||||
<< "rg8_snorm" << "rg8ui"
|
||||
<< "r16_snorm" << "r32ui"
|
||||
<< "r8_snorm" << "r16ui"
|
||||
;
|
||||
syntax_highlighter* sh_glsl = new syntax_highlighter(m_glsl_text->document());
|
||||
sh_glsl->AddWordRule(glsl_syntax, QColor(Qt::darkBlue)); // normal words like: soka, nani, or gomen
|
||||
sh_glsl->AddSimpleRule(QStringList("\\bGL_(?:[A-Z]|_)+\\b"), QColor(Qt::darkMagenta)); // constants like: GL_OMAE_WA_MOU_SHINDEIRU
|
||||
sh_glsl->AddSimpleRule(QStringList("\\bgl_(?:[A-Z]|[a-z]|_)+\\b"), QColor(Qt::darkCyan)); // reserved types like: gl_exploooooosion
|
||||
sh_glsl->AddSimpleRule(QStringList("\\B#[^\\s]+\\b"), QColor(Qt::darkGray)); // preprocessor instructions like: #waifu megumin
|
||||
sh_glsl->AddCommentRule("\/\/", QColor(Qt::darkGreen)); // comments like: // No comment
|
||||
sh_glsl->AddCommentRule("\/\*", QColor(Qt::darkGreen), true, "\*\/"); // comments like: /* I am trapped! Please help me! */
|
||||
|
||||
QSplitter* splitter = new QSplitter();
|
||||
splitter->addWidget(m_disasm_text);
|
||||
splitter->addWidget(m_glsl_text);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <QApplication>
|
||||
#include <QFontDatabase>
|
||||
#include <QCompleter>
|
||||
#include <QMenu>
|
||||
|
||||
constexpr auto qstr = QString::fromStdString;
|
||||
extern bool user_asked_for_frame_capture;
|
||||
@@ -22,6 +23,10 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
|
||||
QHBoxLayout* hbox_b_main = new QHBoxLayout();
|
||||
|
||||
m_list = new debugger_list(this);
|
||||
m_breakpoints_list = new QListWidget(this);
|
||||
m_breakpoints_list->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
m_breakpoints_list->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_breakpoints_list->setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
m_choice_units = new QComboBox(this);
|
||||
m_choice_units->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
m_choice_units->setMaxVisibleItems(30);
|
||||
@@ -33,6 +38,11 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
|
||||
m_choice_units->completer()->setMaxVisibleItems(30);
|
||||
m_choice_units->completer()->setFilterMode(Qt::MatchContains);
|
||||
|
||||
m_breakpoints_list_delete = new QAction("Delete", m_breakpoints_list);
|
||||
m_breakpoints_list_delete->setShortcut(Qt::Key_Delete);
|
||||
m_breakpoints_list_delete->setShortcutContext(Qt::WidgetShortcut);
|
||||
m_breakpoints_list->addAction(m_breakpoints_list_delete);
|
||||
|
||||
m_go_to_addr = new QPushButton(tr("Go To Address"), this);
|
||||
m_go_to_pc = new QPushButton(tr("Go To PC"), this);
|
||||
m_btn_capture = new QPushButton(tr("Capture"), this);
|
||||
@@ -58,9 +68,15 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
|
||||
m_list->setFont(m_mono);
|
||||
m_regs->setFont(m_mono);
|
||||
|
||||
m_right_splitter = new QSplitter(this);
|
||||
m_right_splitter->setOrientation(Qt::Vertical);
|
||||
m_right_splitter->addWidget(m_regs);
|
||||
m_right_splitter->addWidget(m_breakpoints_list);
|
||||
m_right_splitter->setStretchFactor(0, 1);
|
||||
|
||||
m_splitter = new QSplitter(this);
|
||||
m_splitter->addWidget(m_list);
|
||||
m_splitter->addWidget(m_regs);
|
||||
m_splitter->addWidget(m_right_splitter);
|
||||
|
||||
QHBoxLayout* hbox_w_list = new QHBoxLayout();
|
||||
hbox_w_list->addWidget(m_splitter);
|
||||
@@ -117,6 +133,10 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
|
||||
connect(m_choice_units, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &debugger_frame::OnSelectUnit);
|
||||
connect(this, &QDockWidget::visibilityChanged, this, &debugger_frame::EnableUpdateTimer);
|
||||
|
||||
connect(m_breakpoints_list, &QListWidget::itemDoubleClicked, this, &debugger_frame::OnBreakpointList_doubleClicked);
|
||||
connect(m_breakpoints_list, &QListWidget::customContextMenuRequested, this, &debugger_frame::OnBreakpointList_rightClicked);
|
||||
connect(m_breakpoints_list_delete, &QAction::triggered, this, &debugger_frame::OnBreakpointList_delete);
|
||||
|
||||
m_list->ShowAddr(CentrePc(m_list->m_pc));
|
||||
UpdateUnitList();
|
||||
}
|
||||
@@ -194,7 +214,7 @@ u32 debugger_frame::GetPc() const
|
||||
|
||||
u32 debugger_frame::CentrePc(u32 pc) const
|
||||
{
|
||||
return pc/* - ((m_item_count / 2) * 4)*/;
|
||||
return pc - ((m_list->m_item_count / 2) * 4);
|
||||
}
|
||||
|
||||
void debugger_frame::UpdateUI()
|
||||
@@ -473,9 +493,56 @@ void debugger_frame::EnableButtons(bool enable)
|
||||
|
||||
void debugger_frame::ClearBreakpoints()
|
||||
{
|
||||
//This is required to actually delete the breakpoints, not just visually.
|
||||
for (std::map<u32, bool>::iterator it = g_breakpoints.begin(); it != g_breakpoints.end(); it++)
|
||||
m_list->RemoveBreakPoint(it->first, false);
|
||||
|
||||
g_breakpoints.clear();
|
||||
}
|
||||
|
||||
void debugger_frame::OnBreakpointList_doubleClicked()
|
||||
{
|
||||
m_list->ShowAddr(CentrePc(m_breakpoints_list->currentItem()->data(Qt::UserRole).value<u32>()));
|
||||
m_list->setCurrentRow(16);
|
||||
}
|
||||
|
||||
void debugger_frame::OnBreakpointList_rightClicked(const QPoint &pos)
|
||||
{
|
||||
if (m_breakpoints_list->itemAt(pos) == NULL)
|
||||
return;
|
||||
|
||||
QMenu* menu = new QMenu();
|
||||
|
||||
if (m_breakpoints_list->selectedItems().count() == 1)
|
||||
{
|
||||
menu->addAction("Rename");
|
||||
menu->addSeparator();
|
||||
}
|
||||
menu->addAction(m_breakpoints_list_delete);
|
||||
|
||||
QAction* selectedItem = menu->exec(QCursor::pos());
|
||||
if (selectedItem != NULL)
|
||||
{
|
||||
if (selectedItem->text() == "Rename")
|
||||
{
|
||||
QListWidgetItem* currentItem = m_breakpoints_list->selectedItems().at(0);
|
||||
|
||||
currentItem->setFlags(currentItem->flags() | Qt::ItemIsEditable);
|
||||
m_breakpoints_list->editItem(currentItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void debugger_frame::OnBreakpointList_delete()
|
||||
{
|
||||
int selectedCount = m_breakpoints_list->selectedItems().count();
|
||||
|
||||
for (int i = selectedCount - 1; i >= 0; i--)
|
||||
{
|
||||
m_list->RemoveBreakPoint(m_breakpoints_list->item(i)->data(Qt::UserRole).value<u32>());
|
||||
}
|
||||
}
|
||||
|
||||
debugger_list::debugger_list(debugger_frame* parent) : QListWidget(parent)
|
||||
{
|
||||
m_pc = 0;
|
||||
@@ -543,12 +610,47 @@ void debugger_list::AddBreakPoint(u32 pc)
|
||||
{
|
||||
g_breakpoints.emplace(pc, false);
|
||||
ppu_breakpoint(pc);
|
||||
|
||||
const auto cpu = m_debugFrame->cpu.lock();
|
||||
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id_type() != 1 ? static_cast<SPUThread&>(*cpu).offset : 0;
|
||||
m_debugFrame->m_disasm->offset = (u8*)vm::base(cpu_offset);
|
||||
|
||||
m_debugFrame->m_disasm->disasm(m_debugFrame->m_disasm->dump_pc = pc);
|
||||
|
||||
QString breakpointItemText = qstr(m_debugFrame->m_disasm->last_opcode);
|
||||
|
||||
breakpointItemText.remove(10, 13);
|
||||
|
||||
QListWidgetItem* breakpointItem = new QListWidgetItem(breakpointItemText);
|
||||
breakpointItem->setTextColor(m_text_color_bp);
|
||||
breakpointItem->setBackgroundColor(m_color_bp);
|
||||
QVariant pcVariant;
|
||||
pcVariant.setValue(pc);
|
||||
breakpointItem->setData(Qt::UserRole, pcVariant);
|
||||
m_debugFrame->m_breakpoints_list->addItem(breakpointItem);
|
||||
}
|
||||
|
||||
void debugger_list::RemoveBreakPoint(u32 pc)
|
||||
void debugger_list::RemoveBreakPoint(u32 pc, bool eraseFromMap)
|
||||
{
|
||||
g_breakpoints.erase(pc);
|
||||
if(eraseFromMap)
|
||||
g_breakpoints.erase(pc);
|
||||
ppu_breakpoint(pc);
|
||||
|
||||
int breakpointsListCount = m_debugFrame->m_breakpoints_list->count();
|
||||
|
||||
for (int i = 0; i < breakpointsListCount; i++)
|
||||
{
|
||||
QListWidgetItem* currentItem = m_debugFrame->m_breakpoints_list->item(i);
|
||||
|
||||
if (currentItem->data(Qt::UserRole).value<u32>() == pc)
|
||||
{
|
||||
delete m_debugFrame->m_breakpoints_list->takeItem(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ShowAddr(m_pc - (m_item_count) * 4);
|
||||
|
||||
}
|
||||
|
||||
void debugger_list::keyPressEvent(QKeyEvent* event)
|
||||
|
||||
@@ -36,6 +36,7 @@ class debugger_frame : public QDockWidget
|
||||
Q_OBJECT
|
||||
|
||||
debugger_list* m_list;
|
||||
QSplitter* m_right_splitter;
|
||||
QFont m_mono;
|
||||
QTextEdit* m_regs;
|
||||
QPushButton* m_go_to_addr;
|
||||
@@ -61,8 +62,11 @@ class debugger_frame : public QDockWidget
|
||||
|
||||
std::shared_ptr<gui_settings> xgui_settings;
|
||||
|
||||
QAction* m_breakpoints_list_delete;
|
||||
|
||||
public:
|
||||
std::unique_ptr<CPUDisAsm> m_disasm;
|
||||
QListWidget* m_breakpoints_list;
|
||||
std::weak_ptr<cpu_thread> cpu;
|
||||
|
||||
public:
|
||||
@@ -93,6 +97,9 @@ Q_SIGNALS:
|
||||
public Q_SLOTS:
|
||||
void DoStep();
|
||||
private Q_SLOTS:
|
||||
void OnBreakpointList_doubleClicked();
|
||||
void OnBreakpointList_rightClicked(const QPoint &pos);
|
||||
void OnBreakpointList_delete();
|
||||
void OnSelectUnit();
|
||||
void Show_Val();
|
||||
void Show_PC();
|
||||
@@ -117,11 +124,11 @@ public:
|
||||
public:
|
||||
debugger_list(debugger_frame* parent);
|
||||
void ShowAddr(u32 addr);
|
||||
void RemoveBreakPoint(u32 pc, bool eraseFromMap = true);
|
||||
|
||||
private:
|
||||
bool IsBreakPoint(u32 pc);
|
||||
void AddBreakPoint(u32 pc);
|
||||
void RemoveBreakPoint(u32 pc);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent* event);
|
||||
@@ -129,3 +136,5 @@ protected:
|
||||
void wheelEvent(QWheelEvent* event);
|
||||
void resizeEvent(QResizeEvent* event);
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(u32);
|
||||
@@ -56,7 +56,6 @@ public:
|
||||
D3D12Adapter,
|
||||
VulkanAdapter,
|
||||
ForceHighpZ,
|
||||
AutoInvalidateCache,
|
||||
StrictRenderingMode,
|
||||
DisableVertexCache,
|
||||
DisableOcclusionQueries,
|
||||
@@ -83,6 +82,7 @@ public:
|
||||
StartOnBoot,
|
||||
StartGameFullscreen,
|
||||
ShowFPSInTitle,
|
||||
ShowTrophyPopups,
|
||||
ShowWelcomeScreen,
|
||||
|
||||
// Network
|
||||
@@ -209,7 +209,6 @@ private:
|
||||
{ GPUTextureScaling, { "Video", "Use GPU texture scaling"}},
|
||||
{ StretchToDisplayArea, { "Video", "Stretch To Display Area"}},
|
||||
{ ForceHighpZ, { "Video", "Force High Precision Z buffer"}},
|
||||
{ AutoInvalidateCache, { "Video", "Invalidate Cache Every Frame"}},
|
||||
{ StrictRenderingMode, { "Video", "Strict Rendering Mode"}},
|
||||
{ DisableVertexCache, { "Video", "Disable Vertex Cache"}},
|
||||
{ DisableOcclusionQueries, { "Video", "Disable ZCull Occlusion Queries" }},
|
||||
@@ -238,6 +237,7 @@ private:
|
||||
{StartOnBoot, { "Miscellaneous", "Automatically start games after boot" }},
|
||||
{StartGameFullscreen, { "Miscellaneous", "Start games in fullscreen mode"}},
|
||||
{ShowFPSInTitle, { "Miscellaneous", "Show FPS counter in window title"}},
|
||||
{ShowTrophyPopups, { "Miscellaneous", "Show trophy popups"}},
|
||||
{ShowWelcomeScreen, { "Miscellaneous", "Show Welcome Screen"}},
|
||||
|
||||
// Networking
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <QListView>
|
||||
#include <QMenuBar>
|
||||
#include <QMessageBox>
|
||||
#include <QProcess>
|
||||
#include <QTimer>
|
||||
#include <QUrl>
|
||||
#include <QLabel>
|
||||
@@ -37,6 +36,8 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> guiSettings, std:
|
||||
m_Text_Factor = xgui_settings->GetValue(GUI::gl_textFactor).toReal();
|
||||
m_showToolBar = xgui_settings->GetValue(GUI::gl_toolBarVisible).toBool();
|
||||
m_Icon_Color = xgui_settings->GetValue(GUI::gl_iconColor).value<QColor>();
|
||||
m_colSortOrder = xgui_settings->GetValue(GUI::gl_sortAsc).toBool() ? Qt::AscendingOrder : Qt::DescendingOrder;
|
||||
m_sortColumn = xgui_settings->GetValue(GUI::gl_sortCol).toInt();
|
||||
|
||||
m_oldLayoutIsList = m_isListLayout;
|
||||
|
||||
@@ -144,6 +145,7 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> guiSettings, std:
|
||||
m_gameList->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_gameList->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
m_gameList->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
m_gameList->verticalScrollBar()->installEventFilter(this);
|
||||
m_gameList->verticalScrollBar()->setSingleStep(20);
|
||||
m_gameList->horizontalScrollBar()->setSingleStep(20);
|
||||
m_gameList->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||
@@ -157,6 +159,7 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> guiSettings, std:
|
||||
m_gameList->horizontalHeader()->setDefaultSectionSize(150);
|
||||
m_gameList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
m_gameList->setAlternatingRowColors(true);
|
||||
m_gameList->installEventFilter(this);
|
||||
|
||||
m_gameList->setColumnCount(GUI::COLUMN_COUNT);
|
||||
m_gameList->setHorizontalHeaderItem( GUI::COLUMN_ICON, new QTableWidgetItem(tr("Icon")));
|
||||
@@ -545,17 +548,7 @@ static void open_dir(const std::string& spath)
|
||||
{
|
||||
fs::create_dir(spath);
|
||||
QString path = qstr(spath);
|
||||
QProcess* process = new QProcess();
|
||||
|
||||
#ifdef _WIN32
|
||||
std::string command = "explorer";
|
||||
std::replace(path.begin(), path.end(), '/', '\\');
|
||||
process->start("explorer", QStringList() << path);
|
||||
#elif __APPLE__
|
||||
process->start("open", QStringList() << path);
|
||||
#else
|
||||
process->start("xdg-open", QStringList() << path);
|
||||
#endif
|
||||
QDesktopServices::openUrl(QUrl("file:///" + path));
|
||||
}
|
||||
|
||||
void game_list_frame::doubleClickedSlot(const QModelIndex& index)
|
||||
@@ -639,6 +632,7 @@ void game_list_frame::ShowSpecifiedContextMenu(const QPoint &pos, int row)
|
||||
QAction* removeGame = myMenu.addAction(tr("&Remove"));
|
||||
QAction* removeConfig = myMenu.addAction(tr("&Remove Custom Configuration"));
|
||||
QAction* deleteShadersCache = myMenu.addAction(tr("&Delete Shaders Cache"));
|
||||
QAction* deleteLLVMCache = myMenu.addAction(tr("&Delete LLVM Cache"));
|
||||
myMenu.addSeparator();
|
||||
QAction* openGameFolder = myMenu.addAction(tr("&Open Install Folder"));
|
||||
QAction* openConfig = myMenu.addAction(tr("&Open Config Folder"));
|
||||
@@ -679,6 +673,31 @@ void game_list_frame::ShowSpecifiedContextMenu(const QPoint &pos, int row)
|
||||
{
|
||||
DeleteShadersCache(row);
|
||||
});
|
||||
|
||||
connect(deleteLLVMCache, &QAction::triggered, [=]()
|
||||
{
|
||||
if (QMessageBox::question(this, tr("Confirm Delete"), tr("Delete LLVM cache?")) == QMessageBox::Yes)
|
||||
{
|
||||
const std::string config_base_dir = fs::get_config_dir() + "data/" + m_game_data[row].info.serial;
|
||||
|
||||
for (auto&& subdir : fs::dir{config_base_dir})
|
||||
{
|
||||
if (!subdir.is_directory || subdir.name == "." || subdir.name == "..")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto&& entry : fs::dir{config_base_dir + "/" + subdir.name})
|
||||
{
|
||||
if (entry.name.size() >= 4 && entry.name.compare(entry.name.size() - 4, 4, ".obj", 4) == 0)
|
||||
{
|
||||
fs::remove_file(config_base_dir + "/" + subdir.name + "/" + entry.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
connect(openGameFolder, &QAction::triggered, [=]()
|
||||
{
|
||||
open_dir(currGame.path);
|
||||
@@ -950,6 +969,42 @@ void game_list_frame::resizeEvent(QResizeEvent *event)
|
||||
QDockWidget::resizeEvent(event);
|
||||
}
|
||||
|
||||
bool game_list_frame::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
// Zoom gamelist/gamegrid
|
||||
if (event->type() == QEvent::Wheel && (object == m_gameList->verticalScrollBar() || object == m_xgrid->verticalScrollBar()))
|
||||
{
|
||||
QWheelEvent *wheelEvent = static_cast<QWheelEvent *>(event);
|
||||
|
||||
if (wheelEvent->modifiers() & Qt::ControlModifier)
|
||||
{
|
||||
QPoint numSteps = wheelEvent->angleDelta() / 8 / 15; // http://doc.qt.io/qt-5/qwheelevent.html#pixelDelta
|
||||
const int value = numSteps.y();
|
||||
m_Slider_Size->setValue(m_Slider_Size->value() + value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (event->type() == QEvent::KeyPress && (object == m_gameList || object == m_xgrid))
|
||||
{
|
||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||
|
||||
if (keyEvent->modifiers() & Qt::ControlModifier)
|
||||
{
|
||||
if (keyEvent->key() == Qt::Key_Plus)
|
||||
{
|
||||
m_Slider_Size->setValue(m_Slider_Size->value() + 1);
|
||||
return true;
|
||||
}
|
||||
else if (keyEvent->key() == Qt::Key_Minus)
|
||||
{
|
||||
m_Slider_Size->setValue(m_Slider_Size->value() - 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QDockWidget::eventFilter(object, event);
|
||||
}
|
||||
|
||||
/**
|
||||
Cleans and readds entries to table widget in UI.
|
||||
*/
|
||||
@@ -1099,6 +1154,8 @@ void game_list_frame::PopulateGameGrid(uint maxCols, const QSize& image_size, co
|
||||
|
||||
m_xgrid->resizeColumnsToContents();
|
||||
m_xgrid->resizeRowsToContents();
|
||||
m_xgrid->installEventFilter(this);
|
||||
m_xgrid->verticalScrollBar()->installEventFilter(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -103,9 +103,9 @@ namespace category // (see PARAM.SFO in psdevwiki.com) TODO: Disc Categories
|
||||
|
||||
inline bool CategoryInMap(const std::string& cat, const q_from_char& map)
|
||||
{
|
||||
auto map_contains_category = [cat](std::pair<std::string, const QString> p)
|
||||
auto map_contains_category = [s = qstr(cat)](const auto& p)
|
||||
{
|
||||
return p.second == qstr(cat);
|
||||
return p.second == s;
|
||||
};
|
||||
|
||||
return std::find_if(map.begin(), map.end(), map_contains_category) != map.end();
|
||||
@@ -236,6 +236,7 @@ protected:
|
||||
/** Override inherited method from Qt to allow signalling when close happened.*/
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
bool eventFilter(QObject *object, QEvent *event);
|
||||
private:
|
||||
QPixmap PaintedPixmap(const QImage& img, bool paintConfigIcon = false);
|
||||
bool Boot(const GameInfo& info);
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
#include "../Emu/Io/Null/NullPadHandler.h"
|
||||
#include "../Emu/System.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
|
||||
input_config input_cfg;
|
||||
|
||||
// taken from https://stackoverflow.com/a/30818424/8353754
|
||||
@@ -38,6 +41,13 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
|
||||
{
|
||||
setWindowTitle(tr("Gamepads Settings"));
|
||||
|
||||
// read tooltips from json
|
||||
QFile json_file(":/Json/tooltips.json");
|
||||
json_file.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||
QJsonObject json_input = QJsonDocument::fromJson(json_file.readAll()).object().value("input").toObject();
|
||||
json_file.close();
|
||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||
|
||||
QVBoxLayout *dialog_layout = new QVBoxLayout();
|
||||
QHBoxLayout *all_players = new QHBoxLayout();
|
||||
|
||||
@@ -90,6 +100,11 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
|
||||
co_inputtype[i] = new QComboBox();
|
||||
co_inputtype[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
|
||||
co_inputtype[i]->view()->setTextElideMode(Qt::ElideNone);
|
||||
#ifdef WIN32
|
||||
co_inputtype[i]->setToolTip(json_input["padHandlerBox"].toString());
|
||||
#else
|
||||
co_inputtype[i]->setToolTip(json_input["padHandlerBox_Linux"].toString());
|
||||
#endif
|
||||
ppad_layout->addWidget(co_inputtype[i]);
|
||||
|
||||
co_deviceID[i] = new QComboBox();
|
||||
|
||||
@@ -22,7 +22,7 @@ gl_gs_frame::gl_gs_frame(int w, int h, QIcon appIcon, bool disableMouse)
|
||||
setFormat(m_format);
|
||||
}
|
||||
|
||||
void* gl_gs_frame::make_context()
|
||||
draw_context_t gl_gs_frame::make_context()
|
||||
{
|
||||
auto context = new QOpenGLContext();
|
||||
context->setFormat(m_format);
|
||||
@@ -33,16 +33,33 @@ void* gl_gs_frame::make_context()
|
||||
|
||||
void gl_gs_frame::set_current(draw_context_t ctx)
|
||||
{
|
||||
if (!((QOpenGLContext*)ctx.get())->makeCurrent(this))
|
||||
if (!((QOpenGLContext*)ctx)->makeCurrent(this))
|
||||
{
|
||||
create();
|
||||
((QOpenGLContext*)ctx.get())->makeCurrent(this);
|
||||
((QOpenGLContext*)ctx)->makeCurrent(this);
|
||||
}
|
||||
}
|
||||
|
||||
void gl_gs_frame::delete_context(void* ctx)
|
||||
void gl_gs_frame::delete_context(draw_context_t ctx)
|
||||
{
|
||||
((QOpenGLContext*)ctx)->deleteLater();
|
||||
|
||||
auto gl_ctx = (QOpenGLContext*)ctx;
|
||||
gl_ctx->doneCurrent();
|
||||
|
||||
#ifndef _WIN32
|
||||
delete gl_ctx;
|
||||
#else
|
||||
//AMD driver crashes when executing wglDeleteContext
|
||||
//Catch with SEH
|
||||
__try
|
||||
{
|
||||
delete gl_ctx;
|
||||
}
|
||||
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
|
||||
{
|
||||
LOG_FATAL(RSX, "Your graphics driver just crashed whilst cleaning up. All consumed VRAM should have been released, but you may want to restart the emulator just in case");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void gl_gs_frame::flip(draw_context_t context, bool skip_frame)
|
||||
@@ -52,6 +69,6 @@ void gl_gs_frame::flip(draw_context_t context, bool skip_frame)
|
||||
//Do not swap buffers if frame skip is active
|
||||
if (skip_frame) return;
|
||||
|
||||
((QOpenGLContext*)context.get())->makeCurrent(this);
|
||||
((QOpenGLContext*)context.get())->swapBuffers(this);
|
||||
((QOpenGLContext*)context)->makeCurrent(this);
|
||||
((QOpenGLContext*)context)->swapBuffers(this);
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@ private:
|
||||
public:
|
||||
gl_gs_frame(int w, int h, QIcon appIcon, bool disableMouse);
|
||||
|
||||
void* make_context() override;
|
||||
draw_context_t make_context() override;
|
||||
void set_current(draw_context_t context) override;
|
||||
void delete_context(void* context) override;
|
||||
void delete_context(draw_context_t context) override;
|
||||
void flip(draw_context_t context, bool skip_frame=false) override;
|
||||
};
|
||||
|
||||
+84
-62
@@ -26,7 +26,7 @@ gs_frame::gs_frame(const QString& title, int w, int h, QIcon appIcon, bool disab
|
||||
version = version.substr(0 , version.find_last_of("-"));
|
||||
|
||||
//Add branch to version on frame , unless it's master.
|
||||
if (rpcs3::get_branch() != "master" || rpcs3::get_branch() != "HEAD")
|
||||
if (rpcs3::get_branch().compare("master") != 0 && rpcs3::get_branch().compare("HEAD") != 0)
|
||||
{
|
||||
version = version + "-" + rpcs3::get_branch();
|
||||
}
|
||||
@@ -154,7 +154,7 @@ void* gs_frame::handle() const
|
||||
#endif
|
||||
}
|
||||
|
||||
void* gs_frame::make_context()
|
||||
draw_context_t gs_frame::make_context()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
@@ -164,7 +164,7 @@ void gs_frame::set_current(draw_context_t ctx)
|
||||
Q_UNUSED(ctx);
|
||||
}
|
||||
|
||||
void gs_frame::delete_context(void* ctx)
|
||||
void gs_frame::delete_context(draw_context_t ctx)
|
||||
{
|
||||
Q_UNUSED(ctx);
|
||||
}
|
||||
@@ -246,77 +246,99 @@ bool gs_frame::event(QEvent* ev)
|
||||
bool gs_frame::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
//Wait for consumer to clear notification pending flag
|
||||
while (wm_event_raised.load(std::memory_order_consume));
|
||||
|
||||
if (wm_event_queue_enabled.load(std::memory_order_consume) && !Emu.IsStopped())
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(wm_event_lock);
|
||||
MSG* msg = static_cast<MSG*>(message);
|
||||
switch (msg->message)
|
||||
{
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
{
|
||||
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & SWP_NOSIZE;
|
||||
if (m_in_sizing_event || flags != 0)
|
||||
break;
|
||||
//Wait for consumer to clear notification pending flag
|
||||
while (wm_event_raised.load(std::memory_order_consume) && !Emu.IsStopped());
|
||||
|
||||
//About to resize
|
||||
m_in_sizing_event = true;
|
||||
m_interactive_resize = false;
|
||||
m_raised_event = wm_event::geometry_change_notice;
|
||||
wm_event_raised.store(true);
|
||||
break;
|
||||
}
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
{
|
||||
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & (SWP_NOSIZE | SWP_NOMOVE);
|
||||
if (!m_in_sizing_event || m_user_interaction_active || flags == (SWP_NOSIZE | SWP_NOMOVE))
|
||||
break;
|
||||
|
||||
if (flags & SWP_NOSIZE)
|
||||
m_raised_event = wm_event::window_moved;
|
||||
else
|
||||
m_raised_event = wm_event::window_resized;
|
||||
|
||||
//Just finished resizing using maximize or SWP
|
||||
m_in_sizing_event = false;
|
||||
wm_event_raised.store(true);
|
||||
break;
|
||||
}
|
||||
case WM_ENTERSIZEMOVE:
|
||||
m_user_interaction_active = true;
|
||||
break;
|
||||
case WM_EXITSIZEMOVE:
|
||||
m_user_interaction_active = false;
|
||||
if (m_in_sizing_event && !m_user_interaction_active)
|
||||
std::lock_guard<std::mutex> lock(wm_event_lock);
|
||||
MSG* msg = static_cast<MSG*>(message);
|
||||
switch (msg->message)
|
||||
{
|
||||
//Just finished resizing using manual interaction. The corresponding WM_SIZE is consumed before this event fires
|
||||
m_raised_event = m_interactive_resize ? wm_event::window_resized : wm_event::window_moved;
|
||||
case WM_WINDOWPOSCHANGING:
|
||||
{
|
||||
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & SWP_NOSIZE;
|
||||
if (m_in_sizing_event || flags != 0)
|
||||
break;
|
||||
|
||||
//About to resize
|
||||
m_in_sizing_event = true;
|
||||
m_interactive_resize = false;
|
||||
m_raised_event = wm_event::geometry_change_notice;
|
||||
wm_event_raised.store(true);
|
||||
break;
|
||||
}
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
{
|
||||
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & (SWP_NOSIZE | SWP_NOMOVE);
|
||||
if (!m_in_sizing_event || m_user_interaction_active || flags == (SWP_NOSIZE | SWP_NOMOVE))
|
||||
break;
|
||||
|
||||
if (flags & SWP_NOSIZE)
|
||||
{
|
||||
m_raised_event = wm_event::window_moved;
|
||||
}
|
||||
else
|
||||
{
|
||||
LPWINDOWPOS wpos = reinterpret_cast<LPWINDOWPOS>(msg->lParam);
|
||||
if (wpos->cx <= GetSystemMetrics(SM_CXMINIMIZED) || wpos->cy <= GetSystemMetrics(SM_CYMINIMIZED))
|
||||
{
|
||||
//Minimize event
|
||||
m_minimized = true;
|
||||
m_raised_event = wm_event::window_minimized;
|
||||
}
|
||||
else if (m_minimized)
|
||||
{
|
||||
m_minimized = false;
|
||||
m_raised_event = wm_event::window_restored;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_raised_event = wm_event::window_resized;
|
||||
}
|
||||
}
|
||||
|
||||
//Just finished resizing using maximize or SWP
|
||||
m_in_sizing_event = false;
|
||||
wm_event_raised.store(true);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case WM_SIZE:
|
||||
{
|
||||
if (m_user_interaction_active)
|
||||
case WM_ENTERSIZEMOVE:
|
||||
m_user_interaction_active = true;
|
||||
break;
|
||||
case WM_EXITSIZEMOVE:
|
||||
m_user_interaction_active = false;
|
||||
if (m_in_sizing_event && !m_user_interaction_active)
|
||||
{
|
||||
//Just finished resizing using manual interaction. The corresponding WM_SIZE is consumed before this event fires
|
||||
m_raised_event = m_interactive_resize ? wm_event::window_resized : wm_event::window_moved;
|
||||
m_in_sizing_event = false;
|
||||
wm_event_raised.store(true);
|
||||
}
|
||||
break;
|
||||
case WM_SIZE:
|
||||
{
|
||||
//Interaction is a resize not a move
|
||||
m_interactive_resize = true;
|
||||
if (m_user_interaction_active)
|
||||
{
|
||||
//Interaction is a resize not a move
|
||||
m_interactive_resize = true;
|
||||
}
|
||||
else if (m_in_sizing_event)
|
||||
{
|
||||
//Any other unexpected resize mode will give an unconsumed WM_SIZE event
|
||||
m_raised_event = wm_event::window_resized;
|
||||
m_in_sizing_event = false;
|
||||
wm_event_raised.store(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (m_in_sizing_event)
|
||||
{
|
||||
//Any other unexpected resize mode will give an unconsumed WM_SIZE event
|
||||
m_raised_event = wm_event::window_resized;
|
||||
m_in_sizing_event = false;
|
||||
wm_event_raised.store(true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Do not enter DefWndProc until the consumer has consumed the message
|
||||
while (wm_event_raised.load(std::memory_order_consume) && !Emu.IsStopped());
|
||||
}
|
||||
|
||||
//Do not enter DefWndProc until the consumer has consumed the message
|
||||
while (wm_event_raised.load(std::memory_order_consume));
|
||||
#endif
|
||||
|
||||
//Let the default handler deal with this. Only the notification is required
|
||||
|
||||
@@ -17,10 +17,15 @@ class gs_frame : public QWindow, public GSFrameBase
|
||||
bool m_in_sizing_event = false; //a signal that the window is about to be resized was received
|
||||
bool m_user_interaction_active = false; //a signal indicating the window is being manually moved/resized was received
|
||||
bool m_interactive_resize = false; //resize signal received while dragging window
|
||||
bool m_minimized = false;
|
||||
|
||||
public:
|
||||
gs_frame(const QString& title, int w, int h, QIcon appIcon, bool disableMouse);
|
||||
|
||||
draw_context_t make_context() override;
|
||||
void set_current(draw_context_t context) override;
|
||||
void delete_context(draw_context_t context) override;
|
||||
|
||||
wm_event get_default_wm_event() const override;
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *event);
|
||||
@@ -37,9 +42,6 @@ protected:
|
||||
|
||||
void* handle() const override;
|
||||
|
||||
void* make_context() override;
|
||||
void set_current(draw_context_t context) override;
|
||||
void delete_context(void* context) override;
|
||||
void flip(draw_context_t context, bool skip_frame=false) override;
|
||||
int client_width() override;
|
||||
int client_height() override;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user