Compare commits

...

35 Commits

Author SHA1 Message Date
Zangetsu38 976260577d Test 2018-02-24 04:14:59 +01:00
Nekotekina 89f5292057 Fixup 2018-02-24 04:14:59 +01:00
Nekotekina b89c8ec660 Initial cpu_translator impl 2018-02-24 04:14:59 +01:00
Farseer 51278f108c Some reverting 2018-02-24 04:14:59 +01:00
Farseer d2fc690ad2 Correct intersection check 2018-02-24 04:14:59 +01:00
Farseer f9dc36e8f3 Set log level back to notice 2018-02-24 04:14:59 +01:00
Farseer 1b63bf130c Performance improvements and CR fixes 2018-02-24 04:14:59 +01:00
Farseer 15330a86ee Always invalidate code as temp fix
Until I find out what else triggers SPU invalidation
2018-02-24 04:14:58 +01:00
Farseer 72911de000 Temporary crash fix 2018-02-24 04:14:58 +01:00
Farseer c3ea27e378 Maybe fix linux build
Who knows without a linux VM. I sure don't. Only 1 way to find out quickly. Nobody reads these notes anyway ¯\_(ツ)_/¯
2018-02-24 04:14:58 +01:00
Farseer 2d4af4c88c Initial optimizations (Squashed to fix submodules) 2018-02-24 04:14:58 +01:00
Zangetsu38 db96c355ce Update LLVM 6.0. 2018-02-24 04:14:58 +01:00
Zion Nimchuk 2b3df37400 Implement LLVM 6 Polly 2018-02-24 04:14:58 +01:00
Zangetsu38 2cfd552b1d Update Project to Visual Studio 2017.
Fix VS2017 compile by clienthax (PPUAnalyser.cpp).
2018-02-24 04:14:58 +01:00
scribam 53d6fc17dd Add callbacks for cellMusic 2018-02-24 04:14:58 +01:00
Nikolay Amiantov fdd5e4ee1e Fix quoting in cmake 2018-02-24 04:14:58 +01:00
Megamouse 4f4aa2cac5 Update for Qt 5.10 (#4202)
* Update Readme for Qt 5.10

* Update cmake for Qt 5.10

* Update travis to Qt 5.10.1
2018-02-24 04:14:58 +01:00
Zangetsu38 a90522eda1 Some Change in Gui. 2018-02-24 04:14:58 +01:00
Megamouse 59b83bbf7a Qt: use setAttribute(AA_DisableWindowContextHelpButton) instead of flags
probably needs Qt 5.10.1 to work propery
2018-02-24 04:14:58 +01:00
Megamouse ac37ef327b sceNpTrophyGetRequiredDiskSpace: take vfs into account for trophy dir 2018-02-24 04:14:57 +01:00
Megamouse 72a14ef8f8 Qt: add translation to save manager messageboxes 2018-02-24 04:14:57 +01:00
Megamouse 80900a5659 Qt: improve VFS dialog a bit
- use normal selection instead of doubleclick
- move SaveSettings out of the tabs to reduce file access
- translate EmptyPath as well
- some other minor refactors to reduce lines of code
2018-02-24 04:14:57 +01:00
kd-11 6298d21d7a rsx/vk/gl: Enforce format matching for render target resources. Fall back to raw data copy if match fails 2018-02-23 22:52:15 +03:00
kd-11 dcf3ffdce0 rsx/fp: Improve rgister component gather detection
- Also avoids clobbering register data by keeping gathered bits in a temp var
2018-02-23 22:50:46 +03:00
kd-11 932d9c4309 rsx/vulkan: Add post-compilation key validation and dynamically determine attachment write maks based on decompiled shader
- A new step is added between decompilation and pipeline object creation allowing for properties to be updated based on shader contents
- Allos masking off attachment writes that are unmodified in the shader
2018-02-23 17:37:03 +03:00
kd-11 a64bb4a0ec facepalm: _mm_andnot is ~A&B not A&~B as the name would suggest 2018-02-23 16:01:25 +03:00
kd-11 fa6d03d557 rsx: Nvidia driver compatibility workarounds
- Sanitize NaN values before they reach the driver. On nvidia (X * NaN = X)
2018-02-23 11:35:04 +03:00
kd-11 79ec982838 gl: Hotfix
- Reset mapping offsets after window is changed!
2018-02-22 11:43:44 +03:00
kd-11 963b431805 rsx/gl/vk: Improvements
- gl: Do not call makeCurrent every flip - it is already called in set_current()
- gl: Improve ring buffer behaviour; use sliding window to view buffers larger than maximum viewable hardware range
  NV hardware can only view 128M at a time
- gl/vk: Bump transform constant heap size When lots of draw calls are issued, the heap is exhaused very fast (8k per draw)
- gl: Remove CLIENT_STORAGE_BIT from ring buffers. Performance is marginally better without this flag (at least on windows)
2018-02-22 11:15:37 +03:00
kd-11 5ede331da5 gl: inline draw_state::test_property because msvc doesnt do it for us 2018-02-22 11:15:37 +03:00
kd-11 6828d4b3c2 rsx/gl: Minor fixes
- Identify depth textures reaching the gpu via shader_read upload path
- Use correct timestamp counter for opengl
2018-02-21 23:44:16 +03:00
kd-11 1411de38f3 rsx/vk: More optimizations
- Do not bother rechecking the dirty sampler pool for hits. Its faster to create new sampler than to search the pool
- Reserve some memory on vertex layout struct to reduce reallocation penalty
2018-02-21 21:34:40 +03:00
kd-11 5f33949cec vulkan: Optimize vertex data upload
- Reuse buffer views as much as possible, vkCreateBufferView is slow on NV
  Implemented as a large sliding window, reuseable until it is filled
2018-02-21 21:34:39 +03:00
kd-11 0c48fd25a0 rsx/vk: Cleanup
- Silence some warnings, remove dprints
2018-02-21 14:10:53 +03:00
kd-11 20b4c5d323 vulkan: Swapchains reimplemented
- Adds support for abstract implementations
- Adds native windowing implementations for WIN32 and X11 as fallbacks
  when present support is lacking (headless configs)
2018-02-21 14:10:53 +03:00
114 changed files with 2340 additions and 1626 deletions
+1
View File
@@ -60,6 +60,7 @@ rpcs3/git-version.h
# Visual Studio Files # Visual Studio Files
.vs/* .vs/*
.vscode/* .vscode/*
*.ipch
*.vspx *.vspx
*.psess *.psess
*.VC.* *.VC.*
+7 -3
View File
@@ -7,14 +7,14 @@
ignore = dirty ignore = dirty
[submodule "llvm"] [submodule "llvm"]
path = llvm path = llvm
url = https://github.com/RPCS3/llvm url = https://github.com/llvm-mirror/llvm
branch = release_60 branch = release_60
[submodule "GSL"] [submodule "GSL"]
path = 3rdparty/GSL path = 3rdparty/GSL
url = https://github.com/Microsoft/GSL.git url = https://github.com/Microsoft/GSL.git
[submodule "libpng"] [submodule "libpng"]
path = 3rdparty/libpng path = 3rdparty/libpng
url = https://github.com/RPCS3/libpng url = https://github.com/Zangetsu38/libpng
ignore = dirty ignore = dirty
[submodule "Vulkan/glslang"] [submodule "Vulkan/glslang"]
path = Vulkan/glslang path = Vulkan/glslang
@@ -33,7 +33,7 @@
url = https://github.com/madler/zlib url = https://github.com/madler/zlib
[submodule "3rdparty/hidapi"] [submodule "3rdparty/hidapi"]
path = 3rdparty/hidapi path = 3rdparty/hidapi
url = https://github.com/RPCS3/hidapi url = https://github.com/Zangetsu38/hidapi
branch = master branch = master
ignore = dirty ignore = dirty
[submodule "3rdparty/Optional"] [submodule "3rdparty/Optional"]
@@ -42,3 +42,7 @@
[submodule "3rdparty/pugixml"] [submodule "3rdparty/pugixml"]
path = 3rdparty/pugixml path = 3rdparty/pugixml
url = https://github.com/zeux/pugixml url = https://github.com/zeux/pugixml
[submodule "polly"]
path = polly
url = https://github.com/llvm-mirror/polly
branch = release_60
+8 -8
View File
@@ -52,7 +52,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 - 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 - mkdir build
- cd build - cd build
- export CMAKE_PREFIX_PATH=~/Qt/5.10.0/gcc_64/lib/cmake - export CMAKE_PREFIX_PATH=~/Qt/5.10.1/gcc_64/lib/cmake
- export CXXFLAGS="$CXXFLAGS -DTRAVIS=true"; - export CXXFLAGS="$CXXFLAGS -DTRAVIS=true";
- if [ "$TRAVIS_PULL_REQUEST" = false ]; then - if [ "$TRAVIS_PULL_REQUEST" = false ]; then
export CXXFLAGS="$CXXFLAGS -DBRANCH=$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH"; export CXXFLAGS="$CXXFLAGS -DBRANCH=$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH";
@@ -63,20 +63,20 @@ before_script:
- ninja - ninja
- # AppImage generation - # AppImage generation
- if [ -n "$UPLOAD_URL" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$CC" = "clang" ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then - if [ -n "$UPLOAD_URL" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$CC" = "clang" ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then
export LD_LIBRARY_PATH=~/Qt/5.10.0/gcc_64/lib; export LD_LIBRARY_PATH=~/Qt/5.10.1/gcc_64/lib;
DESTDIR=appdir ninja install ; find appdir/ ; DESTDIR=appdir ninja install ; find appdir/ ;
find ../bin ; find ../bin ;
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" ; wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" ;
chmod a+x linuxdeployqt*.AppImage ; chmod a+x linuxdeployqt*.AppImage ;
export PATH=~/Qt/5.10.0/gcc_64/bin/:${PATH} ; export PATH=~/Qt/5.10.1/gcc_64/bin/:${PATH} ;
./linuxdeployqt*.AppImage --appimage-extract ; ./linuxdeployqt*.AppImage --appimage-extract ;
./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -bundle-non-qt-libs ; ./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -bundle-non-qt-libs ;
mkdir ./appdir/usr/plugins/xcbglintegrations/ ; mkdir ./appdir/usr/plugins/xcbglintegrations/ ;
mkdir ./appdir/usr/plugins/imageformats/ ; mkdir ./appdir/usr/plugins/imageformats/ ;
cp ~/Qt/5.10.0/gcc_64/lib/libQt5Svg.so.5 ./appdir/usr/lib/ ; cp ~/Qt/5.10.1/gcc_64/lib/libQt5Svg.so.5 ./appdir/usr/lib/ ;
cp ~/Qt/5.10.0/gcc_64/plugins/xcbglintegrations/* ./appdir/usr/plugins/xcbglintegrations/ ; cp ~/Qt/5.10.1/gcc_64/plugins/xcbglintegrations/* ./appdir/usr/plugins/xcbglintegrations/ ;
cp ~/Qt/5.10.0/gcc_64/plugins/imageformats/* ./appdir/usr/plugins/imageformats/ ; cp ~/Qt/5.10.1/gcc_64/plugins/imageformats/* ./appdir/usr/plugins/imageformats/ ;
cp ~/Qt/5.10.0/gcc_64/plugins/platforms/* ./appdir/usr/plugins/platforms/ ; cp ~/Qt/5.10.1/gcc_64/plugins/platforms/* ./appdir/usr/plugins/platforms/ ;
rm ./appdir/usr/lib/libfreetype.so.6 ; rm ./appdir/usr/lib/libfreetype.so.6 ;
export PATH=${TRAVIS_BUILD_DIR}/build/squashfs-root/usr/bin/:${PATH} ; export PATH=${TRAVIS_BUILD_DIR}/build/squashfs-root/usr/bin/:${PATH} ;
./squashfs-root/usr/bin/appimagetool ${TRAVIS_BUILD_DIR}/build/appdir ; ./squashfs-root/usr/bin/appimagetool ${TRAVIS_BUILD_DIR}/build/appdir ;
@@ -117,7 +117,7 @@ addons:
- libstdc++-5-dev - libstdc++-5-dev
- lib32stdc++6 - lib32stdc++6
- zlib1g-dev - zlib1g-dev
# We need to install qt 5.10.0 manually because the version trusty provides is too old. # We need to install qt 5.10.1 manually because the version trusty provides is too old.
#- qtbase5-dev #- qtbase5-dev
- libudev-dev - libudev-dev
- libevdev-dev - libevdev-dev
+6 -6
View File
@@ -20,15 +20,15 @@ If you want to contribute please take a look at the [Coding Style](https://githu
## Dependencies ## Dependencies
### Windows ### Windows
* [Visual Studio 2015](https://www.visualstudio.com/vs/older-downloads/) * [Visual Studio 2017](https://www.visualstudio.com/en/downloads/)
* [Visual C++ Redistributable Packages for Visual Studio 2015](http://www.microsoft.com/en-us/download/details.aspx?id=48145) * [Visual C++ Redistributable Packages for Visual Studio 2017](https://go.microsoft.com/fwlink/?LinkId=746572)
* [Cmake 3.1.0+](https://www.cmake.org/download/) (required; add to PATH) * [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) * [Python 3.3+](https://www.python.org/downloads/) (required; add to PATH)
* [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) * [Qt 5.10+](https://www.qt.io/download-open-source/) (required; add QTDIR environment variable if you do not want to use the Visual Studio Qt Plugin: e.g. `<QtInstallFolder>\5.10.1\msvc2017_64\`)
* [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2015) (optional; see above) * [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2015) (optional; see above)
### Linux ### Linux
* [Qt 5.7+](https://www.qt.io/download-open-source/) * [Qt 5.10+](https://www.qt.io/download-open-source/)
* GCC 5.1+ or Clang 3.5.0+ ([not GCC 6.1](https://github.com/RPCS3/rpcs3/issues/1691)) * GCC 5.1+ or Clang 3.5.0+ ([not GCC 6.1](https://github.com/RPCS3/rpcs3/issues/1691))
* Debian & Ubuntu: `sudo apt-get install cmake build-essential libasound2-dev libpulse-dev libopenal-dev libglew-dev zlib1g-dev libedit-dev libvulkan-dev libudev-dev git qt5-default` * Debian & Ubuntu: `sudo apt-get install cmake build-essential libasound2-dev libpulse-dev libopenal-dev libglew-dev zlib1g-dev libedit-dev libvulkan-dev libudev-dev git qt5-default`
* Arch: `sudo pacman -S glew openal cmake llvm qt5-base` * Arch: `sudo pacman -S glew openal cmake llvm qt5-base`
@@ -48,14 +48,14 @@ To initialize the repository don't forget to execute `git submodule update --ini
### Configuring Qt ### Configuring Qt
*If you're using Visual Studio 2017 without Qt plugin support (or simply dont want to use it):* *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.8\msvc2015_64\` </br> 1) Add `QTDIR` environment variable and set it to e.g `<QtInstallFolder>\5.10.1\msvc2017_64\` </br>
Open `rpcs3.sln` Open `rpcs3.sln`
*If you wish to use the Visual Studio plugin for Qt:* </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.8\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.10.1\msvc2017_64`. </br>
2) While selecting the rpcs3qt project, go to Qt5->Project Setting and select the version you added. 2) While selecting the rpcs3qt project, go to Qt5->Project Setting and select the version you added.
### Building the projects ### Building the projects
+3 -3
View File
@@ -293,7 +293,7 @@ struct MemoryManager : llvm::RTDyldMemoryManager
return RTDyldMemoryManager::registerEHFrames(addr, load_addr, size); return RTDyldMemoryManager::registerEHFrames(addr, load_addr, size);
} }
void deregisterEHFrames(u8* addr, u64 load_addr, std::size_t size) override virtual void deregisterEHFrames() override
{ {
} }
}; };
@@ -376,11 +376,11 @@ public:
LOG_SUCCESS(GENERAL, "LLVM: Created module: %s", module->getName().data()); LOG_SUCCESS(GENERAL, "LLVM: Created module: %s", module->getName().data());
} }
static std::unique_ptr<llvm::MemoryBuffer> load(const std::string& path) static std::unique_ptr<llvm::WritableMemoryBuffer> load(const std::string& path)
{ {
if (fs::file cached{path, fs::read}) if (fs::file cached{path, fs::read})
{ {
auto buf = llvm::MemoryBuffer::getNewUninitMemBuffer(cached.size()); auto buf = llvm::WritableMemoryBuffer::getNewUninitMemBuffer(cached.size());
cached.read(const_cast<char*>(buf->getBufferStart()), buf->getBufferSize()); cached.read(const_cast<char*>(buf->getBufferStart()), buf->getBufferSize());
return buf; return buf;
} }
+8 -6
View File
@@ -1890,32 +1890,34 @@ u16 thread_ctrl::get_affinity_mask(thread_class group)
} }
case native_core_arrangement::amd_ccx: case native_core_arrangement::amd_ccx:
{ {
u16 spu_mask, ppu_mask, rsx_mask; u16 spu_mask, ppu_mask, rsx_mask, general;
if (thread_count >= 16) if (thread_count >= 16)
{ {
// Threadripper, R7 // Threadripper, R7
// Assign threads 8-16 // Assign threads 1-16
// It appears some windows code is bound to lower core addresses, binding 8-16 is alot faster than 0-7 // It appears some windows code is bound to lower core addresses, binding 8-16 is alot faster than 0-7
ppu_mask = spu_mask = 0b1111111100000000; ppu_mask = spu_mask = 0b1111111100000000;
rsx_mask = all_cores_mask; rsx_mask = 0b11110000;
general = 0b00001111;
} }
else if (thread_count == 12) else if (thread_count == 12)
{ {
// 1600/2600 (x) // 1600/2600 (x)
ppu_mask = spu_mask = 0b111111000000; ppu_mask = spu_mask = 0b111111000000;
rsx_mask = all_cores_mask; rsx_mask = 0b111000;
general = 0b000111;
} }
else else
{ {
// R5 & R3 don't seem to improve performance no matter how these are shuffled // R5 & R3 don't seem to improve performance no matter how these are shuffled
ppu_mask = spu_mask = rsx_mask = 0b11111111 & all_cores_mask; ppu_mask = spu_mask = rsx_mask = general = 0b11111111;
} }
switch (group) switch (group)
{ {
default: default:
case thread_class::general: case thread_class::general:
return all_cores_mask; return general = all_cores_mask;
case thread_class::rsx: case thread_class::rsx:
return rsx_mask; return rsx_mask;
case thread_class::ppu: case thread_class::ppu:
+12 -2
View File
@@ -14,7 +14,10 @@ void shared_mutex::imp_lock_shared(s64 _old)
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
busy_wait(); if (i != 0)
{
busy_wait();
}
const s64 value = m_value.load(); const s64 value = m_value.load();
@@ -173,7 +176,10 @@ void shared_mutex::imp_lock(s64 _old)
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
{ {
busy_wait(); if (i != 0)
{
busy_wait();
}
const s64 value = m_value.load(); const s64 value = m_value.load();
@@ -236,6 +242,10 @@ void shared_mutex::imp_lock_degrade()
bool shared_mutex::try_lock_shared() bool shared_mutex::try_lock_shared()
{ {
if (m_value < c_min) // Fast path
{
return false;
}
// Conditional decrement // Conditional decrement
return m_value.fetch_op([](s64& value) { if (value >= c_min) value -= c_min; }) >= c_min; return m_value.fetch_op([](s64& value) { if (value >= c_min) value -= c_min; }) >= c_min;
} }
+1 -1
View File
@@ -19,7 +19,7 @@
<PropertyGroup Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
+8 -8
View File
@@ -19,12 +19,12 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType> <ConfigurationType>Makefile</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType> <ConfigurationType>Makefile</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
@@ -40,23 +40,23 @@
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<NMakeBuildCommandLine>start /W /B pre-build.bat <NMakeBuildCommandLine>start /W /B pre-build.bat
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m</NMakeBuildCommandLine> msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m</NMakeBuildCommandLine>
<NMakeCleanCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers <NMakeCleanCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release /m</NMakeCleanCommandLine> msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release /m</NMakeCleanCommandLine>
<NMakeReBuildCommandLine>start /W /B pre-build.bat <NMakeReBuildCommandLine>start /W /B pre-build.bat
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m
</NMakeReBuildCommandLine> </NMakeReBuildCommandLine>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<NMakeBuildCommandLine>start /W /B pre-build.bat <NMakeBuildCommandLine>start /W /B pre-build.bat
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m</NMakeBuildCommandLine> msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>start /W /B pre-build.bat <NMakeReBuildCommandLine>start /W /B pre-build.bat
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m</NMakeReBuildCommandLine> msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m</NMakeReBuildCommandLine>
<NMakeCleanCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers <NMakeCleanCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DBUILD_TESTS=OFF -DBUILD_DEMOS=OFF -DBUILD_LAYERS=OFF -DBUILD_VKJSON=OFF ../Vulkan-LoaderAndValidationLayers
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug /m</NMakeCleanCommandLine> msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug /m</NMakeCleanCommandLine>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup> <ItemDefinitionGroup>
+8 -8
View File
@@ -19,12 +19,12 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType> <ConfigurationType>Makefile</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType> <ConfigurationType>Makefile</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
@@ -39,24 +39,24 @@
</ImportGroup> </ImportGroup>
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<NMakeBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang <NMakeBuildCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m</NMakeBuildCommandLine> msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m</NMakeBuildCommandLine>
<NMakeReBuildCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang <NMakeReBuildCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m</NMakeReBuildCommandLine> msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m</NMakeReBuildCommandLine>
<NMakeCleanCommandLine>cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang <NMakeCleanCommandLine>cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release /m</NMakeCleanCommandLine> msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release /m</NMakeCleanCommandLine>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<NMakeBuildCommandLine> <NMakeBuildCommandLine>
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m
</NMakeBuildCommandLine> </NMakeBuildCommandLine>
<NMakeReBuildCommandLine> <NMakeReBuildCommandLine>
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m
</NMakeReBuildCommandLine> </NMakeReBuildCommandLine>
<NMakeCleanCommandLine> <NMakeCleanCommandLine>
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" ../glslang
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug /m msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug /m
</NMakeCleanCommandLine> </NMakeCleanCommandLine>
</PropertyGroup> </PropertyGroup>
+2 -2
View File
@@ -1,10 +1,10 @@
version: '{build}' version: '{build}'
image: Visual Studio 2015 image: Visual Studio 2017
environment: environment:
QTDIR: C:\Qt\5.10.0\msvc2015_64 QTDIR: C:\Qt\5.10.0\msvc2017_64
LLVMLIBS: https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRY2k3Q2Yya05lcm8 LLVMLIBS: https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRY2k3Q2Yya05lcm8
VULKAN: https://drive.google.com/uc?export=download&id=1A2eOMmCO714i0U7J0qI4aEMKnuWl8l_R VULKAN: https://drive.google.com/uc?export=download&id=1A2eOMmCO714i0U7J0qI4aEMKnuWl8l_R
COMPATDB: https://rpcs3.net/compatibility?api=v1&export COMPATDB: https://rpcs3.net/compatibility?api=v1&export
+1 -1
View File
@@ -93,7 +93,7 @@
<PropertyGroup Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
+1 -1
Submodule llvm updated: 4423e35117...16ebb58ea4
+1 -1
View File
@@ -1,7 +1,7 @@
REM You need cmake and python to update the project files REM You need cmake and python to update the project files
REM this script relies on CWD being the path that this script is in REM this script relies on CWD being the path that this script is in
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_EXTERNAL_POLLY_SOURCE_DIR=../polly -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=ON -DLLVM_INCLUDE_UTILS=ON -DWITH_POLLY=ON -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
RD /S /Q cmake RD /S /Q cmake
RD /S /Q CMakeFiles RD /S /Q CMakeFiles
+8 -8
View File
@@ -18,12 +18,12 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType> <ConfigurationType>Makefile</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Makefile</ConfigurationType> <ConfigurationType>Makefile</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
@@ -39,30 +39,30 @@
<NMakePreprocessorDefinitions> <NMakePreprocessorDefinitions>
</NMakePreprocessorDefinitions> </NMakePreprocessorDefinitions>
<NMakeBuildCommandLine> <NMakeBuildCommandLine>
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_EXTERNAL_POLLY_SOURCE_DIR=../polly -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=ON -DLLVM_INCLUDE_UTILS=ON -DWITH_POLLY=ON -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug /m
</NMakeBuildCommandLine> </NMakeBuildCommandLine>
<NMakeReBuildCommandLine> <NMakeReBuildCommandLine>
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_EXTERNAL_POLLY_SOURCE_DIR=../polly -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=ON -DLLVM_INCLUDE_UTILS=ON -DWITH_POLLY=ON -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug /m
</NMakeReBuildCommandLine> </NMakeReBuildCommandLine>
<NMakeCleanCommandLine> <NMakeCleanCommandLine>
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_EXTERNAL_POLLY_SOURCE_DIR=../polly -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=ON -DLLVM_INCLUDE_UTILS=ON -DWITH_POLLY=ON -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug /m msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug /m
</NMakeCleanCommandLine> </NMakeCleanCommandLine>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<NMakePreprocessorDefinitions /> <NMakePreprocessorDefinitions />
<NMakeBuildCommandLine> <NMakeBuildCommandLine>
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_EXTERNAL_POLLY_SOURCE_DIR=../polly -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=ON -DLLVM_INCLUDE_UTILS=ON -DWITH_POLLY=ON -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release /m
</NMakeBuildCommandLine> </NMakeBuildCommandLine>
<NMakeReBuildCommandLine> <NMakeReBuildCommandLine>
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_EXTERNAL_POLLY_SOURCE_DIR=../polly -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=ON -DLLVM_INCLUDE_UTILS=ON -DWITH_POLLY=ON -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release /m
</NMakeReBuildCommandLine> </NMakeReBuildCommandLine>
<NMakeCleanCommandLine> <NMakeCleanCommandLine>
cmake -G "Visual Studio 14 2015 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_EXTERNAL_POLLY_SOURCE_DIR=../polly -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=ON -DLLVM_INCLUDE_UTILS=ON -DWITH_POLLY=ON -DCMAKE_SYSTEM_VERSION=6.1 -DCMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION=8.1 ../llvm
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release /m msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release /m
</NMakeCleanCommandLine> </NMakeCleanCommandLine>
</PropertyGroup> </PropertyGroup>
+3
View File
@@ -62,6 +62,9 @@ vcxproj_files = ["lib\Analysis\LLVMAnalysis.vcxproj",
"lib\Transforms\Utils\LLVMTransformUtils.vcxproj", "lib\Transforms\Utils\LLVMTransformUtils.vcxproj",
"lib\Transforms\Vectorize\LLVMVectorize.vcxproj", "lib\Transforms\Vectorize\LLVMVectorize.vcxproj",
"include\llvm\IR\intrinsics_gen.vcxproj", "include\llvm\IR\intrinsics_gen.vcxproj",
"tools\polly\lib\Polly.vcxproj",
"tools\polly\lib\External\PollyISL.vcxproj",
"tools\polly\lib\External\PollyPPCG.vcxproj",
"utils\TableGen\llvm-tblgen.vcxproj", "utils\TableGen\llvm-tblgen.vcxproj",
] ]
Submodule
+1
Submodule polly added at 7f7d8e3954
+1 -1
View File
@@ -33,7 +33,7 @@ Controller.prototype.ComponentSelectionPageCallback = function() {
var widget = gui.currentPageWidget(); var widget = gui.currentPageWidget();
widget.deselectAll(); widget.deselectAll();
widget.selectComponent("qt.qt5.5100.gcc_64"); widget.selectComponent("qt.qt5.5101.gcc_64");
gui.clickButton(buttons.NextButton); gui.clickButton(buttons.NextButton);
} }
+2 -2
View File
@@ -20,14 +20,14 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc> <UseOfMfc>false</UseOfMfc>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType> <ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc> <UseOfMfc>false</UseOfMfc>
+5 -2
View File
@@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 14 # Visual Studio 15
VisualStudioVersion = 14.0.25420.1 VisualStudioVersion = 15.0.27130.2027
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "asmjit", "asmjitsrc\asmjit.vcxproj", "{AC40FF01-426E-4838-A317-66354CEFAE88}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "asmjit", "asmjitsrc\asmjit.vcxproj", "{AC40FF01-426E-4838-A317-66354CEFAE88}"
EndProject EndProject
@@ -243,4 +243,7 @@ Global
{FDC361C5-7734-493B-8CFB-037308B35122} = {DDF904CA-2771-441A-8629-5DF2EB922A79} {FDC361C5-7734-493B-8CFB-037308B35122} = {DDF904CA-2771-441A-8629-5DF2EB922A79}
{A107C21C-418A-4697-BB10-20C3AA60E2E4} = {FA1E6C16-CA63-45F8-8D52-E21DF396BE36} {A107C21C-418A-4697-BB10-20C3AA60E2E4} = {FA1E6C16-CA63-45F8-8D52-E21DF396BE36}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {06CC7920-E085-4B81-9582-8DE8AAD42510}
EndGlobalSection
EndGlobal EndGlobal
+40 -12
View File
@@ -6,12 +6,12 @@ set(CMAKE_CXX_STANDARD 14)
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
# Qt section # Qt section
find_package(Qt5 5.7 COMPONENTS Widgets Network) find_package(Qt5 5.10 COMPONENTS Widgets Network)
if(WIN32) if(WIN32)
find_package(Qt5 5.7 COMPONENTS WinExtras REQUIRED) find_package(Qt5 5.10 COMPONENTS WinExtras REQUIRED)
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::WinExtras Qt5::Network) set(RPCS3_QT_LIBS Qt5::Widgets Qt5::WinExtras Qt5::Network)
else() else()
find_package(Qt5 5.7 COMPONENTS DBus Gui) find_package(Qt5 5.10 COMPONENTS DBus Gui)
if(Qt5DBus_FOUND) if(Qt5DBus_FOUND)
set(RPCS3_QT_LIBS Qt5::Widgets Qt5::DBus Qt5::Network) set(RPCS3_QT_LIBS Qt5::Widgets Qt5::DBus Qt5::Network)
add_definitions(-DHAVE_QTDBUS) add_definitions(-DHAVE_QTDBUS)
@@ -23,15 +23,15 @@ endif()
# Let's make sure we have Qt before we continue # Let's make sure we have Qt before we continue
if(NOT Qt5Widgets_FOUND) if(NOT Qt5Widgets_FOUND)
if(Qt5Widgets_VERSION VERSION_LESS 5.7.0) if(Qt5Widgets_VERSION VERSION_LESS 5.10.0)
message("Minimum supported Qt5 version is 5.7! You have version ${Qt5Widgets_VERSION} installed, please upgrade!") message("Minimum supported Qt5 version is 5.10.0! You have version ${Qt5Widgets_VERSION} installed, please upgrade!")
if("${CMAKE_SYSTEM}" MATCHES "Linux") if("${CMAKE_SYSTEM}" MATCHES "Linux")
message(FATAL_ERROR "Most distros do not provide an up-to-date version of Qt. 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. 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-qt593-xenial https://launchpad.net/~beineri/+archive/ubuntu/opt-qt-5.10.1-xenial
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt593-trusty https://launchpad.net/~beineri/+archive/ubuntu/opt-qt-5.10.1-trusty
just make sure to run just make sure to run
source /opt/qt59/bin/qt59-env.sh source /opt/qt510/bin/qt510-env.sh
before re-running cmake") before re-running cmake")
elseif(WIN32) elseif(WIN32)
message(FATAL_ERROR "You can download the latest version of Qt5 here: https://www.qt.io/download-open-source/") message(FATAL_ERROR "You can download the latest version of Qt5 here: https://www.qt.io/download-open-source/")
@@ -42,7 +42,7 @@ before re-running cmake")
message("CMake was unable to find Qt5!") message("CMake was unable to find Qt5!")
if(WIN32) if(WIN32)
message(FATAL_ERROR "Make sure the QTDIR env variable has been set properly. (for example C:\\Qt\\5.8\\msvc2017_64\\)") message(FATAL_ERROR "Make sure the QTDIR env variable has been set properly. (for example C:\\Qt\\5.10.1\\msvc2017_64\\)")
elseif("${CMAKE_SYSTEM}" MATCHES "Linux") elseif("${CMAKE_SYSTEM}" MATCHES "Linux")
message(FATAL_ERROR "Make sure to install your distro's qt5 package!") message(FATAL_ERROR "Make sure to install your distro's qt5 package!")
else() else()
@@ -96,7 +96,7 @@ if(NOT MSVC)
if(NOT APPLE) if(NOT APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--exclude-libs,ALL") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--exclude-libs,ALL")
endif() endif()
if(WIN32) if(WIN32)
set(CMAKE_RC_COMPILER_INIT windres) set(CMAKE_RC_COMPILER_INIT windres)
enable_language(RC) enable_language(RC)
@@ -173,7 +173,7 @@ set(CMAKE_MODULE_PATH "${RPCS3_SRC_DIR}/cmake_modules")
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
find_package(OpenAL REQUIRED) find_package(OpenAL REQUIRED)
if(NOT WITHOUT_LLVM) if(NOT WITHOUT_LLVM)
find_package(LLVM 4.0 CONFIG) find_package(LLVM 6.0 CONFIG)
if(NOT LLVM_FOUND) if(NOT LLVM_FOUND)
message("System LLVM was not found, LLVM will be built from the submodule.") message("System LLVM was not found, LLVM will be built from the submodule.")
@@ -198,6 +198,28 @@ if(NOT WITHOUT_LLVM)
endif() endif()
endif() endif()
endif() endif()
# Now let's look for polly.
find_package(Polly)
if(Polly_FOUND)
add_definitions(-DPOLLY_AVAILABLE)
endif()
# Polly LLVM Compiler checks
CHECK_C_COMPILER_FLAG("-mllvm -polly" HAS_POLLY)
CHECK_C_COMPILER_FLAG("-mllvm -polly-target=hybrid" HAS_POLLY_HYBRID)
CHECK_C_COMPILER_FLAG("-mllvm -polly-target=cpu" HAS_POLLY_CPU)
if (HAS_POLLY)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -polly -mllvm -polly-parallel -lgomp -mllvm -polly-vectorizer=stripmine")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mllvm -polly -mllvm -polly-parallel -lgomp -mllvm -polly-vectorizer=stripmine")
if(HAS_POLLY_HYBRID)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -polly-target=hybrid")
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -polly-target=cpu")
elseif(HAS_POLLY_CPU)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -polly-target=cpu")
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} -mllvm -polly-target=cpu")
endif()
endif()
if(APPLE) if(APPLE)
@@ -274,6 +296,7 @@ endif()
include_directories( include_directories(
${OPENAL_INCLUDE_DIR} ${OPENAL_INCLUDE_DIR}
${LLVM_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS}
${Polly_INCLUDE_DIRS}
"${RPCS3_SRC_DIR}/../3rdparty/pugixml/src" "${RPCS3_SRC_DIR}/../3rdparty/pugixml/src"
"${RPCS3_SRC_DIR}" "${RPCS3_SRC_DIR}"
"${RPCS3_SRC_DIR}/Loader" "${RPCS3_SRC_DIR}/Loader"
@@ -319,6 +342,7 @@ endif()
link_directories( link_directories(
"${RPCS3_SRC_DIR}/../3rdparty/minidx12/" "${RPCS3_SRC_DIR}/../3rdparty/minidx12/"
"${RPCS3_SRC_DIR}/../Vulkan" "${RPCS3_SRC_DIR}/../Vulkan"
"${Polly_LIBRARY_DIRS}"
) )
@@ -393,8 +417,12 @@ if(NOT MSVC)
target_link_libraries(rpcs3 GLEW::GLEW) target_link_libraries(rpcs3 GLEW::GLEW)
endif() endif()
if(Polly_FOUND)
target_link_libraries(rpcs3 Polly PollyISL PollyPPCG)
endif()
if(WIN32) if(WIN32)
target_link_libraries(rpcs3 ws2_32.lib Winmm.lib Psapi.lib VKstatic.1 glslang OSDependent OGLCompiler SPIRV HLSL setupapi.lib hidapi-hid Shlwapi.lib) target_link_libraries(rpcs3 ws2_32.lib Winmm.lib Psapi.lib gdi32.lib VKstatic.1 glslang OSDependent OGLCompiler SPIRV HLSL setupapi.lib hidapi-hid Shlwapi.lib)
if(NOT MSVC) if(NOT MSVC)
target_link_libraries(rpcs3 ${OPENGL_LIBRARIES} opengl32.lib glu32.lib libpthread) target_link_libraries(rpcs3 ${OPENGL_LIBRARIES} opengl32.lib glu32.lib libpthread)
else() else()
+1 -1
View File
@@ -31,7 +31,7 @@
<PropertyGroup Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
-32
View File
@@ -711,38 +711,6 @@ public:
return result; return result;
} }
template <typename T, typename T2>
value_t<T> bitcast(T2 expr)
{
value_t<T> result;
result.value = m_ir->CreateBitCast(expr.eval(m_ir), result.get_type(m_context));
return result;
}
template <typename T, typename T2>
value_t<T> trunc(T2 expr)
{
value_t<T> result;
result.value = m_ir->CreateTrunc(expr.eval(m_ir), result.get_type(m_context));
return result;
}
template <typename T, typename T2>
value_t<T> sext(T2 expr)
{
value_t<T> result;
result.value = m_ir->CreateSExt(expr.eval(m_ir), result.get_type(m_context));
return result;
}
template <typename T, typename T2>
value_t<T> zext(T2 expr)
{
value_t<T> result;
result.value = m_ir->CreateZExt(expr.eval(m_ir), result.get_type(m_context));
return result;
}
// Get unsigned addition carry into the sign bit (s = a + b) // Get unsigned addition carry into the sign bit (s = a + b)
template <typename T> template <typename T>
static inline auto ucarry(T a, T b, T s) static inline auto ucarry(T a, T b, T s)
+6 -5
View File
@@ -176,14 +176,16 @@ void mfc_thread::cpu_task()
data = to_write; data = to_write;
vm::reservation_update(cmd.eal, 128); vm::reservation_update(cmd.eal, 128);
vm::notify(cmd.eal, 128);
_xend(); _xend();
vm::notify(cmd.eal, 128);
} }
else else
{ {
vm::writer_lock lock(0); {
data = to_write; vm::writer_lock lock(0);
vm::reservation_update(cmd.eal, 128); data = to_write;
vm::reservation_update(cmd.eal, 128);
}
vm::notify(cmd.eal, 128); vm::notify(cmd.eal, 128);
} }
} }
@@ -356,7 +358,6 @@ void mfc_thread::cpu_task()
} }
else else
{ {
vm::reader_lock lock;
vm::notify_all(); vm::notify_all();
} }
} }
+2 -2
View File
@@ -1,4 +1,4 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/Cell/PPUModule.h" #include "Emu/Cell/PPUModule.h"
@@ -554,7 +554,7 @@ s32 cellFontExtend(u32 a1, u32 a2, u32 a3)
//Something happens //Something happens
} }
//Something happens? //Something happens?
return CELL_OK; return -1;
} }
s32 cellFontRenderCharGlyphImageVertical() s32 cellFontRenderCharGlyphImageVertical()
+214 -46
View File
@@ -2,131 +2,287 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h" #include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/lv2/sys_lwmutex.h"
#include "cellMusic.h" #include "Emu/Cell/lv2/sys_lwcond.h"
#include "Emu/Cell/lv2/sys_spu.h"
#include "cellSearch.h"
#include "cellSpurs.h"
#include "cellSysutil.h" #include "cellSysutil.h"
#include "cellMusic.h"
logs::channel cellMusic("cellMusic"); logs::channel cellMusic("cellMusic");
struct music2_t struct music_t
{ {
vm::ptr<CellMusic2Callback> func; vm::ptr<void(u32 event, vm::ptr<void> param, vm::ptr<void> userData)> func;
vm::ptr<void> userData; vm::ptr<void> userData;
}; };
s32 cellMusicGetSelectionContext() s32 cellMusicGetSelectionContext(vm::ptr<CellMusicSelectionContext> context)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicGetSelectionContext(context=*0x%x)", context);
return CELL_OK; return CELL_OK;
} }
s32 cellMusicSetSelectionContext2() s32 cellMusicSetSelectionContext2(vm::ptr<CellMusicSelectionContext> context)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicSetSelectionContext2(context=*0x%x)", context);
const auto music = fxm::get_always<music_t>();
if (!music->func)
return CELL_MUSIC2_ERROR_GENERIC;
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC2_EVENT_SET_SELECTION_CONTEXT_RESULT, vm::addr_t(CELL_OK), music->userData);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
s32 cellMusicSetVolume2() s32 cellMusicSetVolume2(f32 level)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicSetVolume2(level=0x%x)", level);
const auto music = fxm::get_always<music_t>();
if (!music->func)
return CELL_MUSIC2_ERROR_GENERIC;
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC2_EVENT_SET_VOLUME_RESULT, vm::addr_t(CELL_OK), music->userData);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
s32 cellMusicGetContentsId() s32 cellMusicGetContentsId(vm::ptr<CellSearchContentId> contents_id)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicGetContentsId(contents_id=*0x%x)", contents_id);
return CELL_OK; return CELL_OK;
} }
s32 cellMusicSetSelectionContext() s32 cellMusicSetSelectionContext(vm::ptr<CellMusicSelectionContext> context)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicSetSelectionContext(context=*0x%x)", context);
const auto music = fxm::get_always<music_t>();
if (!music->func)
return CELL_MUSIC_ERROR_GENERIC;
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC_EVENT_SET_SELECTION_CONTEXT_RESULT, vm::addr_t(CELL_OK), music->userData);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
s32 cellMusicInitialize2SystemWorkload() s32 cellMusicInitialize2SystemWorkload(s32 mode, vm::ptr<CellMusic2Callback> func, vm::ptr<void> userData, vm::ptr<CellSpurs> spurs, vm::cptr<u8> priority, vm::cptr<struct CellSpursSystemWorkloadAttribute> attr)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicInitialize2SystemWorkload(mode=0x%x, func=*0x%x, userData=*0x%x, spurs=*0x%x, priority=*0x%x, attr=*0x%x)", mode, func, userData, spurs, priority, attr);
const auto music = fxm::make_always<music_t>();
music->func = func;
music->userData = userData;
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC2_EVENT_INITIALIZE_RESULT, vm::addr_t(CELL_OK), userData);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
s32 cellMusicGetPlaybackStatus2() s32 cellMusicGetPlaybackStatus2(vm::ptr<s32> status)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicGetPlaybackStatus2(status=*0x%x)", status);
return CELL_OK; return CELL_OK;
} }
s32 cellMusicGetContentsId2() s32 cellMusicGetContentsId2(vm::ptr<CellSearchContentId> contents_id)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicGetContentsId2(contents_id=*0x%x)", contents_id);
return CELL_OK; return CELL_OK;
} }
s32 cellMusicFinalize() s32 cellMusicFinalize()
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicFinalize()");
const auto music = fxm::get_always<music_t>();
if (music->func)
{
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC_EVENT_FINALIZE_RESULT, vm::addr_t(CELL_OK), music->userData);
return CELL_OK;
});
}
return CELL_OK; return CELL_OK;
} }
s32 cellMusicInitializeSystemWorkload() s32 cellMusicInitializeSystemWorkload(s32 mode, u32 container, vm::ptr<CellMusicCallback> func, vm::ptr<void> userData, vm::ptr<CellSpurs> spurs, vm::cptr<u8> priority, vm::cptr<struct CellSpursSystemWorkloadAttribute> attr)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicInitializeSystemWorkload(mode=0x%x, container=0x%x, func=*0x%x, userData=*0x%x, spurs=*0x%x, priority=*0x%x, attr=*0x%x)", mode, container, func, userData, spurs, priority, attr);
if (mode != CELL_MUSIC2_PLAYER_MODE_NORMAL)
{
cellMusic.todo("Unknown player mode: 0x%x", mode);
return CELL_MUSIC_ERROR_PARAM;
}
const auto music = fxm::make_always<music_t>();
music->func = func;
music->userData = userData;
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC_EVENT_INITIALIZE_RESULT, vm::addr_t(CELL_OK), userData);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
s32 cellMusicInitialize() s32 cellMusicInitialize(s32 mode, u32 container, s32 spuPriority, vm::ptr<CellMusicCallback> func, vm::ptr<void> userData)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicInitialize(mode=0x%x, container=0x%x, spuPriority=0x%x, func=*0x%x, userData=*0x%x)", mode, container, spuPriority, func, userData);
if (mode != CELL_MUSIC2_PLAYER_MODE_NORMAL)
{
cellMusic.todo("Unknown player mode: 0x%x", mode);
return CELL_MUSIC_ERROR_PARAM;
}
const auto music = fxm::make_always<music_t>();
music->func = func;
music->userData = userData;
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC_EVENT_INITIALIZE_RESULT, vm::addr_t(CELL_OK), userData);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
s32 cellMusicFinalize2() s32 cellMusicFinalize2()
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicFinalize2()");
const auto music = fxm::get_always<music_t>();
if (music->func)
{
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC2_EVENT_FINALIZE_RESULT, vm::addr_t(CELL_OK), music->userData);
return CELL_OK;
});
}
return CELL_OK; return CELL_OK;
} }
s32 cellMusicGetSelectionContext2() s32 cellMusicGetSelectionContext2(vm::ptr<CellMusicSelectionContext> context)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicGetSelectionContext2(context=*0x%x)", context);
return CELL_OK; return CELL_OK;
} }
s32 cellMusicGetVolume() s32 cellMusicGetVolume(vm::ptr<f32> level)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicGetVolume(level=*0x%x)", level);
return CELL_OK; return CELL_OK;
} }
s32 cellMusicGetPlaybackStatus() s32 cellMusicGetPlaybackStatus(vm::ptr<s32> status)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicGetPlaybackStatus(status=*0x%x)", status);
return CELL_OK; return CELL_OK;
} }
s32 cellMusicSetPlaybackCommand2() s32 cellMusicSetPlaybackCommand2(s32 command, vm::ptr<void> param)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicSetPlaybackCommand2(command=0x%x, param=*0x%x)", command, param);
const auto music = fxm::get_always<music_t>();
if (!music->func)
return CELL_MUSIC2_ERROR_GENERIC;
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC2_EVENT_SET_PLAYBACK_COMMAND_RESULT, vm::addr_t(CELL_OK), music->userData);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
s32 cellMusicSetPlaybackCommand() s32 cellMusicSetPlaybackCommand(s32 command, vm::ptr<void> param)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicSetPlaybackCommand(command=0x%x, param=*0x%x)", command, param);
const auto music = fxm::get_always<music_t>();
if (!music->func)
return CELL_MUSIC_ERROR_GENERIC;
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC_EVENT_SET_PLAYBACK_COMMAND_RESULT, vm::addr_t(CELL_OK), music->userData);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
s32 cellMusicSelectContents2() s32 cellMusicSelectContents2()
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicSelectContents2()");
const auto music = fxm::get_always<music_t>();
if (!music->func)
return CELL_MUSIC2_ERROR_GENERIC;
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC2_EVENT_SELECT_CONTENTS_RESULT, vm::addr_t(CELL_OK), music->userData);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
s32 cellMusicSelectContents() s32 cellMusicSelectContents(u32 container)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicSelectContents(container=0x%x)", container);
const auto music = fxm::get_always<music_t>();
if (!music->func)
return CELL_MUSIC_ERROR_GENERIC;
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC_EVENT_SELECT_CONTENTS_RESULT, vm::addr_t(CELL_OK), music->userData);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
@@ -140,28 +296,40 @@ s32 cellMusicInitialize2(s32 mode, s32 spuPriority, vm::ptr<CellMusic2Callback>
return CELL_MUSIC2_ERROR_PARAM; return CELL_MUSIC2_ERROR_PARAM;
} }
const auto music = fxm::make_always<music2_t>(); const auto music = fxm::make_always<music_t>();
music->func = func; music->func = func;
music->userData = userData; music->userData = userData;
sysutil_register_cb([=](ppu_thread& ppu) -> s32 sysutil_register_cb([=](ppu_thread& ppu) -> s32
{ {
func(ppu, CELL_MUSIC2_EVENT_INITIALIZE_RESULT, vm::make_var<s32>(CELL_OK), userData); music->func(ppu, CELL_MUSIC2_EVENT_INITIALIZE_RESULT, vm::addr_t(CELL_OK), userData);
return CELL_OK; return CELL_OK;
}); });
return CELL_OK; return CELL_OK;
} }
s32 cellMusicSetVolume() s32 cellMusicSetVolume(f32 level)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicSetVolume(level=0x%x)", level);
const auto music = fxm::get_always<music_t>();
if (!music->func)
return CELL_MUSIC_ERROR_GENERIC;
sysutil_register_cb([=](ppu_thread& ppu) -> s32
{
music->func(ppu, CELL_MUSIC_EVENT_SET_VOLUME_RESULT, vm::addr_t(CELL_OK), music->userData);
return CELL_OK;
});
return CELL_OK; return CELL_OK;
} }
s32 cellMusicGetVolume2() s32 cellMusicGetVolume2(vm::ptr<f32> level)
{ {
UNIMPLEMENTED_FUNC(cellMusic); cellMusic.todo("cellMusicGetVolume2(level=*0x%x)", level);
return CELL_OK; return CELL_OK;
} }
+2 -2
View File
@@ -12,8 +12,8 @@ enum
CELL_MUSIC_ERROR_PLAYBACK_FAILURE = 0x8002c107, CELL_MUSIC_ERROR_PLAYBACK_FAILURE = 0x8002c107,
CELL_MUSIC_ERROR_NO_MORE_CONTENT = 0x8002c108, CELL_MUSIC_ERROR_NO_MORE_CONTENT = 0x8002c108,
CELL_MUSIC_DIALOG_OPEN = 0x8002c109, CELL_MUSIC_DIALOG_OPEN = 0x8002c109,
CELL_MUSIC_DIALOG_CLOSE = 0x8002c10A, CELL_MUSIC_DIALOG_CLOSE = 0x8002c10a,
CELL_MUSIC_ERROR_GENERIC = 0x8002c1FF, CELL_MUSIC_ERROR_GENERIC = 0x8002c1ff,
CELL_MUSIC2_PLAYBACK_FINISHED = CELL_MUSIC_PLAYBACK_FINISHED, CELL_MUSIC2_PLAYBACK_FINISHED = CELL_MUSIC_PLAYBACK_FINISHED,
CELL_MUSIC2_ERROR_PARAM = CELL_MUSIC_ERROR_PARAM, CELL_MUSIC2_ERROR_PARAM = CELL_MUSIC_ERROR_PARAM,
+2 -1
View File
@@ -2,9 +2,10 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h" #include "Emu/Cell/PPUModule.h"
#include "cellMusic.h"
#include "cellSysutil.h"
#include "cellSearch.h" #include "cellSearch.h"
#include "cellSysutil.h"
logs::channel cellSearch("cellSearch"); logs::channel cellSearch("cellSearch");
-6
View File
@@ -32,7 +32,6 @@ enum
CELL_SEARCH_TITLE_LEN_MAX = 384, CELL_SEARCH_TITLE_LEN_MAX = 384,
CELL_SEARCH_TAG_NUM_MAX = 6, CELL_SEARCH_TAG_NUM_MAX = 6,
CELL_SEARCH_TAG_LEN_MAX = 63, CELL_SEARCH_TAG_LEN_MAX = 63,
CELL_MUSIC_SELECTION_CONTEXT_SIZE = 2048,
CELL_SEARCH_PATH_LEN_MAX = 63, CELL_SEARCH_PATH_LEN_MAX = 63,
CELL_SEARCH_MTOPTION_LEN_MAX = 63, CELL_SEARCH_MTOPTION_LEN_MAX = 63,
CELL_SEARCH_DEVELOPERDATA_LEN_MAX = 64, CELL_SEARCH_DEVELOPERDATA_LEN_MAX = 64,
@@ -339,11 +338,6 @@ struct CellSearchVideoSceneInfo
char tags[CELL_SEARCH_TAG_NUM_MAX][CELL_SEARCH_TAG_LEN_MAX]; char tags[CELL_SEARCH_TAG_NUM_MAX][CELL_SEARCH_TAG_LEN_MAX];
}; };
struct CellMusicSelectionContext
{
char data[CELL_MUSIC_SELECTION_CONTEXT_SIZE];
};
struct CellSearchContentInfoPath struct CellSearchContentInfoPath
{ {
char contentPath[CELL_SEARCH_PATH_LEN_MAX + 1]; char contentPath[CELL_SEARCH_PATH_LEN_MAX + 1];
+1 -1
View File
@@ -352,7 +352,7 @@ error_code sceNpTrophyGetRequiredDiskSpace(u32 context, u32 handle, vm::ptr<u64>
return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE; return SCE_NP_TROPHY_ERROR_UNKNOWN_HANDLE;
} }
if (!fs::is_dir("/dev_hdd0/home/00000001/trophy/" + ctxt->trp_name)) if (!fs::is_dir(vfs::get("/dev_hdd0/home/00000001/trophy/" + ctxt->trp_name)))
{ {
TRPLoader trp(ctxt->trp_stream); TRPLoader trp(ctxt->trp_stream);
+4 -4
View File
@@ -1436,7 +1436,7 @@ void ppu_module::analyse(u32 lib_toc, u32 entry)
void ppu_acontext::UNK(ppu_opcode_t op) void ppu_acontext::UNK(ppu_opcode_t op)
{ {
std::fill_n(gpr, 32, spec_gpr{}); std::fill_n(gpr, 32, spec_gpr());
LOG_ERROR(PPU, "Unknown/Illegal opcode: 0x%08x at 0x%x" HERE, op.opcode, cia); LOG_ERROR(PPU, "Unknown/Illegal opcode: 0x%08x at 0x%x" HERE, op.opcode, cia);
} }
@@ -2563,7 +2563,7 @@ void ppu_acontext::MULHW(ppu_opcode_t op)
void ppu_acontext::LDARX(ppu_opcode_t op) void ppu_acontext::LDARX(ppu_opcode_t op)
{ {
gpr[op.rd] = {}; gpr[op.rd] = spec_gpr();
} }
void ppu_acontext::DCBF(ppu_opcode_t op) void ppu_acontext::DCBF(ppu_opcode_t op)
@@ -2879,7 +2879,7 @@ void ppu_acontext::LVRX(ppu_opcode_t op)
void ppu_acontext::LSWI(ppu_opcode_t op) void ppu_acontext::LSWI(ppu_opcode_t op)
{ {
std::fill_n(gpr, 32, spec_gpr{}); std::fill_n(gpr, 32, spec_gpr());
} }
void ppu_acontext::LFSUX(ppu_opcode_t op) void ppu_acontext::LFSUX(ppu_opcode_t op)
@@ -3106,7 +3106,7 @@ void ppu_acontext::STHU(ppu_opcode_t op)
void ppu_acontext::LMW(ppu_opcode_t op) void ppu_acontext::LMW(ppu_opcode_t op)
{ {
std::fill_n(gpr, 32, spec_gpr{}); std::fill_n(gpr, 32, spec_gpr());
} }
void ppu_acontext::STMW(ppu_opcode_t op) void ppu_acontext::STMW(ppu_opcode_t op)
+36 -14
View File
@@ -40,6 +40,12 @@
#include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Vectorize.h" #include "llvm/Transforms/Vectorize.h"
#ifdef POLLY_AVAILABLE
#include <polly/RegisterPasses.h>
#include <polly/ScopDetection.h>
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
@@ -961,14 +967,18 @@ extern bool ppu_stwcx(ppu_thread& ppu, u32 addr, u32 reg_value)
return result; return result;
} }
vm::writer_lock lock(0); bool result;
const bool result = ppu.rtime == vm::reservation_acquire(addr, sizeof(u32)) && data.compare_and_swap_test(static_cast<u32>(ppu.rdata), reg_value);
if (result)
{ {
vm::reservation_update(addr, sizeof(u32)); vm::writer_lock lock(0);
vm::notify(addr, sizeof(u32));
result = ppu.rtime == vm::reservation_acquire(addr, sizeof(u32)) && data.compare_and_swap_test(static_cast<u32>(ppu.rdata), reg_value);
if (result)
{
vm::reservation_update(addr, sizeof(u32));
lock.unlock();
vm::notify(addr, sizeof(u32));
}
} }
ppu.raddr = 0; ppu.raddr = 0;
@@ -1005,14 +1015,18 @@ extern bool ppu_stdcx(ppu_thread& ppu, u32 addr, u64 reg_value)
return result; return result;
} }
vm::writer_lock lock(0); bool result;
const bool result = ppu.rtime == vm::reservation_acquire(addr, sizeof(u64)) && data.compare_and_swap_test(ppu.rdata, reg_value);
if (result)
{ {
vm::reservation_update(addr, sizeof(u64)); vm::writer_lock lock(0);
vm::notify(addr, sizeof(u64));
result = ppu.rtime == vm::reservation_acquire(addr, sizeof(u64)) && data.compare_and_swap_test(ppu.rdata, reg_value);
if (result)
{
vm::reservation_update(addr, sizeof(u64));
lock.unlock();
vm::notify(addr, sizeof(u64));
}
} }
ppu.raddr = 0; ppu.raddr = 0;
@@ -1464,6 +1478,11 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
} }
} }
#ifdef POLLY_AVAILABLE
PassRegistry &Registry = *PassRegistry::getPassRegistry();
polly::initializePollyPasses(Registry);
initializeAnalysis(Registry);
#endif
std::shared_ptr<MsgDialogBase> dlg; std::shared_ptr<MsgDialogBase> dlg;
{ {
@@ -1481,6 +1500,9 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
//pm.add(createLoopInstSimplifyPass()); //pm.add(createLoopInstSimplifyPass());
//pm.add(createNewGVNPass()); //pm.add(createNewGVNPass());
pm.add(createDeadStoreEliminationPass()); pm.add(createDeadStoreEliminationPass());
#ifdef POLLY_AVAILABLE
polly::registerPollyPasses(pm);
#endif
//pm.add(createSCCPPass()); //pm.add(createSCCPPass());
//pm.add(createReassociatePass()); //pm.add(createReassociatePass());
//pm.add(createInstructionCombiningPass()); //pm.add(createInstructionCombiningPass());
+1 -1
View File
@@ -14,7 +14,7 @@ const ppu_decoder<PPUTranslator> s_ppu_decoder;
PPUTranslator::PPUTranslator(LLVMContext& context, Module* module, const ppu_module& info) PPUTranslator::PPUTranslator(LLVMContext& context, Module* module, const ppu_module& info)
: cpu_translator(context, module, false) : cpu_translator(context, module, false)
, m_info(info) , m_info(info)
, m_pure_attr(AttributeSet::get(m_context, AttributeSet::FunctionIndex, {Attribute::NoUnwind, Attribute::ReadNone})) , m_pure_attr(AttributeList::get(m_context,AttributeList::FunctionIndex, AttrBuilder().addAttribute(Attribute::NoUnwind).addAttribute(Attribute::ReadNone)))
{ {
// There is no weak linkage on JIT, so let's create variables with different names for each module part // There is no weak linkage on JIT, so let's create variables with different names for each module part
const u32 gsuffix = m_info.name.empty() ? info.funcs[0].addr : info.funcs[0].addr - m_info.segs[0].addr; const u32 gsuffix = m_info.name.empty() ? info.funcs[0].addr : info.funcs[0].addr - m_info.segs[0].addr;
+115 -306
View File
@@ -10,11 +10,6 @@
#include <cmath> #include <cmath>
#define ASMJIT_STATIC
#define ASMJIT_DEBUG
#include "asmjit.h"
#define SPU_OFF_128(x, ...) asmjit::x86::oword_ptr(*cpu, offset32(&SPUThread::x, ##__VA_ARGS__)) #define SPU_OFF_128(x, ...) asmjit::x86::oword_ptr(*cpu, offset32(&SPUThread::x, ##__VA_ARGS__))
#define SPU_OFF_64(x, ...) asmjit::x86::qword_ptr(*cpu, offset32(&SPUThread::x, ##__VA_ARGS__)) #define SPU_OFF_64(x, ...) asmjit::x86::qword_ptr(*cpu, offset32(&SPUThread::x, ##__VA_ARGS__))
#define SPU_OFF_32(x, ...) asmjit::x86::dword_ptr(*cpu, offset32(&SPUThread::x, ##__VA_ARGS__)) #define SPU_OFF_32(x, ...) asmjit::x86::dword_ptr(*cpu, offset32(&SPUThread::x, ##__VA_ARGS__))
@@ -36,25 +31,25 @@ spu_recompiler::spu_recompiler()
} }
} }
void spu_recompiler::compile(spu_function_t& f) bool spu_recompiler::compile(spu_function_contents_t* f)
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
if (f.compiled) if (f->compiled)
{ {
// return if function already compiled // return if function already compiled
return; return true;
} }
if (f.addr >= 0x40000 || f.addr % 4 || f.size == 0 || f.size > 0x40000 - f.addr || f.size % 4) if (f->addr >= 0x40000 || f->addr % 4 || f->size == 0 || f->size > 0x40000 - f->addr || f->size % 4)
{ {
fmt::throw_exception("Invalid SPU function (addr=0x%05x, size=0x%x)" HERE, f.addr, f.size); fmt::throw_exception("Invalid SPU function (addr=0x%05x, size=0x%x)" HERE, f->addr, f->size);
} }
using namespace asmjit; using namespace asmjit;
SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode);
dis_asm.offset = reinterpret_cast<u8*>(f.data.data()) - f.addr; dis_asm.offset = reinterpret_cast<u8*>(f->data.data()) - f->addr;
StringLogger logger; StringLogger logger;
logger.addOptions(Logger::kOptionBinaryForm); logger.addOptions(Logger::kOptionBinaryForm);
@@ -63,10 +58,10 @@ void spu_recompiler::compile(spu_function_t& f)
if (g_cfg.core.spu_debug) if (g_cfg.core.spu_debug)
{ {
fmt::append(log, "========== SPU FUNCTION 0x%05x - 0x%05x ==========\n\n", f.addr, f.addr + f.size); fmt::append(log, "========== SPU FUNCTION 0x%05x - 0x%05x ==========\n\n", f->addr, f->addr + f->size);
} }
this->m_func = &f; this->m_func = f;
asmjit::CodeHolder code; asmjit::CodeHolder code;
code.init(m_jit->getCodeInfo()); code.init(m_jit->getCodeInfo());
@@ -121,13 +116,13 @@ void spu_recompiler::compile(spu_function_t& f)
compiler.alloc(vec_vars[5], asmjit::x86::xmm5); compiler.alloc(vec_vars[5], asmjit::x86::xmm5);
// Initialize labels // Initialize labels
std::vector<Label> pos_labels{ 0x10000 }; this->labels = std::unique_ptr<Label[]>(reinterpret_cast<Label*>(new u8[0x10000 * sizeof(Label)]()));
this->labels = pos_labels.data(); auto pos_labels = this->labels.get();
// Register labels for block entries // Register labels for block entries
for (const u32 addr : f.blocks) for (const u32 addr : f->blocks)
{ {
if (addr < f.addr || addr >= f.addr + f.size || addr % 4) if (addr < f->addr || addr >= f->addr + f->size || addr % 4)
{ {
fmt::throw_exception("Invalid function block entry (0x%05x)" HERE, addr); fmt::throw_exception("Invalid function block entry (0x%05x)" HERE, addr);
} }
@@ -136,15 +131,15 @@ void spu_recompiler::compile(spu_function_t& f)
} }
// Register label for post-the-end address // Register label for post-the-end address
pos_labels[(f.addr + f.size) / 4 % 0x10000] = compiler.newLabel(); pos_labels[(f->addr + f->size) / 4 % 0x10000] = compiler.newLabel();
// Register label for jump table resolver // Register label for jump table resolver
Label jt_label = compiler.newLabel(); Label jt_label = compiler.newLabel();
this->jt = &jt_label; this->jt = &jt_label;
for (const u32 addr : f.jtable) for (const u32 addr : f->jtable)
{ {
if (addr < f.addr || addr >= f.addr + f.size || addr % 4) if (addr < f->addr || addr >= f->addr + f->size || addr % 4)
{ {
fmt::throw_exception("Invalid jump table entry (0x%05x)" HERE, addr); fmt::throw_exception("Invalid jump table entry (0x%05x)" HERE, addr);
} }
@@ -155,24 +150,16 @@ void spu_recompiler::compile(spu_function_t& f)
this->end = &end_label; this->end = &end_label;
// Start compilation // Start compilation
m_pos = f.addr; m_pos = f->addr;
if (utils::has_avx()) for (const u32 op : f->data)
{
compiler.vzeroupper();
//compiler.pxor(asmjit::x86::xmm0, asmjit::x86::xmm0);
//compiler.vptest(asmjit::x86::ymm0, asmjit::x86::ymm0);
//compiler.jnz(end_label);
}
for (const u32 op : f.data)
{ {
// Bind label if initialized // Bind label if initialized
if (pos_labels[m_pos / 4].isValid()) if (pos_labels[m_pos / 4].isValid())
{ {
compiler.bind(pos_labels[m_pos / 4]); compiler.bind(pos_labels[m_pos / 4]);
if (f.blocks.find(m_pos) != f.blocks.end()) if (f->blocks.find(m_pos) != f->blocks.end())
{ {
compiler.comment("Block:"); compiler.comment("Block:");
} }
@@ -219,12 +206,12 @@ void spu_recompiler::compile(spu_function_t& f)
// Generate jump table resolver (uses addr_var) // Generate jump table resolver (uses addr_var)
compiler.bind(jt_label); compiler.bind(jt_label);
if (f.jtable.size()) if (f->jtable.size())
{ {
compiler.comment("Jump table resolver:"); compiler.comment("Jump table resolver:");
} }
for (const u32 addr : f.jtable) for (const u32 addr : f->jtable)
{ {
if ((addr % 4) == 0 && addr < 0x40000 && pos_labels[addr / 4].isValid()) if ((addr % 4) == 0 && addr < 0x40000 && pos_labels[addr / 4].isValid())
{ {
@@ -253,8 +240,8 @@ void spu_recompiler::compile(spu_function_t& f)
Func fn; Func fn;
m_jit->add(&fn, codeHolder); m_jit->add(&fn, codeHolder);
f.compiled = asmjit::Internal::ptr_cast<decltype(f.compiled)>(fn); f->compiled = asmjit::Internal::ptr_cast<decltype(f->compiled)>(fn);
if (g_cfg.core.spu_debug) if (g_cfg.core.spu_debug)
{ {
// Add ASMJIT logs // Add ASMJIT logs
@@ -462,16 +449,29 @@ void spu_recompiler::LNOP(spu_opcode_t op)
{ {
} }
void invalidate_jit(SPUThread* _spu)
{
for (u32 i = _spu->first_clean_func_index; i < _spu->last_clean_func_index; i++)
{
_spu->compiled_functions[i].dirty_bit = true;
}
_spu->first_clean_func_index = -1;
_spu->last_clean_func_index = 0;
}
void spu_recompiler::SYNC(spu_opcode_t op) void spu_recompiler::SYNC(spu_opcode_t op)
{ {
asmjit::CCFuncCall* call = c->call(asmjit::imm_ptr(asmjit::Internal::ptr_cast<void*, void(SPUThread*)>(invalidate_jit)), asmjit::FuncSignature1<u32, SPUThread*>(asmjit::CallConv::kIdHost));
call->setArg(0, *cpu);
// This instruction must be used following a store instruction that modifies the instruction stream. // This instruction must be used following a store instruction that modifies the instruction stream.
c->mfence();
} }
void spu_recompiler::DSYNC(spu_opcode_t op) void spu_recompiler::DSYNC(spu_opcode_t op)
{ {
// This instruction forces all earlier load, store, and channel instructions to complete before proceeding. // This instruction forces all earlier load, store, and channel instructions to complete before proceeding.
c->mfence(); c->mfence();
asmjit::CCFuncCall* call = c->call(asmjit::imm_ptr(asmjit::Internal::ptr_cast<void*, void(SPUThread*)>(invalidate_jit)), asmjit::FuncSignature1<u32, SPUThread*>(asmjit::CallConv::kIdHost));
call->setArg(0, *cpu);
} }
void spu_recompiler::MFSPR(spu_opcode_t op) void spu_recompiler::MFSPR(spu_opcode_t op)
@@ -623,16 +623,6 @@ void spu_recompiler::ROT(spu_opcode_t op)
return; return;
} }
if (utils::has_xop())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc();
c->vprotd(vt, va, vb);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
return;
}
auto body = [](u32* t, const u32* a, const s32* b) noexcept auto body = [](u32* t, const u32* a, const s32* b) noexcept
{ {
for (u32 i = 0; i < 4; i++) for (u32 i = 0; i < 4; i++)
@@ -672,22 +662,6 @@ void spu_recompiler::ROTM(spu_opcode_t op)
return; return;
} }
if (utils::has_xop())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc();
c->psubd(vb, XmmConst(_mm_set1_epi32(1)));
c->pandn(vb, XmmConst(_mm_set1_epi32(0x3f)));
c->pxor(vt, vt);
c->psubd(vt, vb);
c->pcmpgtd(vb, XmmConst(_mm_set1_epi32(31)));
c->vpshld(vt, va, vt);
c->vpandn(vt, vb, vt);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
return;
}
auto body = [](u32* t, const u32* a, const u32* b) noexcept auto body = [](u32* t, const u32* a, const u32* b) noexcept
{ {
for (u32 i = 0; i < 4; i++) for (u32 i = 0; i < 4; i++)
@@ -728,21 +702,6 @@ void spu_recompiler::ROTMA(spu_opcode_t op)
return; return;
} }
if (utils::has_xop())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc();
c->psubd(vb, XmmConst(_mm_set1_epi32(1)));
c->pandn(vb, XmmConst(_mm_set1_epi32(0x3f)));
c->pxor(vt, vt);
c->pminud(vb, XmmConst(_mm_set1_epi32(31)));
c->psubd(vt, vb);
c->vpshad(vt, va, vt);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
return;
}
auto body = [](s32* t, const s32* a, const u32* b) noexcept auto body = [](s32* t, const s32* a, const u32* b) noexcept
{ {
for (u32 i = 0; i < 4; i++) for (u32 i = 0; i < 4; i++)
@@ -782,19 +741,6 @@ void spu_recompiler::SHL(spu_opcode_t op)
return; return;
} }
if (utils::has_xop())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc();
c->pand(vb, XmmConst(_mm_set1_epi32(0x3f)));
c->vpcmpgtd(vt, vb, XmmConst(_mm_set1_epi32(31)));
c->vpshld(vb, va, vb);
c->pandn(vt, vb);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
return;
}
auto body = [](u32* t, const u32* a, const u32* b) noexcept auto body = [](u32* t, const u32* a, const u32* b) noexcept
{ {
for (u32 i = 0; i < 4; i++) for (u32 i = 0; i < 4; i++)
@@ -828,24 +774,13 @@ void spu_recompiler::ROTH(spu_opcode_t op) //nf
const XmmLink& vb = XmmGet(op.rb, XmmType::Int); const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc(); const XmmLink& vt = XmmAlloc();
const XmmLink& v4 = XmmAlloc(); const XmmLink& v4 = XmmAlloc();
c->vmovdqa(v4, XmmConst(_mm_set_epi32(0x0d0c0d0c, 0x09080908, 0x05040504, 0x01000100))); c->movdqa(v4, XmmConst(_mm_set1_epi16(0xf)));
c->vpshufb(vt, va, v4); // duplicate low word c->pand(vb, v4);
c->vpsrld(va, va, 16); c->vpsllvw(vt, va, vb);
c->vpshufb(va, va, v4); c->psubw(vb, XmmConst(_mm_set1_epi16(1)));
c->vpsrld(v4, vb, 16); c->pandn(vb, v4);
c->vprolvd(va, va, v4); c->vpsrlvw(va, va, vb);
c->vprolvd(vb, vt, vb); c->por(vt, va);
c->vpblendw(vt, vb, va, 0xaa);
c->vmovdqa(SPU_OFF_128(gpr, op.rt), vt);
return;
}
if (utils::has_xop())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc();
c->vprotw(vt, va, vb);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt); c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
return; return;
} }
@@ -889,42 +824,6 @@ void spu_recompiler::ROTHM(spu_opcode_t op)
return; return;
} }
if (utils::has_avx2())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc();
const XmmLink& v4 = XmmAlloc();
const XmmLink& v5 = XmmAlloc();
c->psubw(vb, XmmConst(_mm_set1_epi16(1)));
c->pandn(vb, XmmConst(_mm_set1_epi16(0x1f)));
c->movdqa(vt, XmmConst(_mm_set1_epi32(0xffff0000))); // mask: select high words
c->vpsrld(v4, vb, 16);
c->vpsubusw(v5, vb, vt); // clear high words (using saturation sub for throughput)
c->vpandn(vb, vt, va); // clear high words
c->vpsrlvd(va, va, v4);
c->vpsrlvd(vb, vb, v5);
c->vpblendw(vt, vb, va, 0xaa); // can use vpblendvb with 0xffff0000 mask (vt)
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
return;
}
if (utils::has_xop())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc();
c->psubw(vb, XmmConst(_mm_set1_epi16(1)));
c->pandn(vb, XmmConst(_mm_set1_epi16(0x1f)));
c->pxor(vt, vt);
c->psubw(vt, vb);
c->pcmpgtw(vb, XmmConst(_mm_set1_epi16(15)));
c->vpshlw(vt, va, vt);
c->vpandn(vt, vb, vt);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
return;
}
auto body = [](u16* t, const u16* a, const u16* b) noexcept auto body = [](u16* t, const u16* a, const u16* b) noexcept
{ {
for (u32 i = 0; i < 8; i++) for (u32 i = 0; i < 8; i++)
@@ -965,43 +864,6 @@ void spu_recompiler::ROTMAH(spu_opcode_t op)
return; return;
} }
if (utils::has_avx2())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc();
const XmmLink& v4 = XmmAlloc();
const XmmLink& v5 = XmmAlloc();
c->psubw(vb, XmmConst(_mm_set1_epi16(1)));
c->movdqa(vt, XmmConst(_mm_set1_epi16(0x1f)));
c->vpandn(v4, vb, vt);
c->vpand(v5, vb, vt);
c->movdqa(vt, XmmConst(_mm_set1_epi32(0x2f)));
c->vpsrld(v4, v4, 16);
c->vpsubusw(v5, vt, v5); // clear high word and add 16 to low word
c->vpslld(vb, va, 16);
c->vpsravd(va, va, v4);
c->vpsravd(vb, vb, v5);
c->vpblendw(vt, vb, va, 0xaa);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
return;
}
if (utils::has_xop())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc();
c->psubw(vb, XmmConst(_mm_set1_epi16(1)));
c->pandn(vb, XmmConst(_mm_set1_epi16(0x1f)));
c->pxor(vt, vt);
c->pminuw(vb, XmmConst(_mm_set1_epi16(15)));
c->psubw(vt, vb);
c->vpshaw(vt, va, vt);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
return;
}
auto body = [](s16* t, const s16* a, const u16* b) noexcept auto body = [](s16* t, const s16* a, const u16* b) noexcept
{ {
for (u32 i = 0; i < 8; i++) for (u32 i = 0; i < 8; i++)
@@ -1041,38 +903,6 @@ void spu_recompiler::SHLH(spu_opcode_t op)
return; return;
} }
if (utils::has_avx2())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc();
const XmmLink& v4 = XmmAlloc();
const XmmLink& v5 = XmmAlloc();
c->pand(vb, XmmConst(_mm_set1_epi16(0x1f)));
c->movdqa(vt, XmmConst(_mm_set1_epi32(0xffff0000))); // mask: select high words
c->vpsrld(v4, vb, 16);
c->vpsubusw(v5, vb, vt); // clear high words (using saturation sub for throughput)
c->vpand(vb, vt, va); // clear low words
c->vpsllvd(va, va, v5);
c->vpsllvd(vb, vb, v4);
c->vpblendw(vt, vb, va, 0x55);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
return;
}
if (utils::has_xop())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& vb = XmmGet(op.rb, XmmType::Int);
const XmmLink& vt = XmmAlloc();
c->pand(vb, XmmConst(_mm_set1_epi16(0x1f)));
c->vpcmpgtw(vt, vb, XmmConst(_mm_set1_epi16(15)));
c->vpshlw(vb, va, vb);
c->pandn(vt, vb);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
return;
}
auto body = [](u16* t, const u16* a, const u16* b) noexcept auto body = [](u16* t, const u16* a, const u16* b) noexcept
{ {
for (u32 i = 0; i < 8; i++) for (u32 i = 0; i < 8; i++)
@@ -1111,14 +941,6 @@ void spu_recompiler::ROTI(spu_opcode_t op)
return; return;
} }
if (utils::has_xop())
{
const XmmLink& va = XmmGet(op.ra, XmmType::Int);
c->vprotd(va, va, s);
c->movdqa(SPU_OFF_128(gpr, op.rt), va);
return;
}
const XmmLink& va = XmmGet(op.ra, XmmType::Int); const XmmLink& va = XmmGet(op.ra, XmmType::Int);
const XmmLink& v1 = XmmAlloc(); const XmmLink& v1 = XmmAlloc();
c->movdqa(v1, va); c->movdqa(v1, va);
@@ -1716,57 +1538,50 @@ void spu_recompiler::CDX(spu_opcode_t op)
void spu_recompiler::ROTQBI(spu_opcode_t op) void spu_recompiler::ROTQBI(spu_opcode_t op)
{ {
const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->mov(*qw0, SPU_OFF_64(gpr, op.ra, &v128::_u64, 0));
const XmmLink& vb = XmmGet(op.rb, XmmType::Int); c->mov(*qw1, SPU_OFF_64(gpr, op.ra, &v128::_u64, 1));
const XmmLink& vt = XmmAlloc(); c->mov(*qw2, *qw0);
const XmmLink& v4 = XmmAlloc(); c->mov(*addr, SPU_OFF_32(gpr, op.rb, &v128::_u32, 3));
c->psrldq(vb, 12); c->and_(*addr, 7);
c->pand(vb, XmmConst(_mm_set_epi64x(0, 7))); c->shld(*qw0, *qw1, *addr);
c->movdqa(v4, XmmConst(_mm_set_epi64x(0, 64))); c->shld(*qw1, *qw2, *addr);
c->pshufd(vt, va, 0x4e); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 0), *qw0);
c->psubq(v4, vb); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 1), *qw1);
c->psllq(va, vb); c->unuse(*addr);
c->psrlq(vt, v4); c->unuse(*qw0);
c->por(vt, va); c->unuse(*qw1);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt); c->unuse(*qw2);
} }
void spu_recompiler::ROTQMBI(spu_opcode_t op) void spu_recompiler::ROTQMBI(spu_opcode_t op)
{ {
const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->mov(*qw0, SPU_OFF_64(gpr, op.ra, &v128::_u64, 0));
const XmmLink& vb = XmmAlloc(); c->mov(*qw1, SPU_OFF_64(gpr, op.ra, &v128::_u64, 1));
const XmmLink& vt = XmmGet(op.rb, XmmType::Int); c->mov(*addr, SPU_OFF_32(gpr, op.rb, &v128::_u32, 3));
const XmmLink& v4 = XmmAlloc(); c->neg(*addr);
c->psrldq(vt, 12); c->and_(*addr, 7);
c->pxor(vb, vb); c->shrd(*qw0, *qw1, *addr);
c->psubq(vb, vt); c->shr(*qw1, *addr);
c->pand(vb, XmmConst(_mm_set_epi64x(0, 7))); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 0), *qw0);
c->movdqa(v4, XmmConst(_mm_set_epi64x(0, 64))); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 1), *qw1);
c->movdqa(vt, va); c->unuse(*addr);
c->psrldq(vt, 8); c->unuse(*qw0);
c->psubq(v4, vb); c->unuse(*qw1);
c->psrlq(va, vb);
c->psllq(vt, v4);
c->por(vt, va);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
} }
void spu_recompiler::SHLQBI(spu_opcode_t op) void spu_recompiler::SHLQBI(spu_opcode_t op)
{ {
const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->mov(*qw0, SPU_OFF_64(gpr, op.ra, &v128::_u64, 0));
const XmmLink& vb = XmmGet(op.rb, XmmType::Int); c->mov(*qw1, SPU_OFF_64(gpr, op.ra, &v128::_u64, 1));
const XmmLink& vt = XmmAlloc(); c->mov(*addr, SPU_OFF_32(gpr, op.rb, &v128::_u32, 3));
const XmmLink& v4 = XmmAlloc(); c->and_(*addr, 7);
c->psrldq(vb, 12); c->shld(*qw1, *qw0, *addr);
c->pand(vb, XmmConst(_mm_set_epi64x(0, 7))); c->shl(*qw0, *addr);
c->movdqa(v4, XmmConst(_mm_set_epi64x(0, 64))); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 0), *qw0);
c->movdqa(vt, va); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 1), *qw1);
c->pslldq(vt, 8); c->unuse(*addr);
c->psubq(v4, vb); c->unuse(*qw0);
c->psllq(va, vb); c->unuse(*qw1);
c->psrlq(vt, v4);
c->por(vt, va);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt);
} }
void spu_recompiler::ROTQBY(spu_opcode_t op) void spu_recompiler::ROTQBY(spu_opcode_t op)
@@ -1867,14 +1682,16 @@ void spu_recompiler::SHLQBY(spu_opcode_t op)
void spu_recompiler::ORX(spu_opcode_t op) void spu_recompiler::ORX(spu_opcode_t op)
{ {
const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->mov(*addr, SPU_OFF_32(gpr, op.ra, &v128::_u32, 0));
const XmmLink& v1 = XmmAlloc(); c->or_(*addr, SPU_OFF_32(gpr, op.ra, &v128::_u32, 1));
c->pshufd(v1, va, 0xb1); c->or_(*addr, SPU_OFF_32(gpr, op.ra, &v128::_u32, 2));
c->por(va, v1); c->or_(*addr, SPU_OFF_32(gpr, op.ra, &v128::_u32, 3));
c->pshufd(v1, va, 0x4e); c->mov(SPU_OFF_32(gpr, op.rt, &v128::_u32, 3), *addr);
c->por(va, v1); c->xor_(*addr, *addr);
c->pslldq(va, 12); c->mov(SPU_OFF_32(gpr, op.rt, &v128::_u32, 0), *addr);
c->movdqa(SPU_OFF_128(gpr, op.rt), va); c->mov(SPU_OFF_32(gpr, op.rt, &v128::_u32, 1), *addr);
c->mov(SPU_OFF_32(gpr, op.rt, &v128::_u32, 2), *addr);
c->unuse(*addr);
} }
void spu_recompiler::CBD(spu_opcode_t op) void spu_recompiler::CBD(spu_opcode_t op)
@@ -1981,37 +1798,40 @@ void spu_recompiler::CDD(spu_opcode_t op)
void spu_recompiler::ROTQBII(spu_opcode_t op) void spu_recompiler::ROTQBII(spu_opcode_t op)
{ {
const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->mov(*qw0, SPU_OFF_64(gpr, op.ra, &v128::_u64, 0));
const XmmLink& vt = XmmAlloc(); c->mov(*qw1, SPU_OFF_64(gpr, op.ra, &v128::_u64, 1));
c->pshufd(vt, va, 0x4e); // swap 64-bit parts c->mov(*qw2, *qw0);
c->psllq(va, (op.i7 & 0x7)); c->shld(*qw0, *qw1, op.i7 & 0x7);
c->psrlq(vt, 64 - (op.i7 & 0x7)); c->shld(*qw1, *qw2, op.i7 & 0x7);
c->por(vt, va); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 0), *qw0);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 1), *qw1);
c->unuse(*qw0);
c->unuse(*qw1);
c->unuse(*qw2);
} }
void spu_recompiler::ROTQMBII(spu_opcode_t op) void spu_recompiler::ROTQMBII(spu_opcode_t op)
{ {
const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->mov(*qw0, SPU_OFF_64(gpr, op.ra, &v128::_u64, 0));
const XmmLink& vt = XmmAlloc(); c->mov(*qw1, SPU_OFF_64(gpr, op.ra, &v128::_u64, 1));
c->movdqa(vt, va); c->shrd(*qw0, *qw1, 0-op.i7 & 0x7);
c->psrldq(vt, 8); c->shr(*qw1, 0-op.i7 & 0x7);
c->psrlq(va, ((0 - op.i7) & 0x7)); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 0), *qw0);
c->psllq(vt, 64 - ((0 - op.i7) & 0x7)); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 1), *qw1);
c->por(vt, va); c->unuse(*qw0);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt); c->unuse(*qw1);
} }
void spu_recompiler::SHLQBII(spu_opcode_t op) void spu_recompiler::SHLQBII(spu_opcode_t op)
{ {
const XmmLink& va = XmmGet(op.ra, XmmType::Int); c->mov(*qw0, SPU_OFF_64(gpr, op.ra, &v128::_u64, 0));
const XmmLink& vt = XmmAlloc(); c->mov(*qw1, SPU_OFF_64(gpr, op.ra, &v128::_u64, 1));
c->movdqa(vt, va); c->shld(*qw1, *qw0, op.i7 & 0x7);
c->pslldq(vt, 8); c->shl(*qw0, op.i7 & 0x7);
c->psllq(va, (op.i7 & 0x7)); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 0), *qw0);
c->psrlq(vt, 64 - (op.i7 & 0x7)); c->mov(SPU_OFF_64(gpr, op.rt, &v128::_u64, 1), *qw1);
c->por(vt, va); c->unuse(*qw0);
c->movdqa(SPU_OFF_128(gpr, op.rt), vt); c->unuse(*qw1);
} }
void spu_recompiler::ROTQBYI(spu_opcode_t op) void spu_recompiler::ROTQBYI(spu_opcode_t op)
@@ -3478,13 +3298,6 @@ void spu_recompiler::SELB(spu_opcode_t op)
return; return;
} }
if (utils::has_xop())
{
c->vpcmov(vc, vb, SPU_OFF_128(gpr, op.ra), vc);
c->movdqa(SPU_OFF_128(gpr, op.rt4), vc);
return;
}
c->pand(vb, vc); c->pand(vb, vc);
c->pandn(vc, SPU_OFF_128(gpr, op.ra)); c->pandn(vc, SPU_OFF_128(gpr, op.ra));
c->por(vb, vc); c->por(vb, vc);
@@ -3609,10 +3422,6 @@ void spu_recompiler::SHUFB(spu_opcode_t op)
{ {
c->vpternlogd(vc, va, vb, 0xca /* A?B:C */); c->vpternlogd(vc, va, vb, 0xca /* A?B:C */);
} }
else if (utils::has_xop())
{
c->vpcmov(vc, va, vb, vc);
}
else else
{ {
c->pand(va, vc); c->pand(va, vc);
+7 -13
View File
@@ -1,17 +1,11 @@
#pragma once #pragma once
#include "SPURecompiler.h" #define ASMJIT_STATIC
#define ASMJIT_DEBUG
namespace asmjit #include "asmjit.h"
{
struct JitRuntime; #include "SPURecompiler.h"
struct CodeHolder;
struct X86Compiler;
struct X86Gp;
struct X86Xmm;
struct X86Mem;
struct Label;
}
// SPU ASMJIT Recompiler // SPU ASMJIT Recompiler
class spu_recompiler : public spu_recompiler_base class spu_recompiler : public spu_recompiler_base
@@ -21,7 +15,7 @@ class spu_recompiler : public spu_recompiler_base
public: public:
spu_recompiler(); spu_recompiler();
virtual void compile(spu_function_t& f) override; virtual bool compile(spu_function_contents_t* f) override;
private: private:
// emitter: // emitter:
@@ -41,7 +35,7 @@ private:
std::array<asmjit::X86Xmm*, 6> vec; std::array<asmjit::X86Xmm*, 6> vec;
// labels: // labels:
asmjit::Label* labels; // array[0x10000] std::unique_ptr<asmjit::Label[]> labels; // array[0x10000]
asmjit::Label* jt; // jump table resolver (uses *addr) asmjit::Label* jt; // jump table resolver (uses *addr)
asmjit::Label* end; // function end (return *addr) asmjit::Label* end; // function end (return *addr)
+54 -19
View File
@@ -5,16 +5,18 @@
const spu_decoder<spu_itype> s_spu_itype; const spu_decoder<spu_itype> s_spu_itype;
spu_function_t* SPUDatabase::find(const be_t<u32>* data, u64 key, u32 max_size) spu_function_contents_t* SPUDatabase::find(const be_t<u32>* data, u64 key, u32 max_size, void* ignore)
{ {
for (auto found = m_db.equal_range(key); found.first != found.second; found.first++) for (auto found = m_db.equal_range(key); found.first != found.second; found.first++)
{ {
const auto& func = found.first->second; const auto & func = found.first->second;
// TODO remove code after a while if it hasn't been touched, else there's a big memory bloat here and switch memcmp with compare_func
// Compare binary data explicitly (TODO: optimize) // Compare binary data explicitly (TODO: optimize)
if (LIKELY(func->size <= max_size) && std::memcmp(func->data.data(), data, func->size) == 0) if (func != ignore && LIKELY(func->size <= max_size) && std::memcmp(func->data.data(), data, func->size) == 0)
{ {
return func.get(); return func;
} }
} }
@@ -33,8 +35,17 @@ SPUDatabase::~SPUDatabase()
// TODO: serialize database // TODO: serialize database
} }
spu_function_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_limit) bool IsDeterministicBranch(spu_itype::type type)
{ {
return type == spu_itype::BR || type == spu_itype::BRSL
|| type == spu_itype::BRA || type == spu_itype::BRASL
|| type == spu_itype::BI || type == spu_itype::BISL
|| type == spu_itype::IRET;
}
spu_function_contents_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, void* ignore /*=nullptr*/)
{
const u32 max_limit = 0x40000;
// Check arguments (bounds and alignment) // Check arguments (bounds and alignment)
if (max_limit > 0x40000 || entry >= max_limit || entry % 4 || max_limit % 4) if (max_limit > 0x40000 || entry >= max_limit || entry % 4 || max_limit % 4)
{ {
@@ -42,7 +53,12 @@ spu_function_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_lim
} }
// Key for multimap // Key for multimap
const u64 key = entry | u64{ ls[entry / 4] } << 32; u32 xor_base = 0;
for (u32 i = 0; i < 10; i++)
{
xor_base ^= ls[(entry / 4) + i];
}
const u64 key = entry | u64{ xor_base } << 32;
const be_t<u32>* base = ls + entry / 4; const be_t<u32>* base = ls + entry / 4;
const u32 block_sz = max_limit - entry; const u32 block_sz = max_limit - entry;
@@ -56,19 +72,11 @@ spu_function_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_lim
} }
} }
{
writer_lock lock(m_mutex);
// Double-check
if (auto func = find(base, key, block_sz))
{
return func;
}
}
// Initialize block entries with the function entry point // Initialize block entries with the function entry point
std::set<u32> blocks{ entry }; std::set<u32> blocks{ entry };
std::vector<u32> blocks_size;
// Entries of adjacent functions; jump table entries // Entries of adjacent functions; jump table entries
std::set<u32> adjacent, jt; std::set<u32> adjacent, jt;
@@ -84,15 +92,21 @@ spu_function_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_lim
// Find preliminary set of possible block entries (first pass), `start` is the current block address // Find preliminary set of possible block entries (first pass), `start` is the current block address
for (u32 start = entry, pos = entry; pos < limit; pos += 4) for (u32 start = entry, pos = entry; pos < limit; pos += 4)
{ {
u32 xor_base = 0;
for (u32 i = 0; i < 10; i++)
{
xor_base ^= ls[(pos / 4) + i];
}
const spu_opcode_t op{ ls[pos / 4] }; const spu_opcode_t op{ ls[pos / 4] };
const auto type = s_spu_itype.decode(op.opcode); const auto type = s_spu_itype.decode(op.opcode);
if (pos != entry)
{ {
reader_lock lock(m_mutex); reader_lock lock(m_mutex);
// Find existing function // Find existing function
if (pos != entry && find(ls + pos / 4, pos | u64{ op.opcode } << 32, limit - pos)) if (find(ls + pos / 4, pos | u64{ ls[pos / 4] } << 32, limit - pos))
{ {
limit = pos; limit = pos;
break; break;
@@ -307,8 +321,27 @@ spu_function_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_lim
return nullptr; return nullptr;
} }
blocks_size.reserve(blocks.size());
for (u32 block : blocks)
{
u32 size = 0;
for (u32 i = block / 4; i < 0x10000; i++)
{
if (ls[i] == 0 || IsDeterministicBranch(s_spu_itype.decode(ls[i])))
{
size = (i * 4) - block + 4;
break;
}
}
if (size == 0)
{
verify("No way out of a block"), size != 0;
}
blocks_size.push_back(size);
}
// Prepare new function (set addr and size) // Prepare new function (set addr and size)
auto func = std::make_shared<spu_function_t>(entry, limit - entry); auto func = new spu_function_contents_t(entry, limit - entry);
// Copy function contents // Copy function contents
func->data = { ls + entry / 4, ls + limit / 4 }; func->data = { ls + entry / 4, ls + limit / 4 };
@@ -340,6 +373,8 @@ spu_function_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_lim
} }
} }
func->blocks_size = std::move(blocks_size);
// Set whether the function can reset stack // Set whether the function can reset stack
func->does_reset_stack = ila_sp_pos < limit; func->does_reset_stack = ila_sp_pos < limit;
@@ -354,5 +389,5 @@ spu_function_t* SPUDatabase::analyse(const be_t<u32>* ls, u32 entry, u32 max_lim
LOG_NOTICE(SPU, "Function detected [0x%05x-0x%05x] (size=0x%x)", func->addr, func->addr + func->size, func->size); LOG_NOTICE(SPU, "Function detected [0x%05x-0x%05x] (size=0x%x)", func->addr, func->addr + func->size, func->size);
return func.get(); return func;
} }
+33 -8
View File
@@ -2,7 +2,9 @@
#include "Utilities/mutex.h" #include "Utilities/mutex.h"
#include <map>
#include <set> #include <set>
#include <memory>
// SPU Instruction Type // SPU Instruction Type
struct spu_itype struct spu_itype
@@ -246,8 +248,10 @@ struct spu_itype
class SPUThread; class SPUThread;
typedef u32(*CompiledFunc)(SPUThread* _spu, be_t<u32>* _ls);
// SPU basic function information structure // SPU basic function information structure
struct spu_function_t struct spu_function_contents_t
{ {
// Entry point (LS address) // Entry point (LS address)
const u32 addr; const u32 addr;
@@ -261,6 +265,9 @@ struct spu_function_t
// Basic blocks (start addresses) // Basic blocks (start addresses)
std::set<u32> blocks; std::set<u32> blocks;
// Basic blocks size
std::vector<u32> blocks_size;
// Functions possibly called by this function (may not be available) // Functions possibly called by this function (may not be available)
std::set<u32> adjacent; std::set<u32> adjacent;
@@ -271,30 +278,48 @@ struct spu_function_t
bool does_reset_stack; bool does_reset_stack;
// Pointer to the compiled function // Pointer to the compiled function
u32(*compiled)(SPUThread* _spu, be_t<u32>* _ls) = nullptr; CompiledFunc compiled = nullptr;
spu_function_t(u32 addr, u32 size) spu_function_contents_t(u32 addr, u32 size)
: addr(addr) : addr(addr),
, size(size) size(size)
{ {
} }
}; };
// A single instance of a compiled function, currently in use
union spu_function_t
{
// The function itself and its data
spu_function_contents_t * contents;
// Whether pages the function is in were written to since its last execution
bool dirty_bit : 1;
operator bool()
{
return contents != nullptr;
}
spu_function_t() : contents(nullptr) {};
~spu_function_t() {};
};
// SPU Function Database (must be global or PS3 process-local) // SPU Function Database (must be global or PS3 process-local)
class SPUDatabase final : spu_itype class SPUDatabase final : spu_itype
{ {
shared_mutex m_mutex; shared_mutex m_mutex;
// All registered functions (uses addr and first instruction as a key) // All registered functions (uses addr and first instruction as a key)
std::unordered_multimap<u64, std::shared_ptr<spu_function_t>> m_db; std::unordered_multimap<u64, spu_function_contents_t*> m_db;
// For internal use // For internal use
spu_function_t* find(const be_t<u32>* data, u64 key, u32 max_size); spu_function_contents_t* find(const be_t<u32>* data, u64 key, u32 max_size, void* ignore = nullptr);
public: public:
SPUDatabase(); SPUDatabase();
~SPUDatabase(); ~SPUDatabase();
// Try to retrieve SPU function information // Try to retrieve SPU function information
spu_function_t* analyse(const be_t<u32>* ls, u32 entry, u32 limit = 0x40000); spu_function_contents_t* analyse(const be_t<u32>* ls, u32 entry, void * ignore=nullptr);
}; };
+2 -1
View File
@@ -101,7 +101,8 @@ void spu_interpreter::RDCH(SPUThread& spu, spu_opcode_t op)
} }
else else
{ {
spu.gpr[op.rt] = v128::from32r(result); memset(&spu.gpr[op.rt], 0, 3*sizeof(u32));
spu.gpr[op.rt]._u32[3] = result;
} }
} }
+29 -11
View File
@@ -24,39 +24,57 @@ void spu_recompiler_base::enter(SPUThread& spu)
const auto _ls = vm::_ptr<u32>(spu.offset); const auto _ls = vm::_ptr<u32>(spu.offset);
// Search if cached data matches // Search if cached data matches
auto func = spu.compiled_cache[spu.pc / 4]; auto func_ptr = spu.compiled_cache[spu.pc / 4];
// Check shared db if we dont have a match // Dirty bit check commented out until another code invalidation is found - SYNC, SYNCC, DSYNC and DMAs aren't covering everything
if (!func || !std::equal(func->data.begin(), func->data.end(), _ls + spu.pc / 4, [](const be_t<u32>& l, const be_t<u32>& r) { return *(u32*)(u8*)&l == *(u32*)(u8*)&r; })) if (func_ptr/* && func_ptr->dirty_bit*/)
{ {
func = spu.spu_db->analyse(_ls, spu.pc); auto & func = *func_ptr;
spu.compiled_cache[spu.pc / 4] = func; func.dirty_bit = false;
u32 index = (reinterpret_cast<size_t>(func_ptr) - reinterpret_cast<size_t>(&spu.compiled_functions[0])) / sizeof(func);
spu.first_clean_func_index = std::min<u32>(index, spu.first_clean_func_index);
spu.last_clean_func_index = std::max<u32>(index + 1, spu.last_clean_func_index);
if (!spu.same_function(func.contents, _ls + (spu.pc / 4)))
{
func.contents = spu.spu_db->analyse(_ls, spu.pc, func.contents);
}
}
else if (!func_ptr)
{
auto & func = spu.compiled_functions[++spu.next_compiled_func_index];
func.contents = spu.spu_db->analyse(_ls, spu.pc);
func_ptr = &func;
spu.compiled_cache[spu.pc / 4] = func_ptr;
spu.last_clean_func_index = spu.next_compiled_func_index + 1;
spu.first_clean_func_index = std::min<u32>(spu.first_clean_func_index, spu.next_compiled_func_index);
} }
// Reset callstack if necessary // Reset callstack if necessary
if ((func->does_reset_stack && spu.recursion_level) || spu.recursion_level >= 128) if ((func_ptr->contents->does_reset_stack && spu.recursion_level) || spu.recursion_level >= 128)
{ {
spu.state += cpu_flag::ret; spu.state += cpu_flag::ret;
return; return;
} }
// Compile if needed // Compile if needed
if (!func->compiled) if (!func_ptr->contents->compiled)
{ {
if (!spu.spu_rec) if (!spu.spu_rec)
{ {
spu.spu_rec = fxm::get_always<spu_recompiler>(); spu.spu_rec = fxm::get_always<spu_recompiler>();
} }
spu.spu_rec->compile(*func); spu.spu_rec->compile(func_ptr->contents);
if (!func->compiled) fmt::throw_exception("Compilation failed" HERE); if (!func_ptr->contents->compiled) fmt::throw_exception("Compilation failed" HERE);
} }
const u32 res = func->compiled(&spu, _ls); const u32 res = func_ptr->contents->compiled(&spu, _ls);
if (const auto exception = spu.pending_exception) if (spu.pending_exception)
{ {
const auto exception = spu.pending_exception;
spu.pending_exception = nullptr; spu.pending_exception = nullptr;
std::rethrow_exception(exception); std::rethrow_exception(exception);
} }
+2 -2
View File
@@ -10,7 +10,7 @@ class spu_recompiler_base
protected: protected:
std::mutex m_mutex; // must be locked in compile() std::mutex m_mutex; // must be locked in compile()
const spu_function_t* m_func; // current function const spu_function_contents_t* m_func; // current function
u32 m_pos; // current position u32 m_pos; // current position
@@ -18,7 +18,7 @@ public:
virtual ~spu_recompiler_base(); virtual ~spu_recompiler_base();
// Compile specified function // Compile specified function
virtual void compile(spu_function_t& f) = 0; virtual bool compile(spu_function_contents_t*) = 0;
// Run // Run
static void enter(class SPUThread&); static void enter(class SPUThread&);
+128 -131
View File
@@ -41,6 +41,18 @@ bool operator ==(const u128& lhs, const u128& rhs)
} }
#endif #endif
#ifndef _MSC_VER
FORCE_INLINE void __movsq(unsigned long * Destination, const unsigned long * Source, size_t Count)
{
__asm__ __volatile__
(
"rep; movsq" :
[Destination] "=D" (Destination), [Source] "=S" (Source), [Count] "=c" (Count) :
"[Destination]" (Destination), "[Source]" (Source), "[Count]" (Count)
);
}
#endif
extern u64 get_timebased_time(); extern u64 get_timebased_time();
extern u64 get_system_time(); extern u64 get_system_time();
@@ -134,8 +146,8 @@ namespace spu
{ {
if (timeout_ms > 0) if (timeout_ms > 0)
{ {
const u64 timeout = timeout_ms * 1000u; //convert to microseconds const auto timeout = timeout_ms * 1000ull; //convert to microseconds
const u64 start = get_system_time(); const auto start = get_system_time();
auto remaining = timeout; auto remaining = timeout;
while (atomic_instruction_table[pc_offset].load(std::memory_order_consume) >= max_concurrent_instructions) while (atomic_instruction_table[pc_offset].load(std::memory_order_consume) >= max_concurrent_instructions)
@@ -162,14 +174,14 @@ namespace spu
} }
} }
atomic_instruction_table[pc_offset]++; ++atomic_instruction_table[pc_offset];
} }
void release_pc_address(u32 pc) void release_pc_address(u32 pc)
{ {
const u32 pc_offset = pc >> 2; const u32 pc_offset = pc >> 2;
atomic_instruction_table[pc_offset]--; --atomic_instruction_table[pc_offset];
} }
struct concurrent_execution_watchdog struct concurrent_execution_watchdog
@@ -290,6 +302,8 @@ void SPUThread::on_spawn()
{ {
thread_ctrl::set_native_priority(-1); thread_ctrl::set_native_priority(-1);
} }
++g_num_spu_threads;
} }
void SPUThread::on_init(const std::shared_ptr<void>& _this) void SPUThread::on_init(const std::shared_ptr<void>& _this)
@@ -456,6 +470,7 @@ void SPUThread::do_dma_transfer(const spu_mfc_cmd& args, bool from_mfc)
u32 eal = args.eal; u32 eal = args.eal;
u32 lsa = args.lsa & 0x3ffff; u32 lsa = args.lsa & 0x3ffff;
SPUThread * spu = nullptr;
if (eal >= SYS_SPU_THREAD_BASE_LOW && offset < RAW_SPU_BASE_ADDR) // SPU Thread Group MMIO (LS and SNR) if (eal >= SYS_SPU_THREAD_BASE_LOW && offset < RAW_SPU_BASE_ADDR) // SPU Thread Group MMIO (LS and SNR)
{ {
@@ -464,15 +479,15 @@ void SPUThread::do_dma_transfer(const spu_mfc_cmd& args, bool from_mfc)
if (group && index < group->num && group->threads[index]) if (group && index < group->num && group->threads[index])
{ {
auto& spu = static_cast<SPUThread&>(*group->threads[index]); spu = group->threads[index].get();
if (offset + args.size - 1 < 0x40000) // LS access if (offset + args.size - 1 < 0x40000) // LS access
{ {
eal = spu.offset + offset; // redirect access eal = spu->offset + offset; // redirect access
} }
else if (!is_get && args.size == 4 && (offset == SYS_SPU_THREAD_SNR1 || offset == SYS_SPU_THREAD_SNR2)) else if (!is_get && args.size == 4 && (offset == SYS_SPU_THREAD_SNR1 || offset == SYS_SPU_THREAD_SNR2))
{ {
spu.push_snr(SYS_SPU_THREAD_SNR2 == offset, _ref<u32>(lsa)); spu->push_snr(SYS_SPU_THREAD_SNR2 == offset, _ref<u32>(lsa));
return; return;
} }
else else
@@ -532,84 +547,29 @@ void SPUThread::do_dma_transfer(const spu_mfc_cmd& args, bool from_mfc)
} }
default: default:
{ {
auto vdst = static_cast<__m128i*>(dst); auto vdst = static_cast<u64*>(dst);
auto vsrc = static_cast<const __m128i*>(src); auto vsrc = static_cast<const u64*>(src);
auto vcnt = size / sizeof(__m128i); auto vcnt = size / sizeof(u64);
//if (is_get && !from_mfc) __movsq(vdst, vsrc, vcnt);
{
while (vcnt >= 8)
{
const __m128i data[]
{
_mm_load_si128(vsrc + 0),
_mm_load_si128(vsrc + 1),
_mm_load_si128(vsrc + 2),
_mm_load_si128(vsrc + 3),
_mm_load_si128(vsrc + 4),
_mm_load_si128(vsrc + 5),
_mm_load_si128(vsrc + 6),
_mm_load_si128(vsrc + 7),
};
_mm_store_si128(vdst + 0, data[0]);
_mm_store_si128(vdst + 1, data[1]);
_mm_store_si128(vdst + 2, data[2]);
_mm_store_si128(vdst + 3, data[3]);
_mm_store_si128(vdst + 4, data[4]);
_mm_store_si128(vdst + 5, data[5]);
_mm_store_si128(vdst + 6, data[6]);
_mm_store_si128(vdst + 7, data[7]);
vcnt -= 8;
vsrc += 8;
vdst += 8;
}
while (vcnt--)
{
_mm_store_si128(vdst++, _mm_load_si128(vsrc++));
}
break;
}
// Disabled
while (vcnt >= 8)
{
const __m128i data[]
{
_mm_load_si128(vsrc + 0),
_mm_load_si128(vsrc + 1),
_mm_load_si128(vsrc + 2),
_mm_load_si128(vsrc + 3),
_mm_load_si128(vsrc + 4),
_mm_load_si128(vsrc + 5),
_mm_load_si128(vsrc + 6),
_mm_load_si128(vsrc + 7),
};
_mm_stream_si128(vdst + 0, data[0]);
_mm_stream_si128(vdst + 1, data[1]);
_mm_stream_si128(vdst + 2, data[2]);
_mm_stream_si128(vdst + 3, data[3]);
_mm_stream_si128(vdst + 4, data[4]);
_mm_stream_si128(vdst + 5, data[5]);
_mm_stream_si128(vdst + 6, data[6]);
_mm_stream_si128(vdst + 7, data[7]);
vcnt -= 8;
vsrc += 8;
vdst += 8;
}
while (vcnt--)
{
_mm_stream_si128(vdst++, _mm_load_si128(vsrc++));
}
} }
} }
if (spu)
{
for (u32 i = 0; i < spu->next_compiled_func_index; i++)
{
auto& func = spu->compiled_functions[i];
auto faddr = func.contents->addr;
auto fsize = func.contents->size;
if (fsize + faddr > eal && eal + args.size > faddr)
{
func.dirty_bit = true;
}
}
}
if (is_get && from_mfc) if (is_get && from_mfc)
{ {
//_mm_sfence(); //_mm_sfence();
@@ -662,15 +622,14 @@ void SPUThread::process_mfc_cmd()
if (is_polling) if (is_polling)
{ {
vm::waiter waiter; vm::waiter* waiter = new vm::waiter();
waiter.owner = this; waiter->owner = this;
waiter.addr = raddr; waiter->addr = raddr;
waiter.size = 128; waiter->stamp = rtime;
waiter.stamp = rtime; waiter->data = rdata.data();
waiter.data = rdata.data(); waiter->init();
waiter.init();
while (vm::reservation_acquire(raddr, 128) == waiter.stamp && rdata == data) while (vm::reservation_acquire(raddr, 128) == waiter->stamp && rdata == data)
{ {
if (test(state, cpu_flag::stop)) if (test(state, cpu_flag::stop))
{ {
@@ -679,6 +638,9 @@ void SPUThread::process_mfc_cmd()
thread_ctrl::wait_for(100); thread_ctrl::wait_for(100);
} }
waiter->remove();
waiter = nullptr;
} }
else if (s_use_rtm && utils::transaction_enter()) else if (s_use_rtm && utils::transaction_enter())
{ {
@@ -704,9 +666,11 @@ void SPUThread::process_mfc_cmd()
if (is_polling || UNLIKELY(vm::reservation_acquire(raddr, 128) != rtime)) if (is_polling || UNLIKELY(vm::reservation_acquire(raddr, 128) != rtime))
{ {
// TODO: vm::check_addr // TODO: vm::check_addr
vm::reader_lock lock; {
rtime = vm::reservation_acquire(raddr, 128); vm::reader_lock lock;
rdata = data; rtime = vm::reservation_acquire(raddr, 128);
}
memcpy(rdata.data(), data.data(), rdata.size() * sizeof(rdata[0]));
} }
// Copy to LS // Copy to LS
@@ -723,12 +687,13 @@ void SPUThread::process_mfc_cmd()
bool result = false; bool result = false;
// Check for fast exit in the beginning as well
if (raddr == ch_mfc_cmd.eal && rtime == vm::reservation_acquire(raddr, 128) && rdata == data) if (raddr == ch_mfc_cmd.eal && rtime == vm::reservation_acquire(raddr, 128) && rdata == data)
{ {
// TODO: vm::check_addr // TODO: vm::check_addr
if (s_use_rtm && utils::transaction_enter()) if (s_use_rtm && utils::transaction_enter())
{ {
if (!vm::reader_lock{vm::try_to_lock}) if (!vm::reader_lock{ vm::try_to_lock })
{ {
_xabort(0); _xabort(0);
} }
@@ -746,14 +711,16 @@ void SPUThread::process_mfc_cmd()
} }
else else
{ {
// TODO maybe timeout and check if the lock is still needed in long waits (If rtime changes, no use)
vm::writer_lock lock; vm::writer_lock lock;
if (rtime == vm::reservation_acquire(raddr, 128) && rdata == data) if (rtime == vm::reservation_acquire(raddr, 128))
{ {
data = to_write; data = to_write;
result = true;
vm::reservation_update(raddr, 128); vm::reservation_update(raddr, 128);
lock.unlock();
result = true;
vm::notify(raddr, 128); vm::notify(raddr, 128);
} }
} }
@@ -766,11 +733,10 @@ void SPUThread::process_mfc_cmd()
else else
{ {
ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE); ch_atomic_stat.set_value(MFC_PUTLLC_FAILURE);
} if (raddr)
{
if (raddr && !result) ch_event_stat |= SPU_EVENT_LR;
{ }
ch_event_stat |= SPU_EVENT_LR;
} }
raddr = 0; raddr = 0;
@@ -808,9 +774,11 @@ void SPUThread::process_mfc_cmd()
return; return;
} }
vm::writer_lock lock(0);
data = to_write; data = to_write;
vm::reservation_update(ch_mfc_cmd.eal, 128); {
vm::writer_lock lock(0);
vm::reservation_update(ch_mfc_cmd.eal, 128);
}
vm::notify(ch_mfc_cmd.eal, 128); vm::notify(ch_mfc_cmd.eal, 128);
ch_atomic_stat.set_value(MFC_PUTLLUC_SUCCESS); ch_atomic_stat.set_value(MFC_PUTLLUC_SUCCESS);
@@ -841,18 +809,22 @@ void SPUThread::process_mfc_cmd()
// Try to process small transfers immediately // Try to process small transfers immediately
if (ch_mfc_cmd.size <= max_imm_dma_size && mfc_queue.size() == 0) if (ch_mfc_cmd.size <= max_imm_dma_size && mfc_queue.size() == 0)
{ {
vm::reader_lock lock(vm::try_to_lock); /* TODO catch the exception (Currently they are ignored and slow things down by grabbing a lock)
if (!lock)
{ {
break; vm::reader_lock lock(vm::try_to_lock);
}
if (!vm::check_addr(ch_mfc_cmd.eal, ch_mfc_cmd.size, vm::page_readable | (ch_mfc_cmd.cmd & MFC_PUT_CMD ? vm::page_writable : 0))) if (!lock)
{ {
// TODO break;
break; }
if (!vm::check_addr(ch_mfc_cmd.eal, ch_mfc_cmd.size, vm::page_readable | (ch_mfc_cmd.cmd & MFC_PUT_CMD ? vm::page_writable : 0)))
{
// TODO
break;
}
} }
*/
do_dma_transfer(ch_mfc_cmd, false); do_dma_transfer(ch_mfc_cmd, false);
return; return;
@@ -872,13 +844,6 @@ void SPUThread::process_mfc_cmd()
{ {
if (ch_mfc_cmd.size <= max_imm_dma_size && mfc_queue.size() == 0) if (ch_mfc_cmd.size <= max_imm_dma_size && mfc_queue.size() == 0)
{ {
vm::reader_lock lock(vm::try_to_lock);
if (!lock)
{
break;
}
struct list_element struct list_element
{ {
be_t<u16> sb; be_t<u16> sb;
@@ -909,11 +874,20 @@ void SPUThread::process_mfc_cmd()
break; break;
} }
if (!vm::check_addr(addr, size, vm::page_readable | (ch_mfc_cmd.cmd & MFC_PUT_CMD ? vm::page_writable : 0))) /* TODO Catch and handle exceptions here
{ {
// TODO vm::reader_lock lock(vm::try_to_lock);
break;
} if (!lock)
{
break;
}
if (!vm::check_addr(addr, size, vm::page_readable | (ch_mfc_cmd.cmd & MFC_PUT_CMD ? vm::page_writable : 0)))
{
// TODO
break;
}
}*/
spu_mfc_cmd transfer; spu_mfc_cmd transfer;
transfer.eal = addr; transfer.eal = addr;
@@ -1189,28 +1163,35 @@ bool SPUThread::get_ch_value(u32 ch, u32& out)
return true; return true;
} }
vm::waiter waiter; vm::waiter* waiter = nullptr;
if (ch_event_mask & SPU_EVENT_LR) if (ch_event_mask & SPU_EVENT_LR)
{ {
waiter.owner = this; waiter = new vm::waiter();
waiter.addr = raddr; waiter->owner = this;
waiter.size = 128; waiter->addr = raddr;
waiter.stamp = rtime; waiter->stamp = rtime;
waiter.data = rdata.data(); waiter->data = rdata.data();
waiter.init(); waiter->init();
} }
while (!(res = get_events(true))) while (!(res = get_events(true)))
{ {
if (test(state & cpu_flag::stop)) if (test(state & cpu_flag::stop))
{ {
waiter->remove();
waiter = nullptr;
return false; return false;
} }
thread_ctrl::wait_for(100); thread_ctrl::wait_for(100);
} }
if (waiter != nullptr)
{
waiter->remove();
waiter = nullptr;
}
out = res; out = res;
return true; return true;
} }
@@ -1842,6 +1823,22 @@ bool SPUThread::stop_and_signal(u32 code)
} }
} }
bool SPUThread::same_function(const spu_function_contents_t * func, const void * addr)
{
auto size = func->blocks_size.cbegin();
auto dst = reinterpret_cast<const u8 *>(addr);
auto src = vm::ps3::_ptr<u8>(offset);
for (auto block : func->blocks)
{
u32 offset = block - func->addr;
if (memcmp(src + offset, dst + offset, *size) != 0) return false;
size++;
}
return true;
}
void SPUThread::halt() void SPUThread::halt()
{ {
LOG_TRACE(SPU, "halt()"); LOG_TRACE(SPU, "halt()");
+17 -14
View File
@@ -3,6 +3,7 @@
#include "Emu/Cell/Common.h" #include "Emu/Cell/Common.h"
#include "Emu/CPU/CPUThread.h" #include "Emu/CPU/CPUThread.h"
#include "Emu/Cell/SPUInterpreter.h" #include "Emu/Cell/SPUInterpreter.h"
#include "Emu/Cell/SPURecompiler.h"
#include "MFC.h" #include "MFC.h"
struct lv2_event_queue; struct lv2_event_queue;
@@ -212,22 +213,15 @@ public:
// returns true on success // returns true on success
bool try_pop(u32& out) bool try_pop(u32& out)
{ {
const auto old = data.fetch_op([&](sync_var_t& data) const auto old = data.fetch_op([](sync_var_t& data)
{ {
if (data.count) sync_var_t t{};
{ t.wait = !data.count;
data.wait = false; data = t;
out = data.value;
}
else
{
data.wait = true;
}
data.count = false;
data.value = 0; // ???
}); });
out = old.value;
return old.count; return old.count;
} }
@@ -585,7 +579,15 @@ public:
std::exception_ptr pending_exception; std::exception_ptr pending_exception;
std::array<struct spu_function_t*, 65536> compiled_cache{}; // No need for shared_ptr in the following two, as whenever something is removed or added to one,
// the same goes for the other.
std::array<spu_function_t*, 65536> compiled_cache{};
std::array<spu_function_t, 65536> compiled_functions{};
u32 next_compiled_func_index = -1;
u32 first_clean_func_index = 0;
u32 last_clean_func_index = 0;
std::shared_ptr<class SPUDatabase> spu_db; std::shared_ptr<class SPUDatabase> spu_db;
std::shared_ptr<class spu_recompiler_base> spu_rec; std::shared_ptr<class spu_recompiler_base> spu_rec;
u32 recursion_level = 0; u32 recursion_level = 0;
@@ -601,6 +603,7 @@ public:
bool get_ch_value(u32 ch, u32& out); bool get_ch_value(u32 ch, u32& out);
bool set_ch_value(u32 ch, u32 value); bool set_ch_value(u32 ch, u32 value);
bool stop_and_signal(u32 code); bool stop_and_signal(u32 code);
bool same_function(const spu_function_contents_t * func, const void * addr);
void halt(); void halt();
void fast_call(u32 ls_addr); void fast_call(u32 ls_addr);
+6
View File
@@ -777,6 +777,12 @@ error_code sys_spu_thread_write_ls(u32 id, u32 lsa, u64 value, u32 type)
default: return CELL_EINVAL; default: return CELL_EINVAL;
} }
auto func = thread->compiled_cache[lsa / 4];
if (func)
{
func->dirty_bit = true;
}
return CELL_OK; return CELL_OK;
} }
+5 -10
View File
@@ -131,25 +131,20 @@ u64 get_timebased_time()
// Returns some relative time in microseconds, don't change this fact // Returns some relative time in microseconds, don't change this fact
u64 get_system_time() u64 get_system_time()
{ {
#ifdef _WIN32
// Pull the time directly from Windows shared page (Constant location on all Windows machines)
return *reinterpret_cast<u64*>(0x7ffe0014) / 10;
#else
while (true) while (true)
{ {
#ifdef _WIN32
LARGE_INTEGER count;
verify(HERE), QueryPerformanceCounter(&count);
const u64 time = count.QuadPart;
const u64 freq = s_time_aux_info.perf_freq;
const u64 result = time / freq * 1000000u + (time % freq) * 1000000u / freq;
#else
struct timespec ts; struct timespec ts;
verify(HERE), ::clock_gettime(CLOCK_MONOTONIC, &ts) == 0; verify(HERE), ::clock_gettime(CLOCK_MONOTONIC, &ts) == 0;
const u64 result = static_cast<u64>(ts.tv_sec) * 1000000u + static_cast<u64>(ts.tv_nsec) / 1000u; const u64 result = static_cast<u64>(ts.tv_sec) * 1000000u + static_cast<u64>(ts.tv_nsec) / 1000u;
#endif
if (result) return result; if (result) return result;
} }
#endif
} }
// Functions // Functions
+76 -76
View File
@@ -8,16 +8,15 @@
#include "Emu/Cell/lv2/sys_memory.h" #include "Emu/Cell/lv2/sys_memory.h"
#include "Emu/RSX/GSRender.h" #include "Emu/RSX/GSRender.h"
#include <atomic>
#include <deque>
namespace vm namespace vm
{ {
static u8* memory_reserve_4GiB(std::uintptr_t _addr = 0) std::array<memory_page, 0x100000000 / 4096> g_pages{};
static u8* memory_reserve_4GiB(const std::uintptr_t _addr = 0)
{ {
for (u64 addr = _addr + 0x100000000;; addr += 0x100000000) for (auto addr = _addr + 0x100000000;; addr += 0x100000000)
{ {
if (auto ptr = utils::memory_reserve(0x100000000, (void*)addr)) if (const auto ptr = utils::memory_reserve(0x100000000, reinterpret_cast<void*>(addr)))
{ {
return static_cast<u8*>(ptr); return static_cast<u8*>(ptr);
} }
@@ -39,11 +38,13 @@ namespace vm
// Memory locations // Memory locations
std::vector<std::shared_ptr<block_t>> g_locations; std::vector<std::shared_ptr<block_t>> g_locations;
// Reservations (lock lines) in a single memory page
using reservation_info = std::array<std::atomic<u64>, 4096 / 128>;
// Registered waiters // Registered waiters
std::deque<vm::waiter*> g_waiters; std::vector<vm::waiter*> g_waiters;
shared_mutex g_waiters_lock;
// Waiters which will be removed once the lock is freed
shared_mutex g_waiters_to_remove_lock;
std::vector<vm::waiter*> g_waiters_to_remove;
// Memory mutex core // Memory mutex core
shared_mutex g_mutex; shared_mutex g_mutex;
@@ -201,78 +202,38 @@ namespace vm
{ {
} }
writer_lock::~writer_lock() void writer_lock::unlock()
{ {
if (locked) if (locked)
{ {
g_mutex.unlock(); g_mutex.unlock();
locked = false;
} }
} }
// Page information writer_lock::~writer_lock()
struct memory_page
{ {
// Memory flags unlock();
atomic_t<u8> flags;
atomic_t<u32> waiters;
// Reservations
atomic_t<reservation_info*> reservations;
// Access reservation info
std::atomic<u64>& operator [](u32 addr)
{
auto ptr = reservations.load();
if (!ptr)
{
// Opportunistic memory allocation
ptr = new reservation_info{};
if (auto old_ptr = reservations.compare_and_swap(nullptr, ptr))
{
delete ptr;
ptr = old_ptr;
}
}
return (*ptr)[(addr & 0xfff) >> 7];
}
};
// Memory pages
std::array<memory_page, 0x100000000 / 4096> g_pages{};
u64 reservation_acquire(u32 addr, u32 _size)
{
// Access reservation info: stamp and the lock bit
return g_pages[addr >> 12][addr].load(std::memory_order_acquire);
}
void reservation_update(u32 addr, u32 _size)
{
// Update reservation info with new timestamp (unsafe, assume allocated)
(*g_pages[addr >> 12].reservations)[(addr & 0xfff) >> 7].store(__rdtsc(), std::memory_order_release);
} }
void waiter::init() void waiter::init()
{ {
// Register waiter // Register waiter
writer_lock lock(0); g_waiters_lock.lock();
g_waiters.emplace_back(this); g_waiters.emplace_back(this);
g_waiters_lock.unlock();
} }
void waiter::test() const void waiter::test() const
{ {
if (std::memcmp(data, vm::base(addr), size) == 0) const auto owner_copy = owner;
if (!owner_copy)
{ {
return; return;
} }
memory_page& page = g_pages[addr >> 12]; memory_page& page = g_pages[addr >> 12];
if (page.reservations == nullptr) if (page.reservations == nullptr)
{ {
return; return;
@@ -283,28 +244,44 @@ namespace vm
return; return;
} }
if (owner) if (memcmp(data, vm::base(addr), size) == 0)
{ {
owner->notify(); return;
}
owner_copy->notify();
}
void remove_old_waiters()
{
if (!g_waiters_to_remove.empty())
{
g_waiters_to_remove_lock.lock();
for (auto ptr : g_waiters_to_remove)
{
const auto found = std::find(g_waiters.cbegin(), g_waiters.cend(), ptr);
if (found != g_waiters.cend())
{
g_waiters.erase(found);
}
delete ptr;
}
g_waiters_to_remove.clear();
g_waiters_to_remove_lock.unlock();
} }
} }
waiter::~waiter() void waiter::remove()
{ {
// Unregister waiter this->owner = nullptr; // Iterations of the object will ignore it from now on
writer_lock lock(0); g_waiters_to_remove_lock.lock();
g_waiters_to_remove.push_back(this);
// Find waiter g_waiters_to_remove_lock.unlock();
const auto found = std::find(g_waiters.cbegin(), g_waiters.cend(), this);
if (found != g_waiters.cend())
{
g_waiters.erase(found);
}
} }
void notify(u32 addr, u32 size) void notify(u32 addr, u32 size)
{ {
g_waiters_lock.lock_shared();
for (const waiter* ptr : g_waiters) for (const waiter* ptr : g_waiters)
{ {
if (ptr->addr / 128 == addr / 128) if (ptr->addr / 128 == addr / 128)
@@ -312,14 +289,37 @@ namespace vm
ptr->test(); ptr->test();
} }
} }
if (g_waiters_to_remove.size() > 10)
{
g_waiters_lock.lock_upgrade();
remove_old_waiters();
g_waiters_lock.unlock();
}
else
{
g_waiters_lock.unlock_shared();
}
} }
void notify_all() void notify_all()
{ {
g_waiters_lock.lock_shared();
for (const waiter* ptr : g_waiters) for (const waiter* ptr : g_waiters)
{ {
ptr->test(); ptr->test();
} }
if (g_waiters_to_remove.size() > 10)
{
g_waiters_lock.lock_upgrade();
remove_old_waiters();
g_waiters_lock.unlock();
}
else
{
g_waiters_lock.unlock_shared();
}
} }
void _page_map(u32 addr, u32 size, u8 flags) void _page_map(u32 addr, u32 size, u8 flags)
@@ -369,8 +369,8 @@ namespace vm
const u8 flags_both = flags_set & flags_clear; const u8 flags_both = flags_set & flags_clear;
flags_test |= page_allocated; flags_test |= page_allocated;
flags_set &= ~flags_both; flags_set &= ~flags_both;
flags_clear &= ~flags_both; flags_clear &= ~flags_both;
for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++) for (u32 i = addr / 4096; i < addr / 4096 + size / 4096; i++)
@@ -736,7 +736,7 @@ namespace vm
{ {
writer_lock lock(0); writer_lock lock(0);
for (auto it = g_locations.begin(); it != g_locations.end(); it++) for (auto it = g_locations.begin(); it != g_locations.end(); ++it)
{ {
if (*it && (*it)->addr == addr) if (*it && (*it)->addr == addr)
{ {
@@ -835,7 +835,7 @@ void fmt_class_string<vm::_ptr_base<const char>>::format(std::string& out, u64 a
out += u8""; out += u8"";
for (vm::_ptr_base<const volatile char> ptr = vm::cast(arg);; ptr++) for (vm::_ptr_base<const volatile char> ptr = vm::cast(arg);; ++ptr)
{ {
if (!vm::check_addr(ptr.addr())) if (!vm::check_addr(ptr.addr()))
{ {
+51 -8
View File
@@ -1,8 +1,8 @@
#pragma once #pragma once
#include <map> #include <map>
#include <functional>
#include <memory> #include <memory>
#include <atomic>
class named_thread; class named_thread;
class cpu_thread; class cpu_thread;
@@ -42,9 +42,9 @@ namespace vm
{ {
named_thread* owner; named_thread* owner;
u32 addr; u32 addr;
u32 size;
u64 stamp; u64 stamp;
const void* data; const void* data;
static const u32 size = 128; // Always 128 currently
waiter() = default; waiter() = default;
@@ -53,7 +53,7 @@ namespace vm
void init(); void init();
void test() const; void test() const;
~waiter(); void remove();
}; };
// Address type // Address type
@@ -90,21 +90,64 @@ namespace vm
struct writer_lock final struct writer_lock final
{ {
const bool locked; bool locked;
writer_lock(const writer_lock&) = delete; writer_lock(const writer_lock&) = delete;
writer_lock(int full = 1); writer_lock(int full = 1);
writer_lock(const try_to_lock_t&); writer_lock(const try_to_lock_t&);
void unlock();
~writer_lock(); ~writer_lock();
explicit operator bool() const { return locked; } explicit operator bool() const { return locked; }
}; };
// Get reservation status for further atomic update: last update timestamp // Reservations (lock lines) in a single memory page
u64 reservation_acquire(u32 addr, u32 size); using reservation_info = std::array<std::atomic<u64>, 4096 / 128>;
// End atomic update // Page information
void reservation_update(u32 addr, u32 size); struct memory_page
{
// Reservations
atomic_t<reservation_info*> reservations;
//atomic_t<u32> waiters;
// Memory flags
atomic_t<u8> flags;
// Access reservation info
FORCE_INLINE std::atomic<u64>& operator [](const u32 addr)
{
auto ptr = reservations.load();
if (!ptr)
{
ptr = new reservation_info();
// Opportunistic memory allocation
if (const auto old_ptr = reservations.compare_and_swap(nullptr, ptr))
{
delete ptr;
ptr = old_ptr;
}
}
return (*ptr)[(addr & 0xfff) >> 7];
}
};
// Memory pages
extern std::array<memory_page, 0x100000000 / 4096> g_pages;
FORCE_INLINE u64 reservation_acquire(u32 addr, u32 _size)
{
// Access reservation info: stamp and the lock bit
return g_pages[addr >> 12][addr].load(std::memory_order_acquire);
}
FORCE_INLINE void reservation_update(u32 addr, u32 _size)
{
// Update reservation info with new timestamp (unsafe, assume allocated)
(*g_pages[addr >> 12].reservations)[(addr & 0xfff) >> 7].store(__rdtsc(), std::memory_order_release);
}
// Check and notify memory changes at address // Check and notify memory changes at address
void notify(u32 addr, u32 size); void notify(u32 addr, u32 size);
+3 -3
View File
@@ -532,7 +532,7 @@ std::tuple<T, T, u32> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::spa
verify(HERE), (dst.size_bytes() >= src.size_bytes()); verify(HERE), (dst.size_bytes() >= src.size_bytes());
u32 dst_idx = 0; u32 dst_idx = -1;
for (T index : src) for (T index : src)
{ {
if (is_primitive_restart_enabled && index == primitive_restart_index) if (is_primitive_restart_enabled && index == primitive_restart_index)
@@ -549,9 +549,9 @@ std::tuple<T, T, u32> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::spa
min_index = std::min(min_index, index); min_index = std::min(min_index, index);
} }
dst[dst_idx++] = index; dst[++dst_idx] = index;
} }
return std::make_tuple(min_index, max_index, dst_idx); return std::make_tuple(min_index, max_index, dst_idx + 1);
} }
template<typename T> template<typename T>
@@ -111,7 +111,7 @@ void FragmentProgramDecompiler::SetDst(std::string code, bool append_mask)
} }
u32 reg_index = dst.fp16 ? dst.dest_reg >> 1 : dst.dest_reg; u32 reg_index = dst.fp16 ? dst.dest_reg >> 1 : dst.dest_reg;
temp_registers[reg_index].tag(dst.dest_reg, !!dst.fp16); temp_registers[reg_index].tag(dst.dest_reg, !!dst.fp16, dst.mask_x, dst.mask_y, dst.mask_z, dst.mask_w);
} }
void FragmentProgramDecompiler::AddFlowOp(std::string code) void FragmentProgramDecompiler::AddFlowOp(std::string code)
@@ -283,14 +283,15 @@ std::string FragmentProgramDecompiler::Format(const std::string& code, bool igno
{ "$_i", [this]() -> std::string {return std::to_string(dst.tex_num);} }, { "$_i", [this]() -> std::string {return std::to_string(dst.tex_num);} },
{ "$m", std::bind(std::mem_fn(&FragmentProgramDecompiler::GetMask), this) }, { "$m", std::bind(std::mem_fn(&FragmentProgramDecompiler::GetMask), this) },
{ "$ifcond ", [this]() -> std::string { "$ifcond ", [this]() -> std::string
{ {
const std::string& cond = GetCond(); const std::string& cond = GetCond();
if (cond == "true") return ""; if (cond == "true") return "";
return "if(" + cond + ") "; return "if(" + cond + ") ";
} }
}, },
{ "$cond", std::bind(std::mem_fn(&FragmentProgramDecompiler::GetCond), this) }, { "$cond", std::bind(std::mem_fn(&FragmentProgramDecompiler::GetCond), this) },
{ "$_c", std::bind(std::mem_fn(&FragmentProgramDecompiler::AddConst), this) } { "$_c", std::bind(std::mem_fn(&FragmentProgramDecompiler::AddConst), this) },
{ "$float4", [this]() -> std::string { return getFloatTypeName(4); } }
}; };
if (!ignore_redirects) if (!ignore_redirects)
@@ -407,20 +408,13 @@ template<typename T> std::string FragmentProgramDecompiler::GetSRC(T src)
dst.opcode == RSX_FP_OPCODE_UPB || dst.opcode == RSX_FP_OPCODE_UPB ||
dst.opcode == RSX_FP_OPCODE_UPG) dst.opcode == RSX_FP_OPCODE_UPG)
{ {
//TODO: Implement aliased gather for half floats
bool xy_read = false;
bool zw_read = false;
if (src.swizzle_x < 2 || src.swizzle_y < 2 || src.swizzle_z < 2 || src.swizzle_w < 2)
xy_read = true;
if (src.swizzle_x > 1 || src.swizzle_y > 1 || src.swizzle_z > 1 || src.swizzle_w > 1)
zw_read = true;
auto &reg = temp_registers[src.tmp_reg_index]; auto &reg = temp_registers[src.tmp_reg_index];
if (reg.requires_gather(xy_read, zw_read)) if (reg.requires_gather(src.swizzle_x))
{ {
properties.has_gather_op = true; properties.has_gather_op = true;
AddCode(reg.gather_r()); AddReg(src.tmp_reg_index, src.fp16);
ret = getFloatTypeName(4) + reg.gather_r();
break;
} }
} }
} }
@@ -24,25 +24,41 @@ class FragmentProgramDecompiler
bool aliased_r0 = false; bool aliased_r0 = false;
bool aliased_h0 = false; bool aliased_h0 = false;
bool aliased_h1 = false; bool aliased_h1 = false;
bool last_write_half = false; bool last_write_half[4] = { false, false, false, false };
u32 real_index = UINT32_MAX; u32 real_index = UINT32_MAX;
void tag(u32 index, bool half_register) void tag(u32 index, bool half_register, bool x, bool y, bool z, bool w)
{ {
if (half_register) if (half_register)
{ {
last_write_half = true;
if (index & 1) if (index & 1)
{
if (x) last_write_half[2] = true;
if (y) last_write_half[2] = true;
if (z) last_write_half[3] = true;
if (w) last_write_half[3] = true;
aliased_h1 = true; aliased_h1 = true;
}
else else
{
if (x) last_write_half[0] = true;
if (y) last_write_half[0] = true;
if (z) last_write_half[1] = true;
if (w) last_write_half[1] = true;
aliased_h0 = true; aliased_h0 = true;
}
} }
else else
{ {
if (x) last_write_half[0] = false;
if (y) last_write_half[1] = false;
if (z) last_write_half[2] = false;
if (w) last_write_half[3] = false;
aliased_r0 = true; aliased_r0 = true;
last_write_half = false;
} }
if (real_index == UINT32_MAX) if (real_index == UINT32_MAX)
@@ -54,12 +70,19 @@ class FragmentProgramDecompiler
} }
} }
bool requires_gather(bool xy, bool zw) const bool requires_gather(u8 channel) const
{ {
//Data fetched from the single precision register requires merging of the two half registers //Data fetched from the single precision register requires merging of the two half registers
//TODO: Check individual swizzle channels verify(HERE), channel < 4;
if ((aliased_h0 && xy) || (aliased_h1 && zw)) if (aliased_h0 && channel < 2)
return last_write_half; {
return last_write_half[channel];
}
if (aliased_h1 && channel > 1)
{
return last_write_half[channel];
}
return false; return false;
} }
@@ -67,7 +90,7 @@ class FragmentProgramDecompiler
bool requires_split(u32 /*index*/) const bool requires_split(u32 /*index*/) const
{ {
//Data fetched from any of the two half registers requires sync with the full register //Data fetched from any of the two half registers requires sync with the full register
if (!last_write_half && aliased_r0) if (!(last_write_half[0] || last_write_half[1]) && aliased_r0)
{ {
//r0 has been written to //r0 has been written to
//TODO: Check for specific elements in real32 register //TODO: Check for specific elements in real32 register
@@ -85,15 +108,12 @@ class FragmentProgramDecompiler
std::string ret = "//Invalid gather"; std::string ret = "//Invalid gather";
if (aliased_h0 && aliased_h1) if (aliased_h0 && aliased_h1)
ret = reg + " = gather(" + h0 + ", " + h1 + ");"; ret = "(gather(" + h0 + ", " + h1 + "))";
else if (aliased_h0) else if (aliased_h0)
ret = reg + ".xy = gather(" + h0 + ");"; ret = "(gather(" + h0 + "), " + reg + ".zw)";
else if (aliased_h1) else if (aliased_h1)
ret = reg + ".zw = gather(" + h1 + ");"; ret = "(" + reg + ".xy, gather(" + h1 + "))";
last_write_half = false;
aliased_h0 = false;
aliased_h1 = false;
return ret; return ret;
} }
}; };
+10 -2
View File
@@ -78,6 +78,7 @@ namespace program_hash_util
* - static void recompile_fragment_program(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID); * - static void recompile_fragment_program(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID);
* - static void recompile_vertex_program(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, size_t ID); * - static void recompile_vertex_program(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, size_t ID);
* - static PipelineData build_program(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData); * - static PipelineData build_program(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData);
* - static void validate_pipeline_properties(const VertexProgramData &vertexProgramData, const FragmentProgramData &fragmentProgramData, PipelineProperties& props);
*/ */
template<typename backend_traits> template<typename backend_traits>
class program_state_cache class program_state_cache
@@ -261,7 +262,7 @@ public:
pipeline_storage_type& getGraphicPipelineState( pipeline_storage_type& getGraphicPipelineState(
const RSXVertexProgram& vertexShader, const RSXVertexProgram& vertexShader,
const RSXFragmentProgram& fragmentShader, const RSXFragmentProgram& fragmentShader,
const pipeline_properties& pipelineProperties, pipeline_properties& pipelineProperties,
Args&& ...args Args&& ...args
) )
{ {
@@ -273,6 +274,7 @@ public:
bool already_existing_fragment_program = std::get<1>(fp_search); bool already_existing_fragment_program = std::get<1>(fp_search);
bool already_existing_vertex_program = std::get<1>(vp_search); bool already_existing_vertex_program = std::get<1>(vp_search);
backend_traits::validate_pipeline_properties(vertex_program, fragment_program, pipelineProperties);
pipeline_key key = { vertex_program.id, fragment_program.id, pipelineProperties }; pipeline_key key = { vertex_program.id, fragment_program.id, pipelineProperties };
if (already_existing_fragment_program && already_existing_vertex_program) if (already_existing_fragment_program && already_existing_vertex_program)
@@ -305,7 +307,7 @@ public:
return 0; return 0;
} }
void fill_fragment_constants_buffer(gsl::span<f32, gsl::dynamic_range> dst_buffer, const RSXFragmentProgram &fragment_program) const void fill_fragment_constants_buffer(gsl::span<f32, gsl::dynamic_range> dst_buffer, const RSXFragmentProgram &fragment_program, bool sanitize = false) const
{ {
const auto I = m_fragment_shader_cache.find(fragment_program); const auto I = m_fragment_shader_cache.find(fragment_program);
if (I == m_fragment_shader_cache.end()) if (I == m_fragment_shader_cache.end())
@@ -345,6 +347,12 @@ public:
} }
} }
} }
else if (sanitize)
{
//Lower NaNs to 0
const auto mask = _mm_cmpunord_ps((__m128&)shuffled_vector, _mm_set1_ps(1.f));
_mm_stream_si128((__m128i*)dst, (__m128i&)_mm_andnot_ps(mask, (__m128&)shuffled_vector));
}
else else
{ {
_mm_stream_si128((__m128i*)dst, shuffled_vector); _mm_stream_si128((__m128i*)dst, shuffled_vector);
@@ -131,4 +131,9 @@ public:
else else
fmt::throw_exception("m_put_pos == m_get_pos!" HERE); fmt::throw_exception("m_put_pos == m_get_pos!" HERE);
} }
size_t size() const
{
return m_size;
}
}; };
+19 -1
View File
@@ -370,6 +370,7 @@ namespace rsx
virtual void set_up_remap_vector(section_storage_type& section, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) = 0; virtual void set_up_remap_vector(section_storage_type& section, const std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) = 0;
virtual void insert_texture_barrier(commandbuffer_type&, image_storage_type* tex) = 0; virtual void insert_texture_barrier(commandbuffer_type&, image_storage_type* tex) = 0;
virtual image_view_type generate_cubemap_from_images(commandbuffer_type&, u32 gcm_format, u16 size, const std::array<image_resource_type, 6>& sources) = 0; virtual image_view_type generate_cubemap_from_images(commandbuffer_type&, u32 gcm_format, u16 size, const std::array<image_resource_type, 6>& sources) = 0;
virtual bool render_target_format_is_compatible(image_storage_type* tex, u32 gcm_format) = 0;
constexpr u32 get_block_size() const { return 0x1000000; } constexpr u32 get_block_size() const { return 0x1000000; }
inline u32 get_block_address(u32 address) const { return (address & ~0xFFFFFF); } inline u32 get_block_address(u32 address) const { return (address & ~0xFFFFFF); }
@@ -1385,6 +1386,12 @@ namespace rsx
} }
} }
if (!requires_processing)
{
//Check if we need to do anything about the formats
requires_processing = !render_target_format_is_compatible(texptr, format);
}
if (requires_processing) if (requires_processing)
{ {
const auto w = rsx::apply_resolution_scale(internal_width, true); const auto w = rsx::apply_resolution_scale(internal_width, true);
@@ -1620,13 +1627,24 @@ namespace rsx
auto subresources_layout = get_subresources_layout(tex); auto subresources_layout = get_subresources_layout(tex);
auto remap_vector = tex.decoded_remap(); auto remap_vector = tex.decoded_remap();
bool is_depth_format = false;
switch (format)
{
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
is_depth_format = true;
break;
}
//Invalidate with writing=false, discard=false, rebuild=false, native_flush=true //Invalidate with writing=false, discard=false, rebuild=false, native_flush=true
invalidate_range_impl_base(texaddr, tex_size, false, false, false, true, std::forward<Args>(extras)...); invalidate_range_impl_base(texaddr, tex_size, false, false, false, true, std::forward<Args>(extras)...);
m_texture_memory_in_use += (tex_pitch * tex_height); m_texture_memory_in_use += (tex_pitch * tex_height);
return{ upload_image_from_cpu(cmd, texaddr, tex_width, tex_height, depth, tex.get_exact_mipmap_count(), tex_pitch, format, return{ upload_image_from_cpu(cmd, texaddr, tex_width, tex_height, depth, tex.get_exact_mipmap_count(), tex_pitch, format,
texture_upload_context::shader_read, subresources_layout, extended_dimension, is_swizzled, remap_vector)->get_raw_view(), texture_upload_context::shader_read, subresources_layout, extended_dimension, is_swizzled, remap_vector)->get_raw_view(),
texture_upload_context::shader_read, false, scale_x, scale_y, extended_dimension }; texture_upload_context::shader_read, is_depth_format, scale_x, scale_y, extended_dimension };
} }
template <typename surface_store_type, typename blitter_type, typename ...Args> template <typename surface_store_type, typename blitter_type, typename ...Args>
+5
View File
@@ -145,6 +145,11 @@ struct D3D12Traits
vertexProgramData.id = (u32)ID; vertexProgramData.id = (u32)ID;
} }
static
void validate_pipeline_properties(const vertex_program_type&, const fragment_program_type&, pipeline_properties&)
{
}
static static
pipeline_storage_type build_pipeline( pipeline_storage_type build_pipeline(
const vertex_program_type &vertexProgramData, const fragment_program_type &fragmentProgramData, const pipeline_properties &pipelineProperties, const vertex_program_type &vertexProgramData, const fragment_program_type &fragmentProgramData, const pipeline_properties &pipelineProperties,
+14 -17
View File
@@ -736,14 +736,16 @@ void GLGSRender::on_init_thread()
m_index_ring_buffer.reset(new gl::ring_buffer()); m_index_ring_buffer.reset(new gl::ring_buffer());
} }
m_attrib_ring_buffer->create(gl::buffer::target::texture, std::min<GLsizeiptr>(m_max_texbuffer_size, 256 * 0x100000)); m_attrib_ring_buffer->create(gl::buffer::target::texture, 256 * 0x100000);
m_index_ring_buffer->create(gl::buffer::target::element_array, std::min<GLsizeiptr>(m_max_texbuffer_size, 64 * 0x100000)); m_index_ring_buffer->create(gl::buffer::target::element_array, 64 * 0x100000);
m_transform_constants_buffer->create(gl::buffer::target::uniform, std::min<GLsizeiptr>(m_max_texbuffer_size, 16 * 0x100000)); m_transform_constants_buffer->create(gl::buffer::target::uniform, 64 * 0x100000);
m_fragment_constants_buffer->create(gl::buffer::target::uniform, std::min<GLsizeiptr>(m_max_texbuffer_size, 16 * 0x100000)); m_fragment_constants_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
m_vertex_state_buffer->create(gl::buffer::target::uniform, std::min<GLsizeiptr>(m_max_texbuffer_size, 16 * 0x100000)); m_vertex_state_buffer->create(gl::buffer::target::uniform, 16 * 0x100000);
m_gl_persistent_stream_buffer.copy_from(*m_attrib_ring_buffer, GL_R8UI, 0, (u32)m_attrib_ring_buffer->size()); m_persistent_stream_view.update(m_attrib_ring_buffer.get(), 0, m_max_texbuffer_size);
m_gl_volatile_stream_buffer.copy_from(*m_attrib_ring_buffer, GL_R8UI, 0, (u32)m_attrib_ring_buffer->size()); m_volatile_stream_view.update(m_attrib_ring_buffer.get(), 0, m_max_texbuffer_size);
m_gl_persistent_stream_buffer.copy_from(m_persistent_stream_view);
m_gl_volatile_stream_buffer.copy_from(m_volatile_stream_view);
m_vao.element_array_buffer = *m_index_ring_buffer; m_vao.element_array_buffer = *m_index_ring_buffer;
@@ -1034,7 +1036,7 @@ bool GLGSRender::check_program_state()
return (rsx::method_registers.shader_program_address() != 0); return (rsx::method_registers.shader_program_address() != 0);
} }
void GLGSRender::load_program(const vertex_upload_info& upload_info) void GLGSRender::load_program(const gl::vertex_upload_info& upload_info)
{ {
get_current_fragment_program(fs_sampler_state); get_current_fragment_program(fs_sampler_state);
verify(HERE), current_fragment_program.valid; verify(HERE), current_fragment_program.valid;
@@ -1110,7 +1112,10 @@ void GLGSRender::load_program(const vertex_upload_info& upload_info)
buf = static_cast<u8*>(mapping.first); buf = static_cast<u8*>(mapping.first);
fragment_constants_offset = mapping.second; fragment_constants_offset = mapping.second;
if (fragment_constants_size) if (fragment_constants_size)
m_prog_buffer.fill_fragment_constants_buffer({ reinterpret_cast<float*>(buf), gsl::narrow<int>(fragment_constants_size) }, fragment_program); {
m_prog_buffer.fill_fragment_constants_buffer({ reinterpret_cast<float*>(buf), gsl::narrow<int>(fragment_constants_size) },
fragment_program, gl::get_driver_caps().vendor_NVIDIA);
}
// Fragment state // Fragment state
fill_fragment_state_buffer(buf+fragment_constants_size, fragment_program); fill_fragment_state_buffer(buf+fragment_constants_size, fragment_program);
@@ -1399,14 +1404,6 @@ void GLGSRender::flip(int buffer)
m_textures_upload_time = 0; m_textures_upload_time = 0;
} }
u64 GLGSRender::timestamp() const
{
GLint64 result;
glGetInteger64v(GL_TIMESTAMP, &result);
return result;
}
bool GLGSRender::on_access_violation(u32 address, bool is_writing) bool GLGSRender::on_access_violation(u32 address, bool is_writing)
{ {
bool can_flush = (std::this_thread::get_id() == m_thread_id); bool can_flush = (std::this_thread::get_id() == m_thread_id);
+15 -14
View File
@@ -21,6 +21,16 @@ namespace gl
using null_vertex_cache = vertex_cache; using null_vertex_cache = vertex_cache;
using shader_cache = rsx::shaders_cache<void*, GLProgramBuffer>; using shader_cache = rsx::shaders_cache<void*, GLProgramBuffer>;
struct vertex_upload_info
{
u32 vertex_draw_count;
u32 allocated_vertex_count;
u32 vertex_index_base;
u32 persistent_mapping_offset;
u32 volatile_mapping_offset;
std::optional<std::tuple<GLenum, u32> > index_info;
};
} }
struct work_item struct work_item
@@ -88,7 +98,7 @@ struct driver_state
return !!test; return !!test;
} }
const bool test_property(GLenum property, u32 test) const inline bool test_property(GLenum property, u32 test) const
{ {
auto found = properties.find(property); auto found = properties.find(property);
if (found == properties.end()) if (found == properties.end())
@@ -255,16 +265,6 @@ struct driver_state
} }
}; };
struct vertex_upload_info
{
u32 vertex_draw_count;
u32 allocated_vertex_count;
u32 vertex_index_base;
u32 persistent_mapping_offset;
u32 volatile_mapping_offset;
std::optional<std::tuple<GLenum, u32> > index_info;
};
class GLGSRender : public GSRender class GLGSRender : public GSRender
{ {
private: private:
@@ -279,6 +279,8 @@ private:
gl::texture_cache m_gl_texture_cache; gl::texture_cache m_gl_texture_cache;
gl::buffer_view m_persistent_stream_view;
gl::buffer_view m_volatile_stream_view;
gl::texture m_gl_persistent_stream_buffer; gl::texture m_gl_persistent_stream_buffer;
gl::texture m_gl_volatile_stream_buffer; gl::texture m_gl_volatile_stream_buffer;
@@ -340,14 +342,14 @@ private:
driver_state gl_state; driver_state gl_state;
// Return element to draw and in case of indexed draw index type and offset in index buffer // Return element to draw and in case of indexed draw index type and offset in index buffer
vertex_upload_info set_vertex_buffer(); gl::vertex_upload_info set_vertex_buffer();
rsx::vertex_input_layout m_vertex_layout = {}; rsx::vertex_input_layout m_vertex_layout = {};
void clear_surface(u32 arg); void clear_surface(u32 arg);
void init_buffers(rsx::framebuffer_creation_context context, bool skip_reading = false); void init_buffers(rsx::framebuffer_creation_context context, bool skip_reading = false);
bool check_program_state(); bool check_program_state();
void load_program(const vertex_upload_info& upload_info); void load_program(const gl::vertex_upload_info& upload_info);
void update_draw_state(); void update_draw_state();
@@ -374,7 +376,6 @@ protected:
void on_exit() override; void on_exit() override;
bool do_method(u32 id, u32 arg) override; bool do_method(u32 id, u32 arg) override;
void flip(int buffer) override; void flip(int buffer) override;
u64 timestamp() const override;
void do_local_task(bool idle) override; void do_local_task(bool idle) override;
+90 -25
View File
@@ -85,8 +85,9 @@ namespace gl
bool ARB_texture_barrier_supported = false; bool ARB_texture_barrier_supported = false;
bool NV_texture_barrier_supported = false; bool NV_texture_barrier_supported = false;
bool initialized = false; bool initialized = false;
bool vendor_INTEL = false; bool vendor_INTEL = false; //has broken GLSL compiler
bool vendor_AMD = false; bool vendor_AMD = false; //has broken ARB_multidraw
bool vendor_NVIDIA = false; //has NaN poisoning issues
void initialize() void initialize()
{ {
@@ -104,35 +105,35 @@ namespace gl
if (ext_name == "GL_ARB_shader_draw_parameters") if (ext_name == "GL_ARB_shader_draw_parameters")
{ {
ARB_shader_draw_parameters_supported = true; ARB_shader_draw_parameters_supported = true;
find_count --; find_count--;
continue; continue;
} }
if (ext_name == "GL_EXT_direct_state_access") if (ext_name == "GL_EXT_direct_state_access")
{ {
EXT_dsa_supported = true; EXT_dsa_supported = true;
find_count --; find_count--;
continue; continue;
} }
if (ext_name == "GL_ARB_direct_state_access") if (ext_name == "GL_ARB_direct_state_access")
{ {
ARB_dsa_supported = true; ARB_dsa_supported = true;
find_count --; find_count--;
continue; continue;
} }
if (ext_name == "GL_ARB_buffer_storage") if (ext_name == "GL_ARB_buffer_storage")
{ {
ARB_buffer_storage_supported = true; ARB_buffer_storage_supported = true;
find_count --; find_count--;
continue; continue;
} }
if (ext_name == "GL_ARB_texture_buffer_object") if (ext_name == "GL_ARB_texture_buffer_object")
{ {
ARB_texture_buffer_supported = true; ARB_texture_buffer_supported = true;
find_count --; find_count--;
continue; continue;
} }
@@ -195,6 +196,10 @@ namespace gl
if (!EXT_dsa_supported && glGetTextureImageEXT && glTextureBufferRangeEXT) if (!EXT_dsa_supported && glGetTextureImageEXT && glTextureBufferRangeEXT)
EXT_dsa_supported = true; EXT_dsa_supported = true;
} }
else if (vendor_string.find("nvidia") != std::string::npos)
{
vendor_NVIDIA = true;
}
#ifdef _WIN32 #ifdef _WIN32
else if (vendor_string.find("amd") != std::string::npos || vendor_string.find("ati") != std::string::npos) else if (vendor_string.find("amd") != std::string::npos || vendor_string.find("ati") != std::string::npos)
{ {
@@ -864,7 +869,7 @@ namespace gl
buffer::create(); buffer::create();
glBindBuffer((GLenum)m_target, m_id); glBindBuffer((GLenum)m_target, m_id);
glBufferStorage((GLenum)m_target, size, data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_CLIENT_STORAGE_BIT | GL_MAP_COHERENT_BIT); glBufferStorage((GLenum)m_target, size, data, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
m_memory_mapping = glMapBufferRange((GLenum)m_target, 0, size, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT); m_memory_mapping = glMapBufferRange((GLenum)m_target, 0, size, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
verify(HERE), m_memory_mapping != nullptr; verify(HERE), m_memory_mapping != nullptr;
@@ -886,15 +891,19 @@ namespace gl
if ((offset + alloc_size) > m_size) if ((offset + alloc_size) > m_size)
{ {
if (!m_fence.is_empty()) if (!m_fence.is_empty())
{
m_fence.wait_for_signal(); m_fence.wait_for_signal();
}
else
{
LOG_ERROR(RSX, "OOM Error: Ring buffer was likely being used without notify() being called");
glFinish();
}
m_data_loc = 0; m_data_loc = 0;
offset = 0; offset = 0;
} }
if (!m_data_loc)
m_fence.reset();
//Align data loc to 256; allows some "guard" region so we dont trample our own data inadvertently //Align data loc to 256; allows some "guard" region so we dont trample our own data inadvertently
m_data_loc = align(offset + alloc_size, 256); m_data_loc = align(offset + alloc_size, 256);
return std::make_pair(((char*)m_memory_mapping) + offset, offset); return std::make_pair(((char*)m_memory_mapping) + offset, offset);
@@ -928,7 +937,8 @@ namespace gl
//Notification of a draw command //Notification of a draw command
virtual void notify() virtual void notify()
{ {
if (m_fence.is_empty()) //Insert fence about 25% into the buffer
if (m_fence.is_empty() && (m_data_loc > (m_size >> 2)))
m_fence.reset(); m_fence.reset();
} }
}; };
@@ -1046,6 +1056,69 @@ namespace gl
void notify() override {} void notify() override {}
}; };
class buffer_view
{
buffer* m_buffer = nullptr;
u32 m_offset = 0;
u32 m_range = 0;
GLenum m_format = GL_R8UI;
public:
buffer_view(buffer *_buffer, u32 offset, u32 range, GLenum format = GL_R8UI)
: m_buffer(_buffer), m_offset(offset), m_range(range), m_format(format)
{}
buffer_view()
{}
void update(buffer *_buffer, u32 offset, u32 range, GLenum format = GL_R8UI)
{
m_buffer = _buffer;
m_offset = offset;
m_range = range;
m_format = format;
}
u32 offset() const
{
return m_offset;
}
u32 range() const
{
return m_range;
}
u32 format() const
{
return m_format;
}
buffer* buffer() const
{
return m_buffer;
}
bool in_range(u32 address, u32 size, u32& new_offset) const
{
if (address < m_offset)
return false;
const u32 _offset = address - m_offset;
if (m_range < _offset)
return false;
const auto remaining = m_range - _offset;
if (size <= remaining)
{
new_offset = _offset;
return true;
}
return false;
}
};
class vao class vao
{ {
template<buffer::target BindId, uint GetStateId> template<buffer::target BindId, uint GetStateId>
@@ -1681,6 +1754,11 @@ namespace gl
__glcheck glTextureBufferRange(id(), gl_format_type, buf.id(), offset, length); __glcheck glTextureBufferRange(id(), gl_format_type, buf.id(), offset, length);
} }
void copy_from(buffer_view &view)
{
copy_from(*view.buffer(), view.format(), view.offset(), view.range());
}
void copy_from(const buffer& buf, texture::format format, texture::type type, class pixel_unpack_settings pixel_settings) void copy_from(const buffer& buf, texture::format format, texture::type type, class pixel_unpack_settings pixel_settings)
{ {
buffer::save_binding_state save_buffer(buffer::target::pixel_unpack, buf); buffer::save_binding_state save_buffer(buffer::target::pixel_unpack, buf);
@@ -2765,17 +2843,4 @@ namespace gl
set_id(0); set_id(0);
} }
}; };
class buffer_view : public buffer
{
public:
buffer_view(GLuint id) : buffer(id)
{
}
~buffer_view()
{
set_id(0);
}
};
} }
+5
View File
@@ -24,6 +24,11 @@ struct GLTraits
vertexProgramData.Compile(); vertexProgramData.Compile();
} }
static
void validate_pipeline_properties(const vertex_program_type&, const fragment_program_type&, pipeline_properties&)
{
}
static static
pipeline_storage_type build_pipeline(const vertex_program_type &vertexProgramData, const fragment_program_type &fragmentProgramData, const pipeline_properties&) pipeline_storage_type build_pipeline(const vertex_program_type &vertexProgramData, const fragment_program_type &fragmentProgramData, const pipeline_properties&)
{ {
+30 -1
View File
@@ -194,7 +194,7 @@ namespace gl
public: public:
void reset(u32 base, u32 size, bool flushable=false) void reset(u32 base, u32 size, bool /*flushable*/=false)
{ {
rsx::protection_policy policy = g_cfg.video.strict_rendering_mode ? rsx::protection_policy::protect_policy_full_range : rsx::protection_policy::protect_policy_conservative; rsx::protection_policy policy = g_cfg.video.strict_rendering_mode ? rsx::protection_policy::protect_policy_full_range : rsx::protection_policy::protect_policy_conservative;
rsx::buffered_section::reset(base, size, policy); rsx::buffered_section::reset(base, size, policy);
@@ -947,6 +947,35 @@ namespace gl
glTextureBarrierNV(); glTextureBarrierNV();
} }
bool render_target_format_is_compatible(gl::texture* tex, u32 gcm_format) override
{
if (auto as_rtt = dynamic_cast<gl::render_target*>(tex))
{
auto ifmt = as_rtt->get_compatible_internal_format();
switch (gcm_format)
{
default:
//TODO
LOG_TRACE(RSX, "Format incompatibility detected, reporting failure to force data copy (GL_INTERNAL_FORMAT=0x%X, GCM_FORMAT=0x%X)", (u32)ifmt, gcm_format);
return false;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return (ifmt == gl::texture::internal_format::rgba16f);
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
return (ifmt == gl::texture::internal_format::rgba32f);
case CELL_GCM_TEXTURE_X32_FLOAT:
return (ifmt == gl::texture::internal_format::r32f);
case CELL_GCM_TEXTURE_R5G6B5:
return (ifmt == gl::texture::internal_format::r5g6b5);
case CELL_GCM_TEXTURE_DEPTH24_D8:
return (ifmt == gl::texture::internal_format::depth24_stencil8 || ifmt == gl::texture::internal_format::depth32f_stencil8);
case CELL_GCM_TEXTURE_A8R8G8B8:
return (ifmt == gl::texture::internal_format::rgba8 || ifmt == gl::texture::internal_format::depth24_stencil8 || ifmt == gl::texture::internal_format::depth32f_stencil8);
}
}
fmt::throw_exception("Format comparison for non-rendertargets is not implemented" HERE);
}
public: public:
texture_cache() {} texture_cache() {}
+22 -2
View File
@@ -180,7 +180,7 @@ namespace
}; };
} }
vertex_upload_info GLGSRender::set_vertex_buffer() gl::vertex_upload_info GLGSRender::set_vertex_buffer()
{ {
std::chrono::time_point<steady_clock> then = steady_clock::now(); std::chrono::time_point<steady_clock> then = steady_clock::now();
@@ -196,7 +196,7 @@ vertex_upload_info GLGSRender::set_vertex_buffer()
auto required = calculate_memory_requirements(m_vertex_layout, vertex_count); auto required = calculate_memory_requirements(m_vertex_layout, vertex_count);
std::pair<void*, u32> persistent_mapping = {}, volatile_mapping = {}; std::pair<void*, u32> persistent_mapping = {}, volatile_mapping = {};
vertex_upload_info upload_info = { result.vertex_draw_count, result.allocated_vertex_count, result.vertex_index_base, 0u, 0u, result.index_info }; gl::vertex_upload_info upload_info = { result.vertex_draw_count, result.allocated_vertex_count, result.vertex_index_base, 0u, 0u, result.index_info };
if (required.first > 0) if (required.first > 0)
{ {
@@ -233,12 +233,32 @@ vertex_upload_info GLGSRender::set_vertex_buffer()
m_vertex_cache->store_range(storage_address, GL_R8UI, required.first, persistent_mapping.second); m_vertex_cache->store_range(storage_address, GL_R8UI, required.first, persistent_mapping.second);
} }
} }
if (!m_persistent_stream_view.in_range(upload_info.persistent_mapping_offset, required.first, upload_info.persistent_mapping_offset))
{
const size_t view_size = ((upload_info.persistent_mapping_offset + m_max_texbuffer_size) > m_attrib_ring_buffer->size()) ?
(m_attrib_ring_buffer->size() - upload_info.persistent_mapping_offset) : m_max_texbuffer_size;
m_persistent_stream_view.update(m_attrib_ring_buffer.get(), upload_info.persistent_mapping_offset, (u32)view_size);
m_gl_persistent_stream_buffer.copy_from(m_persistent_stream_view);
upload_info.persistent_mapping_offset = 0;
}
} }
if (required.second > 0) if (required.second > 0)
{ {
volatile_mapping = m_attrib_ring_buffer->alloc_from_heap(required.second, m_min_texbuffer_alignment); volatile_mapping = m_attrib_ring_buffer->alloc_from_heap(required.second, m_min_texbuffer_alignment);
upload_info.volatile_mapping_offset = volatile_mapping.second; upload_info.volatile_mapping_offset = volatile_mapping.second;
if (!m_volatile_stream_view.in_range(upload_info.volatile_mapping_offset, required.second, upload_info.volatile_mapping_offset))
{
const size_t view_size = ((upload_info.volatile_mapping_offset + m_max_texbuffer_size) > m_attrib_ring_buffer->size()) ?
(m_attrib_ring_buffer->size() - upload_info.volatile_mapping_offset) : m_max_texbuffer_size;
m_volatile_stream_view.update(m_attrib_ring_buffer.get(), upload_info.volatile_mapping_offset, (u32)view_size);
m_gl_volatile_stream_buffer.copy_from(m_volatile_stream_view);
upload_info.volatile_mapping_offset = 0;
}
} }
//Write all the data //Write all the data
+3
View File
@@ -1257,6 +1257,7 @@ namespace rsx
if (state.current_draw_clause.command == rsx::draw_command::inlined_array) if (state.current_draw_clause.command == rsx::draw_command::inlined_array)
{ {
vertex_input_layout result = {}; vertex_input_layout result = {};
result.interleaved_blocks.reserve(8);
interleaved_range_info info = {}; interleaved_range_info info = {};
info.interleaved = true; info.interleaved = true;
@@ -1281,6 +1282,8 @@ namespace rsx
const u32 frequency_divider_mask = rsx::method_registers.frequency_divider_operation_mask(); const u32 frequency_divider_mask = rsx::method_registers.frequency_divider_operation_mask();
vertex_input_layout result = {}; vertex_input_layout result = {};
result.interleaved_blocks.reserve(8);
result.referenced_registers.reserve(4);
for (u8 index = 0; index < rsx::limits::vertex_count; ++index) for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{ {
+3
View File
@@ -96,7 +96,10 @@ void VKFragmentDecompilerThread::insertOutputs(std::stringstream & OS)
for (int i = 0; i < sizeof(table) / sizeof(*table); ++i) for (int i = 0; i < sizeof(table) / sizeof(*table); ++i)
{ {
if (m_parr.HasParam(PF_PARAM_NONE, "vec4", table[i].second)) if (m_parr.HasParam(PF_PARAM_NONE, "vec4", table[i].second))
{
OS << "layout(location=" << std::to_string(output_index++) << ") " << "out vec4 " << table[i].first << ";\n"; OS << "layout(location=" << std::to_string(output_index++) << ") " << "out vec4 " << table[i].first << ";\n";
vk_prog->output_color_masks[i] = UINT32_MAX;
}
} }
} }
+2
View File
@@ -52,6 +52,8 @@ public:
std::string shader; std::string shader;
std::vector<size_t> FragmentConstantOffsetCache; std::vector<size_t> FragmentConstantOffsetCache;
std::array<u32, 4> output_color_masks{ {} };
std::vector<vk::glsl::program_input> uniforms; std::vector<vk::glsl::program_input> uniforms;
void SetInputs(std::vector<vk::glsl::program_input>& uniforms); void SetInputs(std::vector<vk::glsl::program_input>& uniforms);
/** /**
+108 -136
View File
@@ -472,8 +472,6 @@ namespace
VKGSRender::VKGSRender() : GSRender() VKGSRender::VKGSRender() : GSRender()
{ {
//shaders_cache.load(rsx::old_shaders_cache::shader_language::glsl);
u32 instance_handle = m_thread_context.createInstance("RPCS3"); u32 instance_handle = m_thread_context.createInstance("RPCS3");
if (instance_handle > 0) if (instance_handle > 0)
@@ -505,60 +503,44 @@ VKGSRender::VKGSRender() : GSRender()
display_handle_t display = m_frame->handle(); display_handle_t display = m_frame->handle();
#ifdef _WIN32 #ifndef _WIN32
display.match([this](std::pair<Display*, Window> p) { m_display_handle = p.first; XFlush(m_display_handle); }, [](auto _) {});
HINSTANCE hInstance = NULL;
for (auto &gpu : gpus)
{
if (gpu.name() == adapter_name)
{
m_swap_chain = m_thread_context.createSwapChain(hInstance, display, gpu);
gpu_found = true;
break;
}
}
if (!gpu_found || adapter_name.empty())
{
m_swap_chain = m_thread_context.createSwapChain(hInstance, display, gpus[0]);
}
#elif HAVE_VULKAN
display.match([](std::pair<Display*, Window> p) { XFlush(p.first); }, [](auto _) {});
for (auto &gpu : gpus)
{
if (gpu.name() == adapter_name)
{
m_swap_chain = m_thread_context.createSwapChain(display, gpu);
gpu_found = true;
break;
}
}
if (!gpu_found || adapter_name.empty())
{
m_swap_chain = m_thread_context.createSwapChain(display, gpus[0]);
}
display.match([&](std::pair<Display*, Window> p) { m_display_handle = p.first; }, [](auto _) {});
#endif #endif
m_device = (vk::render_device *)(&m_swap_chain->get_device()); for (auto &gpu : gpus)
{
if (gpu.name() == adapter_name)
{
m_swapchain.reset(m_thread_context.createSwapChain(display, gpu));
gpu_found = true;
break;
}
}
m_memory_type_mapping = get_memory_mapping(m_device->gpu()); if (!gpu_found || adapter_name.empty())
{
m_swapchain.reset(m_thread_context.createSwapChain(display, gpus[0]));
}
if (!m_swapchain)
{
m_device = VK_NULL_HANDLE;
LOG_FATAL(RSX, "Could not successfully initialize a swapchain");
return;
}
m_device = (vk::render_device*)(&m_swapchain->get_device());
m_memory_type_mapping = m_device->get_memory_mapping();
m_optimal_tiling_supported_formats = vk::get_optimal_tiling_supported_formats(m_device->gpu()); m_optimal_tiling_supported_formats = vk::get_optimal_tiling_supported_formats(m_device->gpu());
vk::set_current_thread_ctx(m_thread_context); vk::set_current_thread_ctx(m_thread_context);
vk::set_current_renderer(m_swap_chain->get_device()); vk::set_current_renderer(m_swapchain->get_device());
m_client_width = m_frame->client_width(); m_client_width = m_frame->client_width();
m_client_height = m_frame->client_height(); m_client_height = m_frame->client_height();
if (!m_swap_chain->init_swapchain(m_client_width, m_client_height)) if (!m_swapchain->init(m_client_width, m_client_height))
present_surface_dirty_flag = true; present_surface_dirty_flag = true;
//create command buffer... //create command buffer...
@@ -619,7 +601,7 @@ VKGSRender::VKGSRender() : GSRender()
if (g_cfg.video.overlay) if (g_cfg.video.overlay)
{ {
size_t idx = vk::get_render_pass_location( m_swap_chain->get_surface_format(), VK_FORMAT_UNDEFINED, 1); size_t idx = vk::get_render_pass_location( m_swapchain->get_surface_format(), VK_FORMAT_UNDEFINED, 1);
m_text_writer.reset(new vk::text_writer()); m_text_writer.reset(new vk::text_writer());
m_text_writer->init(*m_device, m_memory_type_mapping, m_render_passes[idx]); m_text_writer->init(*m_device, m_memory_type_mapping, m_render_passes[idx]);
} }
@@ -641,25 +623,22 @@ VKGSRender::VKGSRender() : GSRender()
open_command_buffer(); open_command_buffer();
for (u32 i = 0; i < m_swap_chain->get_swap_image_count(); ++i) for (u32 i = 0; i < m_swapchain->get_swap_image_count(); ++i)
{ {
const auto target_layout = m_swapchain->get_optimal_present_layout();
const auto target_image = m_swapchain->get_image(i);
VkClearColorValue clear_color{}; VkClearColorValue clear_color{};
VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i), vk::change_image_layout(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, range);
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, vkCmdClearColorImage(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range);
range); vk::change_image_layout(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_GENERAL, target_layout, range);
vkCmdClearColorImage(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range);
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i),
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
range);
} }
m_current_frame = &frame_context_storage[0]; m_current_frame = &frame_context_storage[0];
m_texture_cache.initialize((*m_device), m_memory_type_mapping, m_optimal_tiling_supported_formats, m_swap_chain->get_present_queue(), m_texture_cache.initialize((*m_device), m_memory_type_mapping, m_optimal_tiling_supported_formats, m_swapchain->get_graphics_queue(),
m_texture_upload_buffer_ring_info); m_texture_upload_buffer_ring_info);
m_ui_renderer.reset(new vk::ui_overlay_renderer()); m_ui_renderer.reset(new vk::ui_overlay_renderer());
@@ -687,6 +666,9 @@ VKGSRender::~VKGSRender()
vk::finalize_compiler_context(); vk::finalize_compiler_context();
m_prog_buffer->clear(); m_prog_buffer->clear();
m_persistent_attribute_storage.reset();
m_volatile_attribute_storage.reset();
//Global resources //Global resources
vk::destroy_global_resources(); vk::destroy_global_resources();
@@ -774,10 +756,8 @@ VKGSRender::~VKGSRender()
m_secondary_command_buffer_pool.destroy(); m_secondary_command_buffer_pool.destroy();
//Device handles/contexts //Device handles/contexts
m_swap_chain->destroy(); m_swapchain->destroy();
m_thread_context.close(); m_thread_context.close();
delete m_swap_chain;
#if !defined(_WIN32) && defined(HAVE_VULKAN) #if !defined(_WIN32) && defined(HAVE_VULKAN)
if (m_display_handle) if (m_display_handle)
@@ -790,7 +770,7 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing)
vk::texture_cache::thrashed_set result; vk::texture_cache::thrashed_set result;
{ {
std::lock_guard<std::mutex> lock(m_secondary_cb_guard); std::lock_guard<std::mutex> lock(m_secondary_cb_guard);
result = std::move(m_texture_cache.invalidate_address(address, is_writing, false, m_secondary_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue())); result = std::move(m_texture_cache.invalidate_address(address, is_writing, false, m_secondary_command_buffer, m_memory_type_mapping, m_swapchain->get_graphics_queue()));
} }
if (!result.violation_handled) if (!result.violation_handled)
@@ -852,7 +832,7 @@ bool VKGSRender::on_access_violation(u32 address, bool is_writing)
m_flush_requests.producer_wait(); m_flush_requests.producer_wait();
} }
m_texture_cache.flush_all(result, m_secondary_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue()); m_texture_cache.flush_all(result, m_secondary_command_buffer, m_memory_type_mapping, m_swapchain->get_graphics_queue());
if (has_queue_ref) if (has_queue_ref)
{ {
@@ -868,7 +848,7 @@ void VKGSRender::on_notify_memory_unmapped(u32 address_base, u32 size)
{ {
std::lock_guard<std::mutex> lock(m_secondary_cb_guard); std::lock_guard<std::mutex> lock(m_secondary_cb_guard);
if (m_texture_cache.invalidate_range(address_base, size, true, true, false, if (m_texture_cache.invalidate_range(address_base, size, true, true, false,
m_secondary_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue()).violation_handled) m_secondary_command_buffer, m_memory_type_mapping, m_swapchain->get_graphics_queue()).violation_handled)
{ {
m_texture_cache.purge_dirty(); m_texture_cache.purge_dirty();
{ {
@@ -1149,22 +1129,8 @@ void VKGSRender::end()
if (replace) if (replace)
{ {
for (auto &sampler : m_current_frame->samplers_to_clean) fs_sampler_handles[i] = std::make_unique<vk::sampler>(*m_device, wrap_s, wrap_t, wrap_r, false, lod_bias, af_level, min_lod, max_lod,
{ min_filter, mag_filter, mip_mode, border_color, compare_enabled, depth_compare_mode);
if (sampler->matches(wrap_s, wrap_t, wrap_r, false, lod_bias, af_level, min_lod, max_lod,
min_filter, mag_filter, mip_mode, border_color, compare_enabled, depth_compare_mode))
{
fs_sampler_handles[i] = std::move(sampler);
replace = false;
break;
}
}
if (replace)
{
fs_sampler_handles[i] = std::make_unique<vk::sampler>(*m_device, wrap_s, wrap_t, wrap_r, false, lod_bias, af_level, min_lod, max_lod,
min_filter, mag_filter, mip_mode, border_color, compare_enabled, depth_compare_mode);
}
} }
} }
else else
@@ -1208,7 +1174,6 @@ void VKGSRender::end()
if (replace) if (replace)
{ {
//This is unlikely, there is no need to check the dirty pool
vs_sampler_handles[i] = std::make_unique<vk::sampler>( vs_sampler_handles[i] = std::make_unique<vk::sampler>(
*m_device, *m_device,
VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT,
@@ -1232,10 +1197,12 @@ void VKGSRender::end()
//Load program //Load program
std::chrono::time_point<steady_clock> program_start = textures_end; std::chrono::time_point<steady_clock> program_start = textures_end;
load_program(std::get<2>(upload_info), std::get<3>(upload_info)); load_program(upload_info);
m_program->bind_uniform(m_persistent_attribute_storage, "persistent_input_stream", m_current_frame->descriptor_set); VkBufferView persistent_buffer = m_persistent_attribute_storage ? m_persistent_attribute_storage->value : null_buffer_view->value;
m_program->bind_uniform(m_volatile_attribute_storage, "volatile_input_stream", m_current_frame->descriptor_set); VkBufferView volatile_buffer = m_volatile_attribute_storage ? m_volatile_attribute_storage->value : null_buffer_view->value;
m_program->bind_uniform(persistent_buffer, "persistent_input_stream", m_current_frame->descriptor_set);
m_program->bind_uniform(volatile_buffer, "volatile_input_stream", m_current_frame->descriptor_set);
std::chrono::time_point<steady_clock> program_stop = steady_clock::now(); std::chrono::time_point<steady_clock> program_stop = steady_clock::now();
m_setup_time += std::chrono::duration_cast<std::chrono::microseconds>(program_stop - program_start).count(); m_setup_time += std::chrono::duration_cast<std::chrono::microseconds>(program_stop - program_start).count();
@@ -1468,8 +1435,6 @@ void VKGSRender::end()
vkCmdClearAttachments(*m_current_command_buffer, static_cast<u32>(buffers_to_clear.size()), buffers_to_clear.data(), 1, &clear_rect); vkCmdClearAttachments(*m_current_command_buffer, static_cast<u32>(buffers_to_clear.size()), buffers_to_clear.data(), 1, &clear_rect);
} }
std::optional<std::tuple<VkDeviceSize, VkIndexType> > index_info = std::get<4>(upload_info);
bool primitive_emulated = false; bool primitive_emulated = false;
vk::get_appropriate_topology(rsx::method_registers.current_draw_clause.primitive, primitive_emulated); vk::get_appropriate_topology(rsx::method_registers.current_draw_clause.primitive, primitive_emulated);
@@ -1484,12 +1449,11 @@ void VKGSRender::end()
m_occlusion_map[m_active_query_info->driver_handle].command_buffer_to_wait = m_current_command_buffer; m_occlusion_map[m_active_query_info->driver_handle].command_buffer_to_wait = m_current_command_buffer;
} }
if (!index_info) if (!upload_info.index_info)
{ {
if (single_draw) if (single_draw)
{ {
const auto vertex_count = std::get<1>(upload_info); vkCmdDraw(*m_current_command_buffer, upload_info.vertex_draw_count, 1, 0, 0);
vkCmdDraw(*m_current_command_buffer, vertex_count, 1, 0, 0);
} }
else else
{ {
@@ -1503,10 +1467,10 @@ void VKGSRender::end()
else else
{ {
VkIndexType index_type; VkIndexType index_type;
u32 index_count = std::get<1>(upload_info); const u32 index_count = upload_info.vertex_draw_count;
VkDeviceSize offset; VkDeviceSize offset;
std::tie(offset, index_type) = index_info.value(); std::tie(offset, index_type) = upload_info.index_info.value();
vkCmdBindIndexBuffer(*m_current_command_buffer, m_index_buffer_ring_info.heap->value, offset, index_type); vkCmdBindIndexBuffer(*m_current_command_buffer, m_index_buffer_ring_info.heap->value, offset, index_type);
if (single_draw) if (single_draw)
@@ -1809,7 +1773,7 @@ void VKGSRender::copy_render_targets_to_dma_location()
continue; continue;
m_texture_cache.flush_memory_to_cache(m_surface_info[index].address, m_surface_info[index].pitch * m_surface_info[index].height, true, m_texture_cache.flush_memory_to_cache(m_surface_info[index].address, m_surface_info[index].pitch * m_surface_info[index].height, true,
*m_current_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue()); *m_current_command_buffer, m_memory_type_mapping, m_swapchain->get_graphics_queue());
} }
} }
@@ -1818,7 +1782,7 @@ void VKGSRender::copy_render_targets_to_dma_location()
if (m_depth_surface_info.pitch) if (m_depth_surface_info.pitch)
{ {
m_texture_cache.flush_memory_to_cache(m_depth_surface_info.address, m_depth_surface_info.pitch * m_depth_surface_info.height, true, m_texture_cache.flush_memory_to_cache(m_depth_surface_info.address, m_depth_surface_info.pitch * m_depth_surface_info.height, true,
*m_current_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue()); *m_current_command_buffer, m_memory_type_mapping, m_swapchain->get_graphics_queue());
} }
} }
@@ -1927,18 +1891,10 @@ void VKGSRender::advance_queued_frames()
void VKGSRender::present(frame_context_t *ctx) void VKGSRender::present(frame_context_t *ctx)
{ {
verify(HERE), ctx->present_image != UINT32_MAX; verify(HERE), ctx->present_image != UINT32_MAX;
VkSwapchainKHR swap_chain = (VkSwapchainKHR)(*m_swap_chain);
if (!present_surface_dirty_flag) if (!present_surface_dirty_flag)
{ {
VkPresentInfoKHR present = {}; switch (VkResult error = m_swapchain->present(ctx->present_image))
present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
present.pNext = nullptr;
present.swapchainCount = 1;
present.pSwapchains = &swap_chain;
present.pImageIndices = &ctx->present_image;
switch (VkResult error = m_swap_chain->queuePresentKHR(m_swap_chain->get_present_queue(), &present))
{ {
case VK_SUCCESS: case VK_SUCCESS:
case VK_SUBOPTIMAL_KHR: case VK_SUBOPTIMAL_KHR:
@@ -1968,7 +1924,17 @@ void VKGSRender::queue_swap_request()
} }
m_current_frame->swap_command_buffer = m_current_command_buffer; m_current_frame->swap_command_buffer = m_current_command_buffer;
close_and_submit_command_buffer({ m_current_frame->present_semaphore }, m_current_command_buffer->submit_fence);
if (m_swapchain->is_headless())
{
m_swapchain->end_frame(*m_current_command_buffer, m_current_frame->present_image);
close_and_submit_command_buffer({}, m_current_command_buffer->submit_fence);
}
else
{
close_and_submit_command_buffer({ m_current_frame->present_semaphore }, m_current_command_buffer->submit_fence);
}
m_current_frame->swap_command_buffer->pending = true; m_current_frame->swap_command_buffer->pending = true;
//Grab next cb in line and make it usable //Grab next cb in line and make it usable
@@ -2181,7 +2147,7 @@ bool VKGSRender::check_program_status()
return (rsx::method_registers.shader_program_address() != 0); return (rsx::method_registers.shader_program_address() != 0);
} }
void VKGSRender::load_program(u32 vertex_count, u32 vertex_base) void VKGSRender::load_program(const vk::vertex_upload_info& vertex_info)
{ {
get_current_fragment_program(fs_sampler_state); get_current_fragment_program(fs_sampler_state);
verify(HERE), current_fragment_program.valid; verify(HERE), current_fragment_program.valid;
@@ -2364,11 +2330,13 @@ void VKGSRender::load_program(u32 vertex_count, u32 vertex_base)
fill_scale_offset_data(buf, false); fill_scale_offset_data(buf, false);
fill_user_clip_data(buf + 64); fill_user_clip_data(buf + 64);
*(reinterpret_cast<u32*>(buf + 128)) = rsx::method_registers.transform_branch_bits(); *(reinterpret_cast<u32*>(buf + 128)) = rsx::method_registers.transform_branch_bits();
*(reinterpret_cast<u32*>(buf + 132)) = vertex_base; *(reinterpret_cast<u32*>(buf + 132)) = vertex_info.vertex_index_base;
*(reinterpret_cast<f32*>(buf + 136)) = rsx::method_registers.point_size(); *(reinterpret_cast<f32*>(buf + 136)) = rsx::method_registers.point_size();
*(reinterpret_cast<f32*>(buf + 140)) = rsx::method_registers.clip_min(); *(reinterpret_cast<f32*>(buf + 140)) = rsx::method_registers.clip_min();
*(reinterpret_cast<f32*>(buf + 144)) = rsx::method_registers.clip_max(); *(reinterpret_cast<f32*>(buf + 144)) = rsx::method_registers.clip_max();
fill_vertex_layout_state(m_vertex_layout, vertex_count, reinterpret_cast<s32*>(buf + 160));
fill_vertex_layout_state(m_vertex_layout, vertex_info.allocated_vertex_count, reinterpret_cast<s32*>(buf + 160),
vertex_info.persistent_window_offset, vertex_info.volatile_window_offset);
//Vertex constants //Vertex constants
buf = buf + 512; buf = buf + 512;
@@ -2378,7 +2346,10 @@ void VKGSRender::load_program(u32 vertex_count, u32 vertex_base)
//Fragment constants //Fragment constants
buf = buf + 8192; buf = buf + 8192;
if (fragment_constants_sz) if (fragment_constants_sz)
m_prog_buffer->fill_fragment_constants_buffer({ reinterpret_cast<float*>(buf), ::narrow<int>(fragment_constants_sz) }, fragment_program); {
m_prog_buffer->fill_fragment_constants_buffer({ reinterpret_cast<float*>(buf), ::narrow<int>(fragment_constants_sz) },
fragment_program, vk::sanitize_fp_values());
}
fill_fragment_state_buffer(buf + fragment_constants_sz, fragment_program); fill_fragment_state_buffer(buf + fragment_constants_sz, fragment_program);
@@ -2462,7 +2433,7 @@ void VKGSRender::close_and_submit_command_buffer(const std::vector<VkSemaphore>
{ {
m_current_command_buffer->end(); m_current_command_buffer->end();
m_current_command_buffer->tag(); m_current_command_buffer->tag();
m_current_command_buffer->submit(m_swap_chain->get_present_queue(), semaphores, fence, pipeline_stage_flags); m_current_command_buffer->submit(m_swapchain->get_graphics_queue(), semaphores, fence, pipeline_stage_flags);
} }
void VKGSRender::open_command_buffer() void VKGSRender::open_command_buffer()
@@ -2654,7 +2625,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
m_texture_cache.set_memory_read_flags(m_surface_info[i].address, m_surface_info[i].pitch * m_surface_info[i].height, rsx::memory_read_flags::flush_once); m_texture_cache.set_memory_read_flags(m_surface_info[i].address, m_surface_info[i].pitch * m_surface_info[i].height, rsx::memory_read_flags::flush_once);
m_texture_cache.flush_if_cache_miss_likely(old_format, m_surface_info[i].address, m_surface_info[i].pitch * m_surface_info[i].height, m_texture_cache.flush_if_cache_miss_likely(old_format, m_surface_info[i].address, m_surface_info[i].pitch * m_surface_info[i].height,
*m_current_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue()); *m_current_command_buffer, m_memory_type_mapping, m_swapchain->get_graphics_queue());
} }
m_surface_info[i].address = m_surface_info[i].pitch = 0; m_surface_info[i].address = m_surface_info[i].pitch = 0;
@@ -2670,7 +2641,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
auto old_format = vk::get_compatible_depth_surface_format(m_optimal_tiling_supported_formats, m_depth_surface_info.depth_format); auto old_format = vk::get_compatible_depth_surface_format(m_optimal_tiling_supported_formats, m_depth_surface_info.depth_format);
m_texture_cache.set_memory_read_flags(m_depth_surface_info.address, m_depth_surface_info.pitch * m_depth_surface_info.height, rsx::memory_read_flags::flush_once); m_texture_cache.set_memory_read_flags(m_depth_surface_info.address, m_depth_surface_info.pitch * m_depth_surface_info.height, rsx::memory_read_flags::flush_once);
m_texture_cache.flush_if_cache_miss_likely(old_format, m_depth_surface_info.address, m_depth_surface_info.pitch * m_depth_surface_info.height, m_texture_cache.flush_if_cache_miss_likely(old_format, m_depth_surface_info.address, m_depth_surface_info.pitch * m_depth_surface_info.height,
*m_current_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue()); *m_current_command_buffer, m_memory_type_mapping, m_swapchain->get_graphics_queue());
} }
m_depth_surface_info.address = m_depth_surface_info.pitch = 0; m_depth_surface_info.address = m_depth_surface_info.pitch = 0;
@@ -2847,14 +2818,14 @@ void VKGSRender::reinitialize_swapchain()
present(&ctx); present(&ctx);
} }
vkQueueWaitIdle(m_swap_chain->get_present_queue()); //Wait for completion
vkDeviceWaitIdle(*m_device); vkDeviceWaitIdle(*m_device);
//Remove any old refs to the old images as they are about to be destroyed //Remove any old refs to the old images as they are about to be destroyed
m_framebuffers_to_clean.clear(); m_framebuffers_to_clean.clear();
//Rebuild swapchain. Old swapchain destruction is handled by the init_swapchain call //Rebuild swapchain. Old swapchain destruction is handled by the init_swapchain call
if (!m_swap_chain->init_swapchain(new_width, new_height)) if (!m_swapchain->init(new_width, new_height))
{ {
LOG_WARNING(RSX, "Swapchain initialization failed. Request ignored [%dx%d]", new_width, new_height); LOG_WARNING(RSX, "Swapchain initialization failed. Request ignored [%dx%d]", new_width, new_height);
present_surface_dirty_flag = true; present_surface_dirty_flag = true;
@@ -2869,18 +2840,16 @@ void VKGSRender::reinitialize_swapchain()
//Prepare new swapchain images for use //Prepare new swapchain images for use
open_command_buffer(); open_command_buffer();
for (u32 i = 0; i < m_swap_chain->get_swap_image_count(); ++i) for (u32 i = 0; i < m_swapchain->get_swap_image_count(); ++i)
{ {
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i), const auto target_layout = m_swapchain->get_optimal_present_layout();
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, const auto target_image = m_swapchain->get_image(i);
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 });
VkClearColorValue clear_color{}; VkClearColorValue clear_color{};
auto range = vk::get_image_subresource_range(0, 0, 1, 1, VK_IMAGE_ASPECT_COLOR_BIT); VkImageSubresourceRange range = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1};
vkCmdClearColorImage(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i), VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range);
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(i), vk::change_image_layout(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, range);
VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, vkCmdClearColorImage(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_GENERAL, &clear_color, 1, &range);
{ VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }); vk::change_image_layout(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_GENERAL, target_layout, range);
} }
//Will have to block until rendering is completed //Will have to block until rendering is completed
@@ -2989,8 +2958,9 @@ void VKGSRender::flip(int buffer)
//Prepare surface for new frame. Set no timeout here so that we wait for the next image if need be //Prepare surface for new frame. Set no timeout here so that we wait for the next image if need be
verify(HERE), m_current_frame->present_image == UINT32_MAX; verify(HERE), m_current_frame->present_image == UINT32_MAX;
u64 timeout = m_swap_chain->get_swap_image_count() <= VK_MAX_ASYNC_FRAMES? 0ull: 100000000ull;
while (VkResult status = vkAcquireNextImageKHR((*m_device), (*m_swap_chain), timeout, m_current_frame->present_semaphore, VK_NULL_HANDLE, &m_current_frame->present_image)) u64 timeout = m_swapchain->get_swap_image_count() <= VK_MAX_ASYNC_FRAMES? 0ull: 100000000ull;
while (VkResult status = m_swapchain->acquire_next_swapchain_image(m_current_frame->present_semaphore, timeout, &m_current_frame->present_image))
{ {
switch (status) switch (status)
{ {
@@ -3053,16 +3023,18 @@ void VKGSRender::flip(int buffer)
} }
} }
VkImage target_image = m_swap_chain->get_swap_chain_image(m_current_frame->present_image); VkImage target_image = m_swapchain->get_image(m_current_frame->present_image);
const auto present_layout = m_swapchain->get_optimal_present_layout();
if (image_to_flip) if (image_to_flip)
{ {
VkImageLayout target_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; VkImageLayout target_layout = present_layout;
VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
if (aspect_ratio.x || aspect_ratio.y) if (aspect_ratio.x || aspect_ratio.y)
{ {
VkClearColorValue clear_black {}; VkClearColorValue clear_black {};
vk::change_image_layout(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, range); vk::change_image_layout(*m_current_command_buffer, target_image, present_layout, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, range);
vkCmdClearColorImage(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_black, 1, &range); vkCmdClearColorImage(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_black, 1, &range);
target_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; target_layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
@@ -3071,9 +3043,9 @@ void VKGSRender::flip(int buffer)
vk::copy_scaled_image(*m_current_command_buffer, image_to_flip->value, target_image, image_to_flip->current_layout, target_layout, vk::copy_scaled_image(*m_current_command_buffer, image_to_flip->value, target_image, image_to_flip->current_layout, target_layout,
0, 0, image_to_flip->width(), image_to_flip->height(), aspect_ratio.x, aspect_ratio.y, aspect_ratio.width, aspect_ratio.height, 1, VK_IMAGE_ASPECT_COLOR_BIT, false); 0, 0, image_to_flip->width(), image_to_flip->height(), aspect_ratio.x, aspect_ratio.y, aspect_ratio.width, aspect_ratio.height, 1, VK_IMAGE_ASPECT_COLOR_BIT, false);
if (target_layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR) if (target_layout != present_layout)
{ {
vk::change_image_layout(*m_current_command_buffer, target_image, target_layout, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, range); vk::change_image_layout(*m_current_command_buffer, target_image, target_layout, present_layout, range);
} }
} }
else else
@@ -3082,9 +3054,9 @@ void VKGSRender::flip(int buffer)
//TODO: Upload raw bytes from cpu for rendering //TODO: Upload raw bytes from cpu for rendering
VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 }; VkImageSubresourceRange range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
VkClearColorValue clear_black {}; VkClearColorValue clear_black {};
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(m_current_frame->present_image), VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_IMAGE_LAYOUT_GENERAL, range); vk::change_image_layout(*m_current_command_buffer, m_swapchain->get_image(m_current_frame->present_image), present_layout, VK_IMAGE_LAYOUT_GENERAL, range);
vkCmdClearColorImage(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(m_current_frame->present_image), VK_IMAGE_LAYOUT_GENERAL, &clear_black, 1, &range); vkCmdClearColorImage(*m_current_command_buffer, m_swapchain->get_image(m_current_frame->present_image), VK_IMAGE_LAYOUT_GENERAL, &clear_black, 1, &range);
vk::change_image_layout(*m_current_command_buffer, m_swap_chain->get_swap_chain_image(m_current_frame->present_image), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, range); vk::change_image_layout(*m_current_command_buffer, m_swapchain->get_image(m_current_frame->present_image), VK_IMAGE_LAYOUT_GENERAL, present_layout, range);
} }
std::unique_ptr<vk::framebuffer_holder> direct_fbo; std::unique_ptr<vk::framebuffer_holder> direct_fbo;
@@ -3096,7 +3068,7 @@ void VKGSRender::flip(int buffer)
VkImageMemoryBarrier barrier = {}; VkImageMemoryBarrier barrier = {};
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; barrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
barrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; barrier.oldLayout = present_layout;
barrier.image = target_image; barrier.image = target_image;
barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; barrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
@@ -3106,7 +3078,7 @@ void VKGSRender::flip(int buffer)
vkCmdPipelineBarrier(*m_current_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier); vkCmdPipelineBarrier(*m_current_command_buffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
size_t idx = vk::get_render_pass_location(m_swap_chain->get_surface_format(), VK_FORMAT_UNDEFINED, 1); size_t idx = vk::get_render_pass_location(m_swapchain->get_surface_format(), VK_FORMAT_UNDEFINED, 1);
VkRenderPass single_target_pass = m_render_passes[idx]; VkRenderPass single_target_pass = m_render_passes[idx];
for (auto It = m_framebuffers_to_clean.begin(); It != m_framebuffers_to_clean.end(); It++) for (auto It = m_framebuffers_to_clean.begin(); It != m_framebuffers_to_clean.end(); It++)
@@ -3123,7 +3095,7 @@ void VKGSRender::flip(int buffer)
if (!direct_fbo) if (!direct_fbo)
{ {
swap_image_view.push_back(std::make_unique<vk::image_view>(*m_device, target_image, VK_IMAGE_VIEW_TYPE_2D, m_swap_chain->get_surface_format(), vk::default_component_map(), subres)); swap_image_view.push_back(std::make_unique<vk::image_view>(*m_device, target_image, VK_IMAGE_VIEW_TYPE_2D, m_swapchain->get_surface_format(), vk::default_component_map(), subres));
direct_fbo.reset(new vk::framebuffer_holder(*m_device, single_target_pass, m_client_width, m_client_height, std::move(swap_image_view))); direct_fbo.reset(new vk::framebuffer_holder(*m_device, single_target_pass, m_client_width, m_client_height, std::move(swap_image_view)));
} }
@@ -3152,7 +3124,7 @@ void VKGSRender::flip(int buffer)
m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 180, direct_fbo->width(), direct_fbo->height(), "Flush requests: " + std::to_string(num_flushes) + " (" + std::to_string(cache_miss_ratio) + "% hard faults)"); m_text_writer->print_text(*m_current_command_buffer, *direct_fbo, 0, 180, direct_fbo->width(), direct_fbo->height(), "Flush requests: " + std::to_string(num_flushes) + " (" + std::to_string(cache_miss_ratio) + "% hard faults)");
} }
vk::change_image_layout(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, subres); vk::change_image_layout(*m_current_command_buffer, target_image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, present_layout, subres);
m_framebuffers_to_clean.push_back(std::move(direct_fbo)); m_framebuffers_to_clean.push_back(std::move(direct_fbo));
} }
@@ -3217,7 +3189,7 @@ bool VKGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst
if (result.dst_image) if (result.dst_image)
{ {
if (m_texture_cache.flush_if_cache_miss_likely(result.dst_image->info.format, result.real_dst_address, result.real_dst_size, if (m_texture_cache.flush_if_cache_miss_likely(result.dst_image->info.format, result.real_dst_address, result.real_dst_size,
*m_current_command_buffer, m_memory_type_mapping, m_swap_chain->get_present_queue())) *m_current_command_buffer, m_memory_type_mapping, m_swapchain->get_graphics_queue()))
require_flush = true; require_flush = true;
} }
+19 -9
View File
@@ -23,13 +23,24 @@ namespace vk
using null_vertex_cache = vertex_cache; using null_vertex_cache = vertex_cache;
using shader_cache = rsx::shaders_cache<vk::pipeline_props, VKProgramBuffer>; using shader_cache = rsx::shaders_cache<vk::pipeline_props, VKProgramBuffer>;
struct vertex_upload_info
{
VkPrimitiveTopology primitive;
u32 vertex_draw_count;
u32 allocated_vertex_count;
u32 vertex_index_base;
u32 persistent_window_offset;
u32 volatile_window_offset;
std::optional<std::tuple<VkDeviceSize, VkIndexType>> index_info;
};
} }
//Heap allocation sizes in MB //Heap allocation sizes in MB
//NOTE: Texture uploads can be huge, upto 16MB for a single texture (4096x4096px) //NOTE: Texture uploads can be huge, upto 16MB for a single texture (4096x4096px)
#define VK_ATTRIB_RING_BUFFER_SIZE_M 256 #define VK_ATTRIB_RING_BUFFER_SIZE_M 256
#define VK_TEXTURE_UPLOAD_RING_BUFFER_SIZE_M 256 #define VK_TEXTURE_UPLOAD_RING_BUFFER_SIZE_M 256
#define VK_UBO_RING_BUFFER_SIZE_M 64 #define VK_UBO_RING_BUFFER_SIZE_M 128
#define VK_INDEX_RING_BUFFER_SIZE_M 64 #define VK_INDEX_RING_BUFFER_SIZE_M 64
#define VK_MAX_ASYNC_CB_COUNT 64 #define VK_MAX_ASYNC_CB_COUNT 64
@@ -238,9 +249,7 @@ class VKGSRender : public GSRender
private: private:
VKFragmentProgram m_fragment_prog; VKFragmentProgram m_fragment_prog;
VKVertexProgram m_vertex_prog; VKVertexProgram m_vertex_prog;
vk::glsl::program *m_program; vk::glsl::program *m_program;
vk::context m_thread_context;
vk::texture_cache m_texture_cache; vk::texture_cache m_texture_cache;
rsx::vk_render_targets m_rtts; rsx::vk_render_targets m_rtts;
@@ -264,8 +273,8 @@ private:
std::array<std::unique_ptr<vk::sampler>, rsx::limits::fragment_textures_count> fs_sampler_handles; 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; std::array<std::unique_ptr<vk::sampler>, rsx::limits::vertex_textures_count> vs_sampler_handles;
VkBufferView m_persistent_attribute_storage; std::unique_ptr<vk::buffer_view> m_persistent_attribute_storage;
VkBufferView m_volatile_attribute_storage; std::unique_ptr<vk::buffer_view> m_volatile_attribute_storage;
public: public:
//vk::fbo draw_fbo; //vk::fbo draw_fbo;
@@ -275,8 +284,9 @@ public:
private: private:
std::unique_ptr<VKProgramBuffer> m_prog_buffer; std::unique_ptr<VKProgramBuffer> m_prog_buffer;
std::unique_ptr<vk::swapchain_base> m_swapchain;
vk::context m_thread_context;
vk::render_device *m_device; vk::render_device *m_device;
vk::swap_chain* m_swap_chain;
//Vulkan internals //Vulkan internals
vk::command_pool m_command_buffer_pool; vk::command_pool m_command_buffer_pool;
@@ -380,11 +390,11 @@ private:
void check_heap_status(); void check_heap_status();
/// returns primitive topology, index_count, allocated_verts, vertex_base_index, (offset in index buffer, index type) vk::vertex_upload_info upload_vertex_data();
std::tuple<VkPrimitiveTopology, u32, u32, u32, std::optional<std::tuple<VkDeviceSize, VkIndexType> > > upload_vertex_data();
public: public:
bool check_program_status(); bool check_program_status();
void load_program(u32 vertex_count, u32 vertex_base); void load_program(const vk::vertex_upload_info& vertex_info);
void init_buffers(rsx::framebuffer_creation_context context, bool skip_reading = false); void init_buffers(rsx::framebuffer_creation_context context, bool skip_reading = false);
void read_buffers(); void read_buffers();
void write_buffers(); void write_buffers();
+18 -4
View File
@@ -14,8 +14,11 @@ namespace vk
VkSampler g_null_sampler = nullptr; VkSampler g_null_sampler = nullptr;
atomic_t<bool> g_cb_no_interrupt_flag { false }; atomic_t<bool> g_cb_no_interrupt_flag { false };
atomic_t<bool> g_drv_no_primitive_restart_flag { false };
atomic_t<bool> g_drv_force_32bit_indices{ false }; //Driver compatibility workarounds
bool g_drv_no_primitive_restart_flag = false;
bool g_drv_force_32bit_indices = false;
bool g_drv_sanitize_fp_values = false;
u64 g_num_processed_frames = 0; u64 g_num_processed_frames = 0;
u64 g_num_total_frames = 0; u64 g_num_total_frames = 0;
@@ -56,10 +59,10 @@ namespace vk
#endif #endif
} }
memory_type_mapping get_memory_mapping(VkPhysicalDevice pdev) memory_type_mapping get_memory_mapping(const vk::physical_device& dev)
{ {
VkPhysicalDeviceMemoryProperties memory_properties; VkPhysicalDeviceMemoryProperties memory_properties;
vkGetPhysicalDeviceMemoryProperties(pdev, &memory_properties); vkGetPhysicalDeviceMemoryProperties((VkPhysicalDevice&)dev, &memory_properties);
memory_type_mapping result; memory_type_mapping result;
result.device_local = VK_MAX_MEMORY_TYPES; result.device_local = VK_MAX_MEMORY_TYPES;
@@ -312,6 +315,12 @@ namespace vk
g_drv_force_32bit_indices = true; g_drv_force_32bit_indices = true;
} }
#endif #endif
//Nvidia cards are easily susceptible to NaN poisoning
if (gpu_name.find("NVIDIA") != std::string::npos || gpu_name.find("GeForce") != std::string::npos)
{
g_drv_sanitize_fp_values = true;
}
} }
bool emulate_primitive_restart() bool emulate_primitive_restart()
@@ -324,6 +333,11 @@ namespace vk
return g_drv_force_32bit_indices; return g_drv_force_32bit_indices;
} }
bool sanitize_fp_values()
{
return g_drv_sanitize_fp_values;
}
void change_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range) void change_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range)
{ {
//Prepare an image to match the new layout.. //Prepare an image to match the new layout..
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -630,7 +630,7 @@ namespace vk
return upload_simple_texture(cmd.get_command_pool().get_owner(), cmd, memory_types, upload_heap, key, desc->w, desc->h, false, true, desc->data); return upload_simple_texture(cmd.get_command_pool().get_owner(), cmd, memory_types, upload_heap, key, desc->w, desc->h, false, true, desc->data);
} }
void update_uniforms(vk::glsl::program *program) override void update_uniforms(vk::glsl::program* /*program*/) override
{ {
auto dst = (f32*)m_ubo->map(first_vertex * 128, 128); auto dst = (f32*)m_ubo->map(first_vertex * 128, 128);
dst[0] = m_scale_offset.r; dst[0] = m_scale_offset.r;
+10
View File
@@ -95,6 +95,16 @@ struct VKTraits
vertexProgramData.Compile(); vertexProgramData.Compile();
} }
static
void validate_pipeline_properties(const VKVertexProgram&, const VKFragmentProgram &fp, vk::pipeline_props& properties)
{
//Explicitly disable writing to undefined registers
properties.att_state[0].colorWriteMask &= fp.output_color_masks[0];
properties.att_state[1].colorWriteMask &= fp.output_color_masks[1];
properties.att_state[2].colorWriteMask &= fp.output_color_masks[2];
properties.att_state[3].colorWriteMask &= fp.output_color_masks[3];
}
static static
pipeline_storage_type build_pipeline(const vertex_program_type &vertexProgramData, const fragment_program_type &fragmentProgramData, pipeline_storage_type build_pipeline(const vertex_program_type &vertexProgramData, const fragment_program_type &fragmentProgramData,
const vk::pipeline_props &pipelineProperties, VkDevice dev, VkPipelineLayout common_pipeline_layout) const vk::pipeline_props &pipelineProperties, VkDevice dev, VkPipelineLayout common_pipeline_layout)
+24
View File
@@ -901,6 +901,30 @@ namespace vk
vk::insert_texture_barrier(cmd, tex); vk::insert_texture_barrier(cmd, tex);
} }
bool render_target_format_is_compatible(vk::image* tex, u32 gcm_format) override
{
auto vk_format = tex->info.format;
switch (gcm_format)
{
default:
//TODO
LOG_TRACE(RSX, "Format incompatibility detected, reporting failure to force data copy (VK_FORMAT=0x%X, GCM_FORMAT=0x%X)", (u32)vk_format, gcm_format);
return false;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return (vk_format == VK_FORMAT_R16G16B16A16_SFLOAT);
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
return (vk_format == VK_FORMAT_R32G32B32A32_SFLOAT);
case CELL_GCM_TEXTURE_X32_FLOAT:
return (vk_format == VK_FORMAT_R32_SFLOAT);
case CELL_GCM_TEXTURE_R5G6B5:
return (vk_format == VK_FORMAT_R5G6B5_UNORM_PACK16);
case CELL_GCM_TEXTURE_DEPTH24_D8:
return (vk_format == VK_FORMAT_D24_UNORM_S8_UINT || vk_format == VK_FORMAT_D32_SFLOAT_S8_UINT);
case CELL_GCM_TEXTURE_A8R8G8B8:
return (vk_format == VK_FORMAT_B8G8R8A8_UNORM || vk_format == VK_FORMAT_D24_UNORM_S8_UINT || vk_format == VK_FORMAT_D32_SFLOAT_S8_UINT);
}
}
public: public:
struct vk_blit_op_result : public blit_op_result struct vk_blit_op_result : public blit_op_result
+33 -24
View File
@@ -253,8 +253,7 @@ namespace
}; };
} }
std::tuple<VkPrimitiveTopology, u32, u32, u32, std::optional<std::tuple<VkDeviceSize, VkIndexType> > > vk::vertex_upload_info VKGSRender::upload_vertex_data()
VKGSRender::upload_vertex_data()
{ {
m_vertex_layout = analyse_inputs_interleaved(); m_vertex_layout = analyse_inputs_interleaved();
@@ -266,11 +265,9 @@ VKGSRender::upload_vertex_data()
//Do actual vertex upload //Do actual vertex upload
auto required = calculate_memory_requirements(m_vertex_layout, vertex_count); auto required = calculate_memory_requirements(m_vertex_layout, vertex_count);
u32 persistent_range_base = UINT32_MAX, volatile_range_base = UINT32_MAX;
size_t persistent_offset = UINT64_MAX, volatile_offset = UINT64_MAX; size_t persistent_offset = UINT64_MAX, volatile_offset = UINT64_MAX;
m_persistent_attribute_storage = VK_NULL_HANDLE;
m_volatile_attribute_storage = VK_NULL_HANDLE;
if (required.first > 0) if (required.first > 0)
{ {
//Check if cacheable //Check if cacheable
@@ -287,8 +284,7 @@ VKGSRender::upload_vertex_data()
if (auto cached = m_vertex_cache->find_vertex_range(storage_address, VK_FORMAT_R8_UINT, required.first)) if (auto cached = m_vertex_cache->find_vertex_range(storage_address, VK_FORMAT_R8_UINT, required.first))
{ {
in_cache = true; in_cache = true;
m_current_frame->buffer_views_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, persistent_range_base = cached->offset_in_heap;
m_attrib_ring_info.heap->value, VK_FORMAT_R8_UINT, cached->offset_in_heap, required.first));
} }
else else
{ {
@@ -299,8 +295,7 @@ VKGSRender::upload_vertex_data()
if (!in_cache) if (!in_cache)
{ {
persistent_offset = (u32)m_attrib_ring_info.alloc<256>(required.first); persistent_offset = (u32)m_attrib_ring_info.alloc<256>(required.first);
m_current_frame->buffer_views_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, persistent_range_base = (u32)persistent_offset;
m_attrib_ring_info.heap->value, VK_FORMAT_R8_UINT, persistent_offset, required.first));
if (to_store) if (to_store)
{ {
@@ -308,25 +303,12 @@ VKGSRender::upload_vertex_data()
m_vertex_cache->store_range(storage_address, VK_FORMAT_R8_UINT, required.first, (u32)persistent_offset); m_vertex_cache->store_range(storage_address, VK_FORMAT_R8_UINT, required.first, (u32)persistent_offset);
} }
} }
m_persistent_attribute_storage = m_current_frame->buffer_views_to_clean.back()->value;
}
else
{
m_persistent_attribute_storage = null_buffer_view->value;
} }
if (required.second > 0) if (required.second > 0)
{ {
volatile_offset = (u32)m_attrib_ring_info.alloc<256>(required.second); volatile_offset = (u32)m_attrib_ring_info.alloc<256>(required.second);
m_current_frame->buffer_views_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device, volatile_range_base = (u32)volatile_offset;
m_attrib_ring_info.heap->value, VK_FORMAT_R8_UINT, volatile_offset, required.second));
m_volatile_attribute_storage = m_current_frame->buffer_views_to_clean.back()->value;
}
else
{
m_volatile_attribute_storage = null_buffer_view->value;
} }
//Write all the data once if possible //Write all the data once if possible
@@ -358,5 +340,32 @@ VKGSRender::upload_vertex_data()
} }
} }
return std::make_tuple(result.native_primitive_type, result.vertex_draw_count, result.allocated_vertex_count, result.vertex_index_base, result.index_info); if (persistent_range_base != UINT32_MAX)
{
if (!m_persistent_attribute_storage || !m_persistent_attribute_storage->in_range(persistent_range_base, required.first, persistent_range_base))
{
if (m_persistent_attribute_storage)
m_current_frame->buffer_views_to_clean.push_back(std::move(m_persistent_attribute_storage));
//View 64M blocks at a time (different drivers will only allow a fixed viewable heap size, 64M should be safe)
const size_t view_size = (persistent_range_base + 0x4000000) > m_attrib_ring_info.size() ? m_attrib_ring_info.size() - persistent_range_base : 0x4000000;
m_persistent_attribute_storage = std::make_unique<vk::buffer_view>(*m_device, m_attrib_ring_info.heap->value, VK_FORMAT_R8_UINT, persistent_range_base, view_size);
persistent_range_base = 0;
}
}
if (volatile_range_base != UINT32_MAX)
{
if (!m_volatile_attribute_storage || !m_volatile_attribute_storage->in_range(volatile_range_base, required.second, volatile_range_base))
{
if (m_volatile_attribute_storage)
m_current_frame->buffer_views_to_clean.push_back(std::move(m_volatile_attribute_storage));
const size_t view_size = (volatile_range_base + 0x4000000) > m_attrib_ring_info.size() ? m_attrib_ring_info.size() - volatile_range_base : 0x4000000;
m_volatile_attribute_storage = std::make_unique<vk::buffer_view>(*m_device, m_attrib_ring_info.heap->value, VK_FORMAT_R8_UINT, volatile_range_base, view_size);
volatile_range_base = 0;
}
}
return{ result.native_primitive_type, result.vertex_draw_count, result.allocated_vertex_count, result.vertex_index_base, persistent_range_base, volatile_range_base, result.index_info };
} }
+26 -33
View File
@@ -21,10 +21,10 @@ void fmt_class_string<frame_limit_type>::format(std::string& out, u64 arg)
switch (value) switch (value)
{ {
case frame_limit_type::none: return "Off"; case frame_limit_type::none: return "Off";
case frame_limit_type::_59_94: return "59.94";
case frame_limit_type::_50: return "50";
case frame_limit_type::_60: return "60";
case frame_limit_type::_30: return "30"; case frame_limit_type::_30: return "30";
case frame_limit_type::_50: return "50";
case frame_limit_type::_59_94: return "59.94";
case frame_limit_type::_60: return "60";
case frame_limit_type::_auto: return "Auto"; case frame_limit_type::_auto: return "Auto";
} }
@@ -35,7 +35,7 @@ void fmt_class_string<frame_limit_type>::format(std::string& out, u64 arg)
namespace rsx namespace rsx
{ {
rsx_state method_registers; rsx_state method_registers;
std::array<rsx_method_t, 0x10000 / 4> methods{}; std::array<rsx_method_t, 0x10000 / 4> methods{};
void invalid_method(thread* rsx, u32 _reg, u32 arg) void invalid_method(thread* rsx, u32 _reg, u32 arg)
@@ -64,10 +64,10 @@ namespace rsx
{ {
rsx->sync_point_request = true; rsx->sync_point_request = true;
const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e()); const u32 addr = get_address(method_registers.semaphore_offset_406e(), method_registers.semaphore_context_dma_406e());
if (vm::read32(addr) == arg) return; if (vm::ps3::read32(addr) == arg) return;
u64 start = get_system_time(); u64 start = get_system_time();
while (vm::read32(addr) != arg) while (vm::ps3::read32(addr) != arg)
{ {
// todo: LLE: why does this one keep hanging? is it vsh system semaphore? whats actually pushing this to the command buffer?! // todo: LLE: why does this one keep hanging? is it vsh system semaphore? whats actually pushing this to the command buffer?!
if (addr == 0x40000030) if (addr == 0x40000030)
@@ -116,12 +116,11 @@ namespace rsx
if (addr >> 28 == 0x4) if (addr >> 28 == 0x4)
{ {
// TODO: check no reservation area instead // TODO: check no reservation area instead
vm::write32(addr, arg); vm::ps3::write32(addr, arg);
return; return;
} }
vm::reader_lock lock; vm::ps3::write32(addr, arg);
vm::write32(addr, arg);
vm::notify(addr, 4); vm::notify(addr, 4);
} }
} }
@@ -162,7 +161,7 @@ namespace rsx
{ {
// //
} }
auto& sema = vm::_ref<RsxReports>(rsx->label_addr); auto& sema = vm::ps3::_ref<RsxReports>(rsx->label_addr);
sema.semaphore[index].val = arg; sema.semaphore[index].val = arg;
sema.semaphore[index].pad = 0; sema.semaphore[index].pad = 0;
sema.semaphore[index].timestamp = rsx->timestamp(); sema.semaphore[index].timestamp = rsx->timestamp();
@@ -177,7 +176,7 @@ namespace rsx
} }
u32 val = (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff); u32 val = (arg & 0xff00ff00) | ((arg & 0xff) << 16) | ((arg >> 16) & 0xff);
auto& sema = vm::_ref<RsxReports>(rsx->label_addr); auto& sema = vm::ps3::_ref<RsxReports>(rsx->label_addr);
sema.semaphore[index].val = val; sema.semaphore[index].val = val;
sema.semaphore[index].pad = 0; sema.semaphore[index].pad = 0;
sema.semaphore[index].timestamp = rsx->timestamp(); sema.semaphore[index].timestamp = rsx->timestamp();
@@ -352,7 +351,7 @@ namespace rsx
{ {
rsx::method_registers.current_draw_clause.first_count_commands.resize(0); rsx::method_registers.current_draw_clause.first_count_commands.resize(0);
rsx::method_registers.current_draw_clause.command = draw_command::none; rsx::method_registers.current_draw_clause.command = draw_command::none;
rsx::method_registers.current_draw_clause.primitive = to_primitive_type(arg); rsx::method_registers.current_draw_clause.primitive = rsx::method_registers.primitive_mode();
rsxthr->begin(); rsxthr->begin();
return; return;
} }
@@ -416,7 +415,7 @@ namespace rsx
return; return;
} }
vm::ptr<CellGcmReportData> result = address_ptr; vm::ps3::ptr<CellGcmReportData> result = address_ptr;
switch (type) switch (type)
{ {
@@ -484,7 +483,7 @@ namespace rsx
return; return;
} }
vm::ptr<CellGcmReportData> result = address_ptr; vm::ps3::ptr<CellGcmReportData> result = address_ptr;
rsx->conditional_render_test_failed = (result->value == 0); rsx->conditional_render_test_failed = (result->value == 0);
} }
@@ -553,7 +552,7 @@ namespace rsx
const u32 pixel_offset = (method_registers.blit_engine_output_pitch_nv3062() * y) + (x << 2); 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()); u32 address = get_address(method_registers.blit_engine_output_offset_nv3062() + pixel_offset + index * 4, method_registers.blit_engine_output_location_nv3062());
vm::write32(address, arg); vm::ps3::write32(address, arg);
} }
}; };
} }
@@ -662,7 +661,7 @@ namespace rsx
const tiled_region dst_region = rsx->get_tiled_address(dst_offset + out_offset, dst_dma & 0xf); const tiled_region dst_region = rsx->get_tiled_address(dst_offset + out_offset, dst_dma & 0xf);
u8* pixels_src = src_region.tile ? src_region.ptr + src_region.base : src_region.ptr; u8* pixels_src = src_region.tile ? src_region.ptr + src_region.base : src_region.ptr;
u8* pixels_dst = vm::_ptr<u8>(get_address(dst_offset + out_offset, dst_dma)); u8* pixels_dst = vm::ps3::_ptr<u8>(get_address(dst_offset + out_offset, dst_dma));
if (out_pitch == 0) if (out_pitch == 0)
{ {
@@ -694,8 +693,7 @@ namespace rsx
if (convert_w == 0 || convert_h == 0) if (convert_w == 0 || convert_h == 0)
{ {
LOG_ERROR(RSX, "NV3089_IMAGE_IN: Invalid dimensions or scaling factor. Request ignored (ds_dx=%d, dt_dy=%d)", LOG_ERROR(RSX, "NV3089_IMAGE_IN: Invalid dimensions or scaling factor. Request ignored");
method_registers.blit_engine_ds_dx(), method_registers.blit_engine_dt_dy());
return; return;
} }
@@ -790,7 +788,7 @@ namespace rsx
if (method_registers.blit_engine_context_surface() != blit_engine::context_surface::swizzle2d) if (method_registers.blit_engine_context_surface() != blit_engine::context_surface::swizzle2d)
{ {
if (need_convert || need_clip) if (need_convert || need_clip)
{ {
if (need_clip) if (need_clip)
{ {
if (need_convert) if (need_convert)
@@ -856,7 +854,7 @@ namespace rsx
pixels_src = temp2.get(); pixels_src = temp2.get();
} }
// It looks like rsx may ignore the requested swizzle size and just always // It looks like rsx may ignore the requested swizzle size and just always
// round up to nearest power of 2 // round up to nearest power of 2
/*u8 sw_width_log2 = method_registers.nv309e_sw_width_log2(); /*u8 sw_width_log2 = method_registers.nv309e_sw_width_log2();
u8 sw_height_log2 = method_registers.nv309e_sw_height_log2(); u8 sw_height_log2 = method_registers.nv309e_sw_height_log2();
@@ -934,7 +932,7 @@ namespace rsx
LOG_ERROR(RSX, "NV0039_OFFSET_IN: Unsupported format: inFormat=%d, outFormat=%d", in_format, out_format); LOG_ERROR(RSX, "NV0039_OFFSET_IN: Unsupported format: inFormat=%d, outFormat=%d", in_format, out_format);
} }
LOG_TRACE(RSX, "NV0039_OFFSET_IN: pitch(in=0x%x, out=0x%x), line(len=0x%x, cnt=0x%x), fmt(in=0x%x, out=0x%x), notify=0x%x", LOG_NOTICE(RSX, "NV0039_OFFSET_IN: pitch(in=0x%x, out=0x%x), line(len=0x%x, cnt=0x%x), fmt(in=0x%x, out=0x%x), notify=0x%x",
in_pitch, out_pitch, line_length, line_count, in_format, out_format, notify); in_pitch, out_pitch, line_length, line_count, in_format, out_format, notify);
if (!in_pitch) if (!in_pitch)
@@ -997,10 +995,10 @@ namespace rsx
switch (g_cfg.video.frame_limit) switch (g_cfg.video.frame_limit)
{ {
case frame_limit_type::none: limit = 0.; break; case frame_limit_type::none: limit = 0.; break;
case frame_limit_type::_59_94: limit = 59.94; break;
case frame_limit_type::_50: limit = 50.; break;
case frame_limit_type::_60: limit = 60.; break;
case frame_limit_type::_30: limit = 30.; break; case frame_limit_type::_30: limit = 30.; break;
case frame_limit_type::_50: limit = 50.; break;
case frame_limit_type::_59_94: limit = 59.94; break;
case frame_limit_type::_60: limit = 60.; break;
case frame_limit_type::_auto: limit = rsx->fps_limit; break; // TODO case frame_limit_type::_auto: limit = rsx->fps_limit; break; // TODO
} }
@@ -1028,7 +1026,7 @@ namespace rsx
} }
} }
} }
rsx->int_flip_index++; rsx->int_flip_index++;
rsx->current_display_buffer = arg; rsx->current_display_buffer = arg;
rsx->flip(arg); rsx->flip(arg);
@@ -1190,11 +1188,6 @@ namespace rsx
registers[reg] = value; registers[reg] = value;
} }
bool rsx_state::test(u32 reg, u32 value) const
{
return registers[reg] == value;
}
namespace method_detail namespace method_detail
{ {
template<int Id, int Step, int Count, template<u32> class T, int Index = 0> template<int Id, int Step, int Count, template<u32> class T, int Index = 0>
@@ -1567,7 +1560,7 @@ namespace rsx
//Some custom GCM methods //Some custom GCM methods
methods[GCM_SET_DRIVER_OBJECT] = nullptr; methods[GCM_SET_DRIVER_OBJECT] = nullptr;
bind_array<GCM_FLIP_HEAD, 1, 2, nullptr>(); bind_array<GCM_FLIP_HEAD, 1, 2, nullptr>();
bind_array<GCM_DRIVER_QUEUE, 1, 8, nullptr>(); bind_array<GCM_DRIVER_QUEUE, 1, 8, nullptr>();
@@ -1684,8 +1677,8 @@ namespace rsx
// custom methods // custom methods
bind<GCM_FLIP_COMMAND, flip_command>(); bind<GCM_FLIP_COMMAND, flip_command>();
return true;
return true;
}(); }();
} }
+1 -1
View File
@@ -96,7 +96,7 @@ void fmt_class_string<video_renderer>::format(std::string& out, u64 arg)
case video_renderer::opengl: return "OpenGL"; case video_renderer::opengl: return "OpenGL";
case video_renderer::vulkan: return "Vulkan"; case video_renderer::vulkan: return "Vulkan";
#ifdef _MSC_VER #ifdef _MSC_VER
case video_renderer::dx12: return "D3D12"; case video_renderer::dx12: return "DirectX 12";
#endif #endif
} }
+7 -7
View File
@@ -127,10 +127,10 @@ enum class video_aspect
enum class frame_limit_type enum class frame_limit_type
{ {
none, none,
_59_94,
_50,
_60,
_30, _30,
_50,
_59_94,
_60,
_auto, _auto,
}; };
@@ -291,7 +291,7 @@ struct cfg_root : cfg::node
cfg::_int<0, 16> spu_delay_penalty{this, "SPU delay penalty", 3}; //Number of milliseconds to block a thread if a virtual 'core' isn't free cfg::_int<0, 16> spu_delay_penalty{this, "SPU delay penalty", 3}; //Number of milliseconds to block a thread if a virtual 'core' isn't free
cfg::_bool spu_loop_detection{this, "SPU loop detection", true}; //Try to detect wait loops and trigger thread yield cfg::_bool spu_loop_detection{this, "SPU loop detection", true}; //Try to detect wait loops and trigger thread yield
cfg::_enum<lib_loading_type> lib_loading{this, "Lib Loader", lib_loading_type::liblv2only}; cfg::_enum<lib_loading_type> lib_loading{this, "Lib loader", lib_loading_type::liblv2only};
cfg::_bool hook_functions{this, "Hook static functions"}; cfg::_bool hook_functions{this, "Hook static functions"};
cfg::set_entry load_libraries{this, "Load libraries"}; cfg::set_entry load_libraries{this, "Load libraries"};
@@ -350,7 +350,7 @@ struct cfg_root : cfg::node
struct node_d3d12 : cfg::node struct node_d3d12 : cfg::node
{ {
node_d3d12(cfg::node* _this) : cfg::node(_this, "D3D12") {} node_d3d12(cfg::node* _this) : cfg::node(_this, "DirectX 12") {}
cfg::string adapter{this, "Adapter"}; cfg::string adapter{this, "Adapter"};
@@ -375,7 +375,7 @@ struct cfg_root : cfg::node
cfg::_enum<audio_renderer> renderer{this, "Renderer", static_cast<audio_renderer>(1)}; cfg::_enum<audio_renderer> renderer{this, "Renderer", static_cast<audio_renderer>(1)};
cfg::_bool dump_to_file{this, "Dump to file"}; cfg::_bool dump_to_file{this, "Dump to file"};
cfg::_bool convert_to_u16{this, "Convert to 16 bit"}; cfg::_bool convert_to_u16{this, "Convert to 16-bit"};
cfg::_bool downmix_to_2ch{this, "Downmix to Stereo", true}; cfg::_bool downmix_to_2ch{this, "Downmix to Stereo", true};
cfg::_int<2, 128> frames{this, "Buffer Count", 32}; cfg::_int<2, 128> frames{this, "Buffer Count", 32};
cfg::_int<1, 128> startt{this, "Start Threshold", 1}; cfg::_int<1, 128> startt{this, "Start Threshold", 1};
@@ -388,7 +388,7 @@ struct cfg_root : cfg::node
cfg::_enum<keyboard_handler> keyboard{this, "Keyboard", keyboard_handler::null}; cfg::_enum<keyboard_handler> keyboard{this, "Keyboard", keyboard_handler::null};
cfg::_enum<mouse_handler> mouse{this, "Mouse", mouse_handler::basic}; cfg::_enum<mouse_handler> mouse{this, "Mouse", mouse_handler::basic};
cfg::_enum<pad_handler> pad{this, "Pad", pad_handler::keyboard}; cfg::_enum<pad_handler> pad{this, "Controller", pad_handler::keyboard};
cfg::_enum<camera_handler> camera{this, "Camera", camera_handler::null}; cfg::_enum<camera_handler> camera{this, "Camera", camera_handler::null};
cfg::_enum<fake_camera_type> camera_type{this, "Camera type", fake_camera_type::unknown}; cfg::_enum<fake_camera_type> camera_type{this, "Camera type", fake_camera_type::unknown};
+1 -1
View File
@@ -31,7 +31,7 @@
<PropertyGroup Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
+1 -1
View File
@@ -31,7 +31,7 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+1 -1
View File
@@ -62,7 +62,7 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+1 -1
View File
@@ -31,7 +31,7 @@
<PropertyGroup Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings"> <ImportGroup Label="ExtensionSettings">
+2 -2
View File
@@ -30,7 +30,7 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Label="Configuration"> <PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType> <ConfigurationType>StaticLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
@@ -61,7 +61,7 @@
<ItemDefinitionGroup> <ItemDefinitionGroup>
<ClCompile> <ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader> <PrecompiledHeader>Use</PrecompiledHeader>
<AdditionalIncludeDirectories>..\3rdparty\zlib;..\llvm\include;..\llvm_build\include;</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>..\3rdparty\zlib;..\llvm\include;..\polly\include;..\llvm_build\include;</AdditionalIncludeDirectories>
</ClCompile> </ClCompile>
<PreBuildEvent> <PreBuildEvent>
<Command>%windir%\sysnative\cmd.exe /c "$(SolutionDir)\Utilities\git-version-gen.cmd"</Command> <Command>%windir%\sysnative\cmd.exe /c "$(SolutionDir)\Utilities\git-version-gen.cmd"</Command>
+2 -2
View File
@@ -40,14 +40,14 @@ if(EXISTS ${GIT_VERSION_FILE})
# Don't update if marked not to update. # Don't update if marked not to update.
file(STRINGS ${GIT_VERSION_FILE} match file(STRINGS ${GIT_VERSION_FILE} match
REGEX "RPCS3_GIT_VERSION_NO_UPDATE 1") REGEX "RPCS3_GIT_VERSION_NO_UPDATE 1")
if(NOT ${match} EQUAL "") if(NOT "${match}" EQUAL "")
set(GIT_VERSION_UPDATE "0") set(GIT_VERSION_UPDATE "0")
endif() endif()
# Don't update if it's already the same. # Don't update if it's already the same.
file(STRINGS ${GIT_VERSION_FILE} match file(STRINGS ${GIT_VERSION_FILE} match
REGEX "${GIT_VERSION}") REGEX "${GIT_VERSION}")
if(NOT ${match} EQUAL "") if(NOT "${match}" EQUAL "")
set(GIT_VERSION_UPDATE "0") set(GIT_VERSION_UPDATE "0")
endif() endif()
endif() endif()
+1
View File
@@ -86,6 +86,7 @@ int main(int argc, char** argv)
#endif #endif
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QCoreApplication::setAttribute(Qt::AA_DisableWindowContextHelpButton);
s_init.post(); s_init.post();
s_qt_mutex.wait(); s_qt_mutex.wait();
+5 -5
View File
@@ -26,7 +26,7 @@
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<PlatformToolSet>v140</PlatformToolSet> <PlatformToolSet>v141</PlatformToolSet>
<OutputDirectory>release\</OutputDirectory> <OutputDirectory>release\</OutputDirectory>
<ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage> <ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
@@ -35,7 +35,7 @@
<PrimaryOutput>rpcs3</PrimaryOutput> <PrimaryOutput>rpcs3</PrimaryOutput>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'" Label="Configuration">
<PlatformToolSet>v140</PlatformToolSet> <PlatformToolSet>v141</PlatformToolSet>
<OutputDirectory>release\</OutputDirectory> <OutputDirectory>release\</OutputDirectory>
<ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage> <ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
@@ -44,7 +44,7 @@
<PrimaryOutput>rpcs3</PrimaryOutput> <PrimaryOutput>rpcs3</PrimaryOutput>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<PlatformToolSet>v140</PlatformToolSet> <PlatformToolSet>v141</PlatformToolSet>
<OutputDirectory>debug\</OutputDirectory> <OutputDirectory>debug\</OutputDirectory>
<ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage> <ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
@@ -53,7 +53,7 @@
<PrimaryOutput>rpcs3</PrimaryOutput> <PrimaryOutput>rpcs3</PrimaryOutput>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'" Label="Configuration">
<PlatformToolSet>v140</PlatformToolSet> <PlatformToolSet>v141</PlatformToolSet>
<OutputDirectory>debug\</OutputDirectory> <OutputDirectory>debug\</OutputDirectory>
<ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage> <ATLMinimizesCRunTimeLibraryUsage>false</ATLMinimizesCRunTimeLibraryUsage>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
@@ -195,7 +195,7 @@
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
</ClCompile> </ClCompile>
<Link> <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> <AdditionalDependencies>gdi32.lib;..\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;%(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> <AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention> <DataExecutionPrevention>true</DataExecutionPrevention>
-1
View File
@@ -23,7 +23,6 @@ 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->patreon, &QAbstractButton::clicked, [] { QDesktopServices::openUrl(QUrl("https://www.patreon.com/Nekotekina")); });
connect(ui->close, &QAbstractButton::clicked, this, &QWidget::close); connect(ui->close, &QAbstractButton::clicked, this, &QWidget::close);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
layout()->setSizeConstraint(QLayout::SetFixedSize); layout()->setSizeConstraint(QLayout::SetFixedSize);
} }
+7 -9
View File
@@ -5,9 +5,7 @@ constexpr auto qstr = QString::fromStdString;
auto_pause_settings_dialog::auto_pause_settings_dialog(QWidget *parent) : QDialog(parent) auto_pause_settings_dialog::auto_pause_settings_dialog(QWidget *parent) : QDialog(parent)
{ {
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); QLabel *description = new QLabel(tr("To use automatic pause: enter the ID(s) of a function or a system call. You must restart your emulated game or application for changed settings to take effect. You can enable/disable this in the settings."), this);
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); pauseList = new QTableWidget(this);
pauseList->setColumnCount(2); pauseList->setColumnCount(2);
@@ -38,7 +36,7 @@ auto_pause_settings_dialog::auto_pause_settings_dialog(QWidget *parent) : QDialo
setLayout(mainLayout); setLayout(mainLayout);
setMinimumSize(QSize(400, 360)); setMinimumSize(QSize(400, 360));
setWindowTitle(tr("Auto Pause Manager")); setWindowTitle(tr("Automatic pause settings"));
//Events //Events
connect(pauseList, &QTableWidget::customContextMenuRequested, this, &auto_pause_settings_dialog::ShowContextMenu); connect(pauseList, &QTableWidget::customContextMenuRequested, this, &auto_pause_settings_dialog::ShowContextMenu);
@@ -47,7 +45,7 @@ auto_pause_settings_dialog::auto_pause_settings_dialog(QWidget *parent) : QDialo
connect(saveButton, &QAbstractButton::clicked, [=] connect(saveButton, &QAbstractButton::clicked, [=]
{ {
SaveEntries(); SaveEntries();
LOG_SUCCESS(HLE, "Auto Pause: File pause.bin was updated."); LOG_SUCCESS(HLE, "Automatic pause: file pause.bin was updated.");
}); });
connect(cancelButton, &QAbstractButton::clicked, this, &QWidget::close); connect(cancelButton, &QAbstractButton::clicked, this, &QWidget::close);
@@ -126,11 +124,11 @@ void auto_pause_settings_dialog::UpdateList(void)
if (m_entries[i] < 1024) if (m_entries[i] < 1024)
{ {
typeItem->setData(Qt::DisplayRole, tr("System Call")); typeItem->setData(Qt::DisplayRole, tr("System call"));
} }
else else
{ {
typeItem->setData(Qt::DisplayRole, tr("Function Call")); typeItem->setData(Qt::DisplayRole, tr("Function call"));
} }
pauseList->setItem(i, 0, callItem); pauseList->setItem(i, 0, callItem);
@@ -208,7 +206,7 @@ AutoPauseConfigDialog::AutoPauseConfigDialog(QWidget* parent, auto_pause_setting
button_ok->setFixedWidth(50); button_ok->setFixedWidth(50);
button_cancel->setFixedWidth(50); button_cancel->setFixedWidth(50);
QLabel* description = new QLabel(tr("Specify ID of System Call or Function Call below. You need to use a Hexadecimal ID."), this); QLabel* description = new QLabel(tr("Specify ID of system call or function call below. You need to use a hexadecimal ID."), this);
description->setWordWrap(true); description->setWordWrap(true);
m_current_converted = new QLabel(tr("Currently it gets an id of \"Unset\"."), this); m_current_converted = new QLabel(tr("Currently it gets an id of \"Unset\"."), this);
@@ -220,7 +218,7 @@ AutoPauseConfigDialog::AutoPauseConfigDialog(QWidget* parent, auto_pause_setting
m_id->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); m_id->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
m_id->setMaxLength(8); m_id->setMaxLength(8);
m_id->setFixedWidth(65); m_id->setFixedWidth(65);
setWindowTitle("Auto Pause Setting: " + m_id->text()); setWindowTitle("Automatic pause setting: " + m_id->text());
connect(button_cancel, &QAbstractButton::clicked, this, &AutoPauseConfigDialog::OnCancel); connect(button_cancel, &QAbstractButton::clicked, this, &AutoPauseConfigDialog::OnCancel);
connect(button_ok, &QAbstractButton::clicked, this, &AutoPauseConfigDialog::OnOk); connect(button_ok, &QAbstractButton::clicked, this, &AutoPauseConfigDialog::OnOk);
+1 -1
View File
@@ -22,7 +22,7 @@ inline std::string sstr(const QString& _in) { return _in.toStdString(); }
cg_disasm_window::cg_disasm_window(std::shared_ptr<gui_settings> xSettings): xgui_settings(xSettings) cg_disasm_window::cg_disasm_window(std::shared_ptr<gui_settings> xSettings): xgui_settings(xSettings)
{ {
setWindowTitle(tr("Cg Disasm")); setWindowTitle(tr("Cg disassembler"));
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
setAcceptDrops(true); setAcceptDrops(true);
setMinimumSize(QSize(200, 150)); // seems fine on win 10 setMinimumSize(QSize(200, 150)); // seems fine on win 10
+2 -2
View File
@@ -43,8 +43,8 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
m_breakpoints_list_delete->setShortcutContext(Qt::WidgetShortcut); m_breakpoints_list_delete->setShortcutContext(Qt::WidgetShortcut);
m_breakpoints_list->addAction(m_breakpoints_list_delete); m_breakpoints_list->addAction(m_breakpoints_list_delete);
m_go_to_addr = new QPushButton(tr("Go To Address"), this); m_go_to_addr = new QPushButton(tr("Go to address"), this);
m_go_to_pc = new QPushButton(tr("Go To PC"), this); m_go_to_pc = new QPushButton(tr("Go to PC"), this);
m_btn_capture = new QPushButton(tr("Capture"), this); m_btn_capture = new QPushButton(tr("Capture"), this);
m_btn_step = new QPushButton(tr("Step"), this); m_btn_step = new QPushButton(tr("Step"), this);
m_btn_run = new QPushButton(Run, this); m_btn_run = new QPushButton(Run, this);
+4 -4
View File
@@ -126,7 +126,7 @@ public:
QStringList vulkanAdapters; QStringList vulkanAdapters;
QString name_Null = tr("Null"); QString name_Null = tr("Null");
QString name_Vulkan = tr("Vulkan"); QString name_Vulkan = tr("Vulkan");
QString name_D3D12 = tr("D3D12[DO NOT USE]"); QString name_D3D12 = tr("DirectX 12");
QString name_OpenGL = tr("OpenGL"); QString name_OpenGL = tr("OpenGL");
Render_Info D3D12; Render_Info D3D12;
Render_Info Vulkan; Render_Info Vulkan;
@@ -186,7 +186,7 @@ private:
// Core Tab // Core Tab
{ PPUDecoder, { "Core", "PPU Decoder"}}, { PPUDecoder, { "Core", "PPU Decoder"}},
{ SPUDecoder, { "Core", "SPU Decoder"}}, { SPUDecoder, { "Core", "SPU Decoder"}},
{ LibLoadOptions, { "Core", "Lib Loader"}}, { LibLoadOptions, { "Core", "Lib loader"}},
{ HookStaticFuncs, { "Core", "Hook static functions"}}, { HookStaticFuncs, { "Core", "Hook static functions"}},
{ EnableThreadScheduler, { "Core", "Enable thread scheduler"}}, { EnableThreadScheduler, { "Core", "Enable thread scheduler"}},
{ LowerSPUThreadPrio, { "Core", "Lower SPU thread priority"}}, { LowerSPUThreadPrio, { "Core", "Lower SPU thread priority"}},
@@ -221,13 +221,13 @@ private:
{ AnisotropicFilterOverride,{ "Video", "Anisotropic Filter Override" }}, { AnisotropicFilterOverride,{ "Video", "Anisotropic Filter Override" }},
{ ResolutionScale, { "Video", "Resolution Scale" }}, { ResolutionScale, { "Video", "Resolution Scale" }},
{ MinimumScalableDimension, { "Video", "Minimum Scalable Dimension" }}, { MinimumScalableDimension, { "Video", "Minimum Scalable Dimension" }},
{ D3D12Adapter, { "Video", "D3D12", "Adapter"}}, { D3D12Adapter, { "Video", "DirectX 12", "Adapter"}},
{ VulkanAdapter, { "Video", "Vulkan", "Adapter"}}, { VulkanAdapter, { "Video", "Vulkan", "Adapter"}},
// Audio // Audio
{ AudioRenderer, { "Audio", "Renderer"}}, { AudioRenderer, { "Audio", "Renderer"}},
{ DumpToFile, { "Audio", "Dump to file"}}, { DumpToFile, { "Audio", "Dump to file"}},
{ ConvertTo16Bit, { "Audio", "Convert to 16 bit"}}, { ConvertTo16Bit, { "Audio", "Convert to 16-bit"}},
{ DownmixStereo, { "Audio", "Downmix to Stereo"}}, { DownmixStereo, { "Audio", "Downmix to Stereo"}},
// Input / Output // Input / Output
-1
View File
@@ -5,7 +5,6 @@
find_dialog::find_dialog(QTextEdit* edit, QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f), m_text_edit(edit) find_dialog::find_dialog(QTextEdit* edit, QWidget *parent, Qt::WindowFlags f) : QDialog(parent, f), m_text_edit(edit)
{ {
setWindowTitle(tr("Find string")); setWindowTitle(tr("Find string"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
m_find_bar = new QLineEdit(); m_find_bar = new QLineEdit();
m_find_bar->setPlaceholderText(tr("Search...")); m_find_bar->setPlaceholderText(tr("Search..."));
+23 -23
View File
@@ -24,7 +24,7 @@ inline std::string sstr(const QString& _in) { return _in.toStdString(); }
inline QSize sizeFromSlider(const int& pos) { return gui::gl_icon_size_min + (gui::gl_icon_size_max - gui::gl_icon_size_min) * (pos / (float)gui::gl_max_slider_pos); } inline QSize sizeFromSlider(const int& pos) { return gui::gl_icon_size_min + (gui::gl_icon_size_max - gui::gl_icon_size_min) * (pos / (float)gui::gl_max_slider_pos); }
game_list_frame::game_list_frame(std::shared_ptr<gui_settings> guiSettings, std::shared_ptr<emu_settings> emuSettings, QWidget *parent) game_list_frame::game_list_frame(std::shared_ptr<gui_settings> guiSettings, std::shared_ptr<emu_settings> emuSettings, QWidget *parent)
: QDockWidget(tr("Game List"), parent), xgui_settings(guiSettings), xemu_settings(emuSettings) : QDockWidget(tr("Game list"), parent), xgui_settings(guiSettings), xemu_settings(emuSettings)
{ {
m_isListLayout = xgui_settings->GetValue(gui::gl_listMode).toBool(); m_isListLayout = xgui_settings->GetValue(gui::gl_listMode).toBool();
m_icon_size_index = xgui_settings->GetValue(gui::gl_iconSize).toInt(); m_icon_size_index = xgui_settings->GetValue(gui::gl_iconSize).toInt();
@@ -87,10 +87,10 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> guiSettings, std:
m_categoryActs->setEnabled(m_isListLayout); m_categoryActs->setEnabled(m_isListLayout);
m_modeActList = { new QAction(""), QIcon(":/Icons/list_blue.png"), QIcon(":/Icons/list_gray.png") }; m_modeActList = { new QAction(""), QIcon(":/Icons/list_blue.png"), QIcon(":/Icons/list_gray.png") };
m_modeActList.action->setToolTip(tr("Enable List Mode")); m_modeActList.action->setToolTip(tr("Enable list mode"));
m_modeActGrid = { new QAction(""), QIcon(":/Icons/grid_blue.png"), QIcon(":/Icons/grid_gray.png") }; m_modeActGrid = { new QAction(""), QIcon(":/Icons/grid_blue.png"), QIcon(":/Icons/grid_gray.png") };
m_modeActGrid.action->setToolTip(tr("Enable Grid Mode")); m_modeActGrid.action->setToolTip(tr("Enable grid mode"));
m_modeActs = new QActionGroup(m_Tool_Bar); m_modeActs = new QActionGroup(m_Tool_Bar);
m_modeActs->addAction(m_modeActList.action); m_modeActs->addAction(m_modeActList.action);
@@ -186,17 +186,17 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> guiSettings, std:
m_Game_Dock->setCentralWidget(m_Central_Widget); m_Game_Dock->setCentralWidget(m_Central_Widget);
// Actions regarding showing/hiding columns // Actions regarding showing/hiding columns
QAction* showIconColAct = new QAction(tr("Show Icons"), this); QAction* showIconColAct = new QAction(tr("Show icons"), this);
QAction* showNameColAct = new QAction(tr("Show Names"), this); QAction* showNameColAct = new QAction(tr("Show names"), this);
QAction* showSerialColAct = new QAction(tr("Show Serials"), this); QAction* showSerialColAct = new QAction(tr("Show serials"), this);
QAction* showFWColAct = new QAction(tr("Show Firmwares"), this); QAction* showFWColAct = new QAction(tr("Show firmwares"), this);
QAction* showAppVersionColAct = new QAction(tr("Show Versions"), this); QAction* showAppVersionColAct = new QAction(tr("Show versions"), this);
QAction* showCategoryColAct = new QAction(tr("Show Categories"), this); QAction* showCategoryColAct = new QAction(tr("Show categories"), this);
QAction* showPathColAct = new QAction(tr("Show Paths"), this); QAction* showPathColAct = new QAction(tr("Show paths"), this);
QAction* showResolutionColAct = new QAction(tr("Show Supported Resolutions"), this); QAction* showResolutionColAct = new QAction(tr("Show supported resolutions"), this);
QAction* showSoundFormatColAct = new QAction(tr("Show Sound Formats"), this); QAction* showSoundFormatColAct = new QAction(tr("Show sound formats"), this);
QAction* showParentalLevelColAct = new QAction(tr("Show Parental Levels"), this); QAction* showParentalLevelColAct = new QAction(tr("Show parental levels"), this);
QAction* showCompatibilityAct = new QAction(tr("Show Compatibilities"), this); QAction* showCompatibilityAct = new QAction(tr("Show compatibilities"), this);
m_columnActs = { showIconColAct, showNameColAct, showSerialColAct, showFWColAct, showAppVersionColAct, showCategoryColAct, showPathColAct, m_columnActs = { showIconColAct, showNameColAct, showSerialColAct, showFWColAct, showAppVersionColAct, showCategoryColAct, showPathColAct,
showResolutionColAct, showSoundFormatColAct, showParentalLevelColAct, showCompatibilityAct }; showResolutionColAct, showSoundFormatColAct, showParentalLevelColAct, showCompatibilityAct };
@@ -670,15 +670,15 @@ void game_list_frame::ShowSpecifiedContextMenu(const QPoint &pos, int row)
QAction* configure = myMenu.addAction(tr("&Configure")); QAction* configure = myMenu.addAction(tr("&Configure"));
myMenu.addSeparator(); myMenu.addSeparator();
QAction* removeGame = myMenu.addAction(tr("&Remove")); QAction* removeGame = myMenu.addAction(tr("&Remove"));
QAction* removeConfig = myMenu.addAction(tr("&Remove Custom Configuration")); QAction* removeConfig = myMenu.addAction(tr("&Remove custom configuration"));
QAction* deleteShadersCache = myMenu.addAction(tr("&Delete Shaders Cache")); QAction* deleteShadersCache = myMenu.addAction(tr("&Delete shaders cache"));
QAction* deleteLLVMCache = myMenu.addAction(tr("&Delete LLVM Cache")); QAction* deleteLLVMCache = myMenu.addAction(tr("&Delete LLVM cache"));
myMenu.addSeparator(); myMenu.addSeparator();
QAction* openGameFolder = myMenu.addAction(tr("&Open Install Folder")); QAction* openGameFolder = myMenu.addAction(tr("&Open install folder"));
QAction* openConfig = myMenu.addAction(tr("&Open Config Folder")); QAction* openConfig = myMenu.addAction(tr("&Open config folder"));
myMenu.addSeparator(); myMenu.addSeparator();
QAction* checkCompat = myMenu.addAction(tr("&Check Game Compatibility")); QAction* checkCompat = myMenu.addAction(tr("&Check game compatibility"));
QAction* downloadCompat = myMenu.addAction(tr("&Download Compatibility Database")); QAction* downloadCompat = myMenu.addAction(tr("&Download compatibility database"));
connect(boot, &QAction::triggered, [=] connect(boot, &QAction::triggered, [=]
{ {
@@ -717,7 +717,7 @@ void game_list_frame::ShowSpecifiedContextMenu(const QPoint &pos, int row)
connect(deleteLLVMCache, &QAction::triggered, [=]() connect(deleteLLVMCache, &QAction::triggered, [=]()
{ {
if (QMessageBox::question(this, tr("Confirm Delete"), tr("Delete LLVM cache?")) == QMessageBox::Yes) 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; const std::string config_base_dir = fs::get_config_dir() + "data/" + m_game_data[row].info.serial;
@@ -832,7 +832,7 @@ void game_list_frame::RemoveCustomConfiguration(int row)
void game_list_frame::DeleteShadersCache(int row) void game_list_frame::DeleteShadersCache(int row)
{ {
if (QMessageBox::question(this, tr("Confirm Delete"), tr("Delete shaders cache?")) != QMessageBox::Yes) if (QMessageBox::question(this, tr("Confirm delete"), tr("Delete shaders cache?")) != QMessageBox::Yes)
return; return;
const std::string config_base_dir = fs::get_config_dir() + "data/" + m_game_data[row].info.serial; const std::string config_base_dir = fs::get_config_dir() + "data/" + m_game_data[row].info.serial;
@@ -76,7 +76,6 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
json_file.open(QIODevice::ReadOnly | QIODevice::Text); json_file.open(QIODevice::ReadOnly | QIODevice::Text);
QJsonObject json_input = QJsonDocument::fromJson(json_file.readAll()).object().value("input").toObject(); QJsonObject json_input = QJsonDocument::fromJson(json_file.readAll()).object().value("input").toObject();
json_file.close(); json_file.close();
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
QVBoxLayout *dialog_layout = new QVBoxLayout(); QVBoxLayout *dialog_layout = new QVBoxLayout();
QHBoxLayout *all_players = new QHBoxLayout(); QHBoxLayout *all_players = new QHBoxLayout();
-1
View File
@@ -69,6 +69,5 @@ void gl_gs_frame::flip(draw_context_t context, bool skip_frame)
//Do not swap buffers if frame skip is active //Do not swap buffers if frame skip is active
if (skip_frame) return; if (skip_frame) return;
((QOpenGLContext*)context)->makeCurrent(this);
((QOpenGLContext*)context)->swapBuffers(this); ((QOpenGLContext*)context)->swapBuffers(this);
} }
+1 -1
View File
@@ -105,7 +105,7 @@ void gs_frame::keyPressEvent(QKeyEvent *keyEvent)
case Qt::Key_R: case Qt::Key_R:
if (keyEvent->modifiers() == Qt::ControlModifier && (!Emu.GetBoot().empty())) { Emu.Restart(); return; } if (keyEvent->modifiers() == Qt::ControlModifier && (!Emu.GetBoot().empty())) { Emu.Restart(); return; }
break; break;
case Qt::Key_E: case Qt::Key_F:
if (keyEvent->modifiers() == Qt::ControlModifier) if (keyEvent->modifiers() == Qt::ControlModifier)
{ {
if (Emu.IsReady()) { Emu.Run(); return; } if (Emu.IsReady()) { Emu.Run(); return; }
-1
View File
@@ -260,7 +260,6 @@ void gui_settings::ShowInfoBox(const gui_save& entry, const QString& title, cons
{ {
QCheckBox* cb = new QCheckBox(tr("Don't show again")); QCheckBox* cb = new QCheckBox(tr("Don't show again"));
QMessageBox* mb = new QMessageBox(QMessageBox::Information, title, text, QMessageBox::Ok, parent); QMessageBox* mb = new QMessageBox(QMessageBox::Information, title, text, QMessageBox::Ok, parent);
mb->setWindowFlags(mb->windowFlags() & ~Qt::WindowContextHelpButtonHint);
mb->setCheckBox(cb); mb->setCheckBox(cb);
mb->deleteLater(); mb->deleteLater();
mb->exec(); mb->exec();
@@ -14,7 +14,6 @@ instruction_editor_dialog::instruction_editor_dialog(QWidget *parent, u32 _pc, c
{ {
setWindowTitle(tr("Edit instruction")); setWindowTitle(tr("Edit instruction"));
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setMinimumSize(300, sizeHint().height()); setMinimumSize(300, sizeHint().height());
const auto cpu = _cpu.get(); const auto cpu = _cpu.get();
+20 -21
View File
@@ -27,10 +27,9 @@
kernel_explorer::kernel_explorer(QWidget* parent) : QDialog(parent) kernel_explorer::kernel_explorer(QWidget* parent) : QDialog(parent)
{ {
setWindowTitle(tr("Kernel Explorer")); setWindowTitle(tr("Kernel explorer"));
setObjectName("kernel_explorer"); setObjectName("kernel_explorer");
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setMinimumSize(QSize(700, 450)); setMinimumSize(QSize(700, 450));
QVBoxLayout* vbox_panel = new QVBoxLayout(); QVBoxLayout* vbox_panel = new QVBoxLayout();
@@ -75,7 +74,7 @@ void kernel_explorer::Update()
const u32 total_memory_usage = vm_block->used(); const u32 total_memory_usage = vm_block->used();
QTreeWidgetItem* root = new QTreeWidgetItem(); QTreeWidgetItem* root = new QTreeWidgetItem();
root->setText(0, qstr(fmt::format("Process, ID = 0x00000001, Total Memory Usage = 0x%x (%0.2f MB)", total_memory_usage, (float)total_memory_usage / (1024 * 1024)))); root->setText(0, qstr(fmt::format("Process, ID = 0x00000001, Total memory usage = 0x%x (%0.2f MB)", total_memory_usage, (float)total_memory_usage / (1024 * 1024))));
m_tree->addTopLevelItem(root); m_tree->addTopLevelItem(root);
union name64 union name64
@@ -119,21 +118,21 @@ void kernel_explorer::Update()
std::vector<lv2_obj_rec> lv2_types(256); std::vector<lv2_obj_rec> lv2_types(256);
lv2_types[SYS_MEM_OBJECT] = l_addTreeChild(root, "Memory"); lv2_types[SYS_MEM_OBJECT] = l_addTreeChild(root, "Memory");
lv2_types[SYS_MUTEX_OBJECT] = l_addTreeChild(root, "Mutexes"); lv2_types[SYS_MUTEX_OBJECT] = l_addTreeChild(root, "Mutexes");
lv2_types[SYS_COND_OBJECT] = l_addTreeChild(root, "Condition Variables"); lv2_types[SYS_COND_OBJECT] = l_addTreeChild(root, "Condition variables");
lv2_types[SYS_RWLOCK_OBJECT] = l_addTreeChild(root, "Reader Writer Locks"); lv2_types[SYS_RWLOCK_OBJECT] = l_addTreeChild(root, "Reader writer locks");
lv2_types[SYS_INTR_TAG_OBJECT] = l_addTreeChild(root, "Interrupt Tags"); lv2_types[SYS_INTR_TAG_OBJECT] = l_addTreeChild(root, "Interrupt tags");
lv2_types[SYS_INTR_SERVICE_HANDLE_OBJECT] = l_addTreeChild(root, "Interrupt Service Handles"); lv2_types[SYS_INTR_SERVICE_HANDLE_OBJECT] = l_addTreeChild(root, "Interrupt service handles");
lv2_types[SYS_EVENT_QUEUE_OBJECT] = l_addTreeChild(root, "Event Queues"); lv2_types[SYS_EVENT_QUEUE_OBJECT] = l_addTreeChild(root, "Event queues");
lv2_types[SYS_EVENT_PORT_OBJECT] = l_addTreeChild(root, "Event Ports"); lv2_types[SYS_EVENT_PORT_OBJECT] = l_addTreeChild(root, "Event ports");
lv2_types[SYS_TRACE_OBJECT] = l_addTreeChild(root, "Traces"); lv2_types[SYS_TRACE_OBJECT] = l_addTreeChild(root, "Traces");
lv2_types[SYS_SPUIMAGE_OBJECT] = l_addTreeChild(root, "SPU Images"); lv2_types[SYS_SPUIMAGE_OBJECT] = l_addTreeChild(root, "SPU Images");
lv2_types[SYS_PRX_OBJECT] = l_addTreeChild(root, "Modules"); lv2_types[SYS_PRX_OBJECT] = l_addTreeChild(root, "Modules");
lv2_types[SYS_SPUPORT_OBJECT] = l_addTreeChild(root, "SPU Ports"); lv2_types[SYS_SPUPORT_OBJECT] = l_addTreeChild(root, "SPU Ports");
lv2_types[SYS_LWMUTEX_OBJECT] = l_addTreeChild(root, "Light Weight Mutexes"); lv2_types[SYS_LWMUTEX_OBJECT] = l_addTreeChild(root, "Light weight mutexes");
lv2_types[SYS_TIMER_OBJECT] = l_addTreeChild(root, "Timers"); lv2_types[SYS_TIMER_OBJECT] = l_addTreeChild(root, "Timers");
lv2_types[SYS_SEMAPHORE_OBJECT] = l_addTreeChild(root, "Semaphores"); lv2_types[SYS_SEMAPHORE_OBJECT] = l_addTreeChild(root, "Semaphores");
lv2_types[SYS_LWCOND_OBJECT] = l_addTreeChild(root, "Light Weight Condition Variables"); lv2_types[SYS_LWCOND_OBJECT] = l_addTreeChild(root, "Light weight condition variables");
lv2_types[SYS_EVENT_FLAG_OBJECT] = l_addTreeChild(root, "Event Flags"); lv2_types[SYS_EVENT_FLAG_OBJECT] = l_addTreeChild(root, "Event flags");
idm::select<lv2_obj>([&](u32 id, lv2_obj& obj) idm::select<lv2_obj>([&](u32 id, lv2_obj& obj)
{ {
@@ -171,26 +170,26 @@ void kernel_explorer::Update()
case SYS_INTR_TAG_OBJECT: case SYS_INTR_TAG_OBJECT:
{ {
// auto& tag = static_cast<lv2_int_tag&>(obj); // auto& tag = static_cast<lv2_int_tag&>(obj);
l_addTreeChild(node, qstr(fmt::format("Intr Tag: ID = 0x%08x", id))); l_addTreeChild(node, qstr(fmt::format("Intr tag: ID = 0x%08x", id)));
break; break;
} }
case SYS_INTR_SERVICE_HANDLE_OBJECT: case SYS_INTR_SERVICE_HANDLE_OBJECT:
{ {
// auto& serv = static_cast<lv2_int_serv&>(obj); // auto& serv = static_cast<lv2_int_serv&>(obj);
l_addTreeChild(node, qstr(fmt::format("Intr Svc: ID = 0x%08x", id))); l_addTreeChild(node, qstr(fmt::format("Intr svc: ID = 0x%08x", id)));
break; break;
} }
case SYS_EVENT_QUEUE_OBJECT: case SYS_EVENT_QUEUE_OBJECT:
{ {
auto& eq = static_cast<lv2_event_queue&>(obj); auto& eq = static_cast<lv2_event_queue&>(obj);
l_addTreeChild(node, qstr(fmt::format("Event Queue: ID = 0x%08x \"%s\", %s, Key = %#llx, Events = %zu/%d, Waiters = %zu", id, +name64(eq.name), l_addTreeChild(node, qstr(fmt::format("Event queue: ID = 0x%08x \"%s\", %s, Key = %#llx, Events = %zu/%d, Waiters = %zu", id, +name64(eq.name),
eq.type == SYS_SPU_QUEUE ? "SPU" : "PPU", eq.key, eq.events.size(), eq.size, eq.sq.size()))); eq.type == SYS_SPU_QUEUE ? "SPU" : "PPU", eq.key, eq.events.size(), eq.size, eq.sq.size())));
break; break;
} }
case SYS_EVENT_PORT_OBJECT: case SYS_EVENT_PORT_OBJECT:
{ {
auto& ep = static_cast<lv2_event_port&>(obj); auto& ep = static_cast<lv2_event_port&>(obj);
l_addTreeChild(node, qstr(fmt::format("Event Port: ID = 0x%08x, Name = %#llx", id, ep.name))); l_addTreeChild(node, qstr(fmt::format("Event port: ID = 0x%08x, Name = %#llx", id, ep.name)));
break; break;
} }
case SYS_TRACE_OBJECT: case SYS_TRACE_OBJECT:
@@ -253,12 +252,12 @@ void kernel_explorer::Update()
} }
}); });
lv2_types.emplace_back(l_addTreeChild(root, "Memory Containers")); lv2_types.emplace_back(l_addTreeChild(root, "Memory containers"));
idm::select<lv2_memory_container>([&](u32 id, lv2_memory_container&) idm::select<lv2_memory_container>([&](u32 id, lv2_memory_container&)
{ {
lv2_types.back().count++; lv2_types.back().count++;
l_addTreeChild(lv2_types.back().node, qstr(fmt::format("Memory Container: ID = 0x%08x", id))); l_addTreeChild(lv2_types.back().node, qstr(fmt::format("Memory container: ID = 0x%08x", id)));
}); });
lv2_types.emplace_back(l_addTreeChild(root, "PPU Threads")); lv2_types.emplace_back(l_addTreeChild(root, "PPU Threads"));
@@ -277,15 +276,15 @@ void kernel_explorer::Update()
l_addTreeChild(lv2_types.back().node, qstr(fmt::format("SPU Thread: ID = 0x%08x '%s'", id, spu.get_name()))); l_addTreeChild(lv2_types.back().node, qstr(fmt::format("SPU Thread: ID = 0x%08x '%s'", id, spu.get_name())));
}); });
lv2_types.emplace_back(l_addTreeChild(root, "SPU Thread Groups")); lv2_types.emplace_back(l_addTreeChild(root, "SPU Thread groups"));
idm::select<lv2_spu_group>([&](u32 id, lv2_spu_group& tg) idm::select<lv2_spu_group>([&](u32 id, lv2_spu_group& tg)
{ {
lv2_types.back().count++; lv2_types.back().count++;
l_addTreeChild(lv2_types.back().node, qstr(fmt::format("SPU Thread Group: ID = 0x%08x '%s'", id, tg.name))); l_addTreeChild(lv2_types.back().node, qstr(fmt::format("SPU Thread group: ID = 0x%08x '%s'", id, tg.name)));
}); });
lv2_types.emplace_back(l_addTreeChild(root, "File Descriptors")); lv2_types.emplace_back(l_addTreeChild(root, "File descriptors"));
idm::select<lv2_fs_object>([&](u32 id, lv2_fs_object& fo) idm::select<lv2_fs_object>([&](u32 id, lv2_fs_object& fo)
{ {
+4 -4
View File
@@ -290,7 +290,7 @@ void main_window::BootGame()
} }
QString path_last_Game = guiSettings->GetValue(gui::fd_boot_game).toString(); QString path_last_Game = guiSettings->GetValue(gui::fd_boot_game).toString();
QString dirPath = QFileDialog::getExistingDirectory(this, tr("Select Game Folder"), path_last_Game, QFileDialog::ShowDirsOnly); QString dirPath = QFileDialog::getExistingDirectory(this, tr("Select game folder"), path_last_Game, QFileDialog::ShowDirsOnly);
if (dirPath == NULL) if (dirPath == NULL)
{ {
@@ -727,7 +727,7 @@ void main_window::OnEmuPause()
m_thumb_playPause->setToolTip(tr("Resume emulation")); m_thumb_playPause->setToolTip(tr("Resume emulation"));
m_thumb_playPause->setIcon(m_icon_thumb_play); m_thumb_playPause->setIcon(m_icon_thumb_play);
#endif #endif
ui->sysPauseAct->setText(tr("&Resume\tCtrl+E")); ui->sysPauseAct->setText(tr("&Resume\tCtrl+F"));
ui->sysPauseAct->setIcon(m_icon_play); ui->sysPauseAct->setIcon(m_icon_play);
ui->toolbar_start->setIcon(m_icon_play); ui->toolbar_start->setIcon(m_icon_play);
ui->toolbar_start->setToolTip(tr("Resume emulation")); ui->toolbar_start->setToolTip(tr("Resume emulation"));
@@ -1099,7 +1099,7 @@ void main_window::CreateConnects()
{ {
sysutil_send_system_cmd(m_sys_menu_opened ? 0x0132 /* CELL_SYSUTIL_SYSTEM_MENU_CLOSE */ : 0x0131 /* CELL_SYSUTIL_SYSTEM_MENU_OPEN */, 0); sysutil_send_system_cmd(m_sys_menu_opened ? 0x0132 /* CELL_SYSUTIL_SYSTEM_MENU_CLOSE */ : 0x0131 /* CELL_SYSUTIL_SYSTEM_MENU_OPEN */, 0);
m_sys_menu_opened = !m_sys_menu_opened; m_sys_menu_opened = !m_sys_menu_opened;
ui->sysSendOpenMenuAct->setText(tr("Send &%0 system menu cmd").arg(m_sys_menu_opened ? tr("close") : tr("open"))); ui->sysSendOpenMenuAct->setText(tr("Press &%0 PS button").arg(m_sys_menu_opened ? tr("close") : tr("open")));
}); });
connect(ui->sysSendExitAct, &QAction::triggered, [=] connect(ui->sysSendExitAct, &QAction::triggered, [=]
@@ -1512,7 +1512,7 @@ void main_window::keyPressEvent(QKeyEvent *keyEvent)
{ {
switch (keyEvent->key()) switch (keyEvent->key())
{ {
case Qt::Key_E: if (Emu.IsPaused()) Emu.Resume(); else if (Emu.IsReady()) Emu.Run(); return; case Qt::Key_F: if (Emu.IsPaused()) Emu.Resume(); else if (Emu.IsReady()) Emu.Run(); return;
case Qt::Key_P: if (Emu.IsRunning()) Emu.Pause(); return; case Qt::Key_P: if (Emu.IsRunning()) Emu.Pause(); return;
case Qt::Key_S: if (!Emu.IsStopped()) Emu.Stop(); return; case Qt::Key_S: if (!Emu.IsStopped()) Emu.Stop(); return;
case Qt::Key_R: if (!Emu.GetBoot().empty()) Emu.Restart(); return; case Qt::Key_R: if (!Emu.GetBoot().empty()) Emu.Restart(); return;
+1 -2
View File
@@ -6,9 +6,8 @@
memory_string_searcher::memory_string_searcher(QWidget* parent) memory_string_searcher::memory_string_searcher(QWidget* parent)
: QDialog(parent) : QDialog(parent)
{ {
setWindowTitle(tr("String Searcher")); setWindowTitle(tr("String searcher"));
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
m_addr_line = new QLineEdit(this); m_addr_line = new QLineEdit(this);
m_addr_line->setFixedWidth(QLabel("This is the very length of the lineedit due to hidpi reasons.").sizeHint().width()); m_addr_line->setFixedWidth(QLabel("This is the very length of the lineedit due to hidpi reasons.").sizeHint().width());
+4 -5
View File
@@ -8,10 +8,9 @@ constexpr auto qstr = QString::fromStdString;
memory_viewer_panel::memory_viewer_panel(QWidget* parent) memory_viewer_panel::memory_viewer_panel(QWidget* parent)
: QDialog(parent) : QDialog(parent)
{ {
setWindowTitle(tr("Memory Viewer")); setWindowTitle(tr("Memory viewer"));
setObjectName("memory_viewer"); setObjectName("memory_viewer");
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
exit = false; exit = false;
m_addr = 0; m_addr = 0;
m_colcount = 16; m_colcount = 16;
@@ -30,7 +29,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent)
QHBoxLayout* hbox_tools = new QHBoxLayout(); QHBoxLayout* hbox_tools = new QHBoxLayout();
//Tools: Memory Viewer Options //Tools: Memory Viewer Options
QGroupBox* tools_mem = new QGroupBox(tr("Memory Viewer Options")); QGroupBox* tools_mem = new QGroupBox(tr("Memory viewer options"));
QHBoxLayout* hbox_tools_mem = new QHBoxLayout(); QHBoxLayout* hbox_tools_mem = new QHBoxLayout();
//Tools: Memory Viewer Options: Address //Tools: Memory Viewer Options: Address
@@ -82,7 +81,7 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent)
tools_mem->setLayout(hbox_tools_mem); tools_mem->setLayout(hbox_tools_mem);
//Tools: Raw Image Preview Options //Tools: Raw Image Preview Options
QGroupBox* tools_img = new QGroupBox(tr("Raw Image Preview Options")); QGroupBox* tools_img = new QGroupBox(tr("Raw image preview options"));
QHBoxLayout* hbox_tools_img = new QHBoxLayout();; QHBoxLayout* hbox_tools_img = new QHBoxLayout();;
//Tools: Raw Image Preview Options : Size //Tools: Raw Image Preview Options : Size
@@ -390,7 +389,7 @@ void memory_viewer_panel::ShowImage(QWidget* parent, u32 addr, int mode, u32 wid
layout->addWidget(canvas); layout->addWidget(canvas);
QDialog* f_image_viewer = new QDialog(parent); QDialog* f_image_viewer = new QDialog(parent);
f_image_viewer->setWindowTitle(qstr(fmt::format("Raw Image @ 0x%x", addr))); f_image_viewer->setWindowTitle(qstr(fmt::format("Raw image @ 0x%x", addr)));
f_image_viewer->setFixedSize(QSize(width, height)); f_image_viewer->setFixedSize(QSize(width, height));
f_image_viewer->setLayout(layout); f_image_viewer->setLayout(layout);
f_image_viewer->show(); f_image_viewer->show();
-2
View File
@@ -24,7 +24,6 @@ void msg_dialog_frame::Create(const std::string& msg)
m_dialog = new custom_dialog(type.disable_cancel); m_dialog = new custom_dialog(type.disable_cancel);
m_dialog->setWindowTitle(type.se_normal ? "Normal dialog" : "Error dialog"); m_dialog->setWindowTitle(type.se_normal ? "Normal dialog" : "Error dialog");
m_dialog->setWindowFlags(m_dialog->windowFlags() & ~Qt::WindowContextHelpButtonHint);
m_dialog->setWindowOpacity(type.bg_invisible ? 1. : 0.75); m_dialog->setWindowOpacity(type.bg_invisible ? 1. : 0.75);
m_text = new QLabel(qstr(msg)); m_text = new QLabel(qstr(msg));
@@ -246,7 +245,6 @@ void msg_dialog_frame::CreateOsk(const std::string& msg, char16_t* osk_text, u32
//Title //Title
m_osk_dialog->setWindowTitle(qstr(msg)); m_osk_dialog->setWindowTitle(qstr(msg));
m_osk_dialog->setWindowFlags(m_osk_dialog->windowFlags() & ~Qt::WindowContextHelpButtonHint);
//Text Input //Text Input
QLineEdit* input = new QLineEdit(m_osk_dialog); QLineEdit* input = new QLineEdit(m_osk_dialog);

Some files were not shown because too many files have changed in this diff Show More