mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-09-11 23:32:56 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37a8be7b42 | ||
|
|
4cdda8d99b | ||
|
|
a5fc5aefc9 | ||
|
|
e6a88bccff | ||
|
|
0caaa2cb49 | ||
|
|
4a4cbb875e | ||
|
|
6a0d3011ab | ||
|
|
d3cc62f37e | ||
|
|
32c19d94fa | ||
|
|
1810140d1d | ||
|
|
7676b1f73e |
+1
-1
@@ -2,7 +2,7 @@
|
||||
* text=auto
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.sln text eol=crlf
|
||||
*.slnx text eol=crlf
|
||||
*.props text eol=crlf
|
||||
*.vcxproj text eol=crlf
|
||||
*.vcxproj.filters text eol=crlf
|
||||
|
||||
+2
-2
@@ -6,8 +6,8 @@
|
||||
- any-glob-to-any-file:
|
||||
- '.github/*'
|
||||
- '.github/**/*'
|
||||
- '*.sln'
|
||||
- '**/*.sln'
|
||||
- '*.slnx'
|
||||
- '**/*.slnx'
|
||||
- '*.vcxproj*'
|
||||
- '**/*.vcxproj*'
|
||||
- 'cmake/*'
|
||||
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
|
||||
- name: Build Flatpak (beta)
|
||||
if: ${{ inputs.stableBuild == false || inputs.stableBuild == 'false' }}
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@401fe28a8384095fc1531b9d320b292f0ee45adb
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@79327416609af08178ad73b352877e51450790b3
|
||||
with:
|
||||
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
|
||||
upload-artifact: false
|
||||
@@ -109,7 +109,7 @@ jobs:
|
||||
|
||||
- name: Build Flatpak (stable)
|
||||
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@401fe28a8384095fc1531b9d320b292f0ee45adb
|
||||
uses: flatpak/flatpak-github-actions/flatpak-builder@79327416609af08178ad73b352877e51450790b3
|
||||
with:
|
||||
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
|
||||
upload-artifact: false
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
|
||||
- name: Push to Flathub (beta)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == false || inputs.stableBuild == 'false') }}
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@401fe28a8384095fc1531b9d320b292f0ee45adb
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@79327416609af08178ad73b352877e51450790b3
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: beta
|
||||
@@ -138,7 +138,7 @@ jobs:
|
||||
|
||||
- name: Push to Flathub (stable)
|
||||
if: ${{ inputs.publish == true && (inputs.stableBuild == true || inputs.stableBuild == 'true') }}
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@401fe28a8384095fc1531b9d320b292f0ee45adb
|
||||
uses: flatpak/flatpak-github-actions/flat-manager@79327416609af08178ad73b352877e51450790b3
|
||||
with:
|
||||
flat-manager-url: https://hub.flathub.org/
|
||||
repository: stable
|
||||
|
||||
@@ -145,7 +145,7 @@ jobs:
|
||||
cmake --build build --config Release || exit /b
|
||||
cmake --install build --config Release || exit /b
|
||||
) else (
|
||||
msbuild "PCSX2_qt.sln" /m /v:m /p:Configuration="${{ inputs.configuration }}" /p:Platform="${{ inputs.platform }}" || exit /b
|
||||
msbuild "PCSX2_qt.slnx" /m /v:m /p:Configuration="${{ inputs.configuration }}" /p:Platform="${{ inputs.platform }}" || exit /b
|
||||
)
|
||||
REM We can use Segoe UI Emoji so we don't need to bundle this
|
||||
del bin\resources\fonts\Twemoji*
|
||||
|
||||
-1018
File diff suppressed because it is too large
Load Diff
+485
@@ -0,0 +1,485 @@
|
||||
<Solution>
|
||||
<Configurations>
|
||||
<BuildType Name="Debug" />
|
||||
<BuildType Name="Debug AVX2" />
|
||||
<BuildType Name="Debug Clang" />
|
||||
<BuildType Name="Debug Clang AVX2" />
|
||||
<BuildType Name="Devel" />
|
||||
<BuildType Name="Devel AVX2" />
|
||||
<BuildType Name="Devel Clang" />
|
||||
<BuildType Name="Devel Clang AVX2" />
|
||||
<BuildType Name="Release" />
|
||||
<BuildType Name="Release AVX2" />
|
||||
<BuildType Name="Release Clang" />
|
||||
<BuildType Name="Release Clang AVX2" />
|
||||
<Platform Name="ARM64" />
|
||||
<Platform Name="x64" />
|
||||
</Configurations>
|
||||
<Folder Name="/3rdparty/">
|
||||
<Project Path="3rdparty/ccc/ccc.vcxproj" Id="2589f8ce-ea77-4b73-911e-64074569795b">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/cpuinfo/cpuinfo.vcxproj" Id="7e183337-a7e9-460c-9d3d-568bc9f9bcc1">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/cubeb/cubeb.vcxproj" Id="bf74c473-dc04-44b3-92e8-4145f4e77342">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/d3d12memalloc/d3d12memalloc.vcxproj" Id="d45cec7a-3171-40dd-975d-e1544cf16139">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/demangler/demangler.vcxproj" Id="d31a6dd1-99ca-41d8-a230-1fae913c8989">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/discord-rpc/discord-rpc.vcxproj" Id="e960dfdf-1bd3-4c29-b251-d1a0919c9b09">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/fmt/fmt.vcxproj" Id="449ad25e-424a-4714-babc-68706cdcc33b">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/freesurround/freesurround.vcxproj" Id="1dd0b31f-37f0-4a36-a521-74133aca4737">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/glad/glad.vcxproj" Id="c0293b32-5acf-40f0-aa6c-e6da6f3bf33a">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/imgui/imgui.vcxproj" Id="88fb34ec-845e-4f21-a552-f1573b9ed167">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/libchdr/libchdr.vcxproj" Id="a0d2b3ad-1f72-4ee3-8b5c-f2c358da35f0">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/libzip/libzip.vcxproj" Id="20b2e9fe-f020-42a0-b324-956f5b06ea68">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/lzma/lzma.vcxproj" Id="a4323327-3f2b-4271-83d9-7f9a3c66b6b2">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/rainterface/rainterface.vcxproj" Id="95dd0a0c-d14d-4cff-a593-820ef26efcc8">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/rcheevos/rcheevos.vcxproj" Id="6d5b5ad9-1525-459b-939f-a5e1082af6b3">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/simpleini/simpleini.vcxproj" Id="1ec8b3c0-8fb3-46de-a2e0-a9121203f266">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/soundtouch/SoundTouch.vcxproj" Id="e9b51944-7e6d-4bcd-83f2-7bbd5a46182d">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/vixl/vixl.vcxproj" Id="8906836e-f06e-46e8-b11a-74e5e8c7b8fb">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="*|x64" Project="false" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/zydis/zydis.vcxproj" Id="67d0160c-0fe4-44b9-ac2e-82bbcf4104df">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="*|ARM64" Project="false" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Project Path="common/common.vcxproj" Id="4639972e-424e-4e13-8b07-ca403c481346">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="pcsx2-gsrunner/pcsx2-gsrunner.vcxproj" Id="bb98bf81-a132-444a-bb81-96d510f433a8">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Project="false" />
|
||||
</Project>
|
||||
<Project Path="pcsx2-qt/pcsx2-qt.vcxproj" Id="2a016f21-87ae-4154-8271-1f57e91408e9">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="pcsx2/pcsx2.vcxproj" Id="6c7986c4-3e4d-4dcc-b3c6-6bb12b238995">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="updater/updater.vcxproj" Id="90bbdc04-cc44-4006-b893-06a4fea8ed47">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
</Solution>
|
||||
@@ -60605,7 +60605,6 @@ SLPS-25529:
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns DoF effects.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UltramanFightingEvolution"
|
||||
SLPS-25530:
|
||||
name: "餓狼伝 Breakblow"
|
||||
name-sort: "がろうでん Breakblow"
|
||||
@@ -62343,7 +62342,6 @@ SLPS-25800:
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns DoF effects.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UltramanFightingEvolution"
|
||||
SLPS-25801:
|
||||
name: "今日からマ王! 眞マ国の休日"
|
||||
name-sort: "きょうからまおう しんまこくのきゅうじつ"
|
||||
|
||||
+3
-110
@@ -62,7 +62,6 @@ namespace GSRunner
|
||||
static bool InitializeConfig();
|
||||
static void SettingsOverride();
|
||||
static bool ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& params);
|
||||
static void DumpStats();
|
||||
|
||||
static bool CreatePlatformWindow();
|
||||
static void DestroyPlatformWindow();
|
||||
@@ -80,43 +79,11 @@ static std::string s_output_prefix;
|
||||
static s32 s_loop_count = 1;
|
||||
static std::optional<bool> s_use_window;
|
||||
static bool s_no_console = false;
|
||||
static bool s_perf_enable = false;
|
||||
|
||||
// Owned by the GS thread.
|
||||
static u32 s_dump_frame_number = 0;
|
||||
static u32 s_loop_number = s_loop_count;
|
||||
static double s_last_internal_draws = 0;
|
||||
static double s_last_draws = 0;
|
||||
static double s_last_render_passes = 0;
|
||||
static double s_last_barriers = 0;
|
||||
static double s_last_copies = 0;
|
||||
static double s_last_uploads = 0;
|
||||
static double s_last_readbacks = 0;
|
||||
static double s_last_depth_copies_rov = 0;
|
||||
static double s_last_draws_rov = 0;
|
||||
static double s_last_barriers_rov = 0;
|
||||
static u64 s_total_internal_draws = 0;
|
||||
static u64 s_total_draws = 0;
|
||||
static u64 s_total_render_passes = 0;
|
||||
static u64 s_total_barriers = 0;
|
||||
static u64 s_total_copies = 0;
|
||||
static u64 s_total_uploads = 0;
|
||||
static u64 s_total_readbacks = 0;
|
||||
static u64 s_total_copies_rov = 0;
|
||||
static u64 s_total_draws_rov = 0;
|
||||
static u64 s_total_barriers_rov = 0;
|
||||
static u32 s_total_frames = 0;
|
||||
static u32 s_total_drawn_frames = 0;
|
||||
|
||||
static bool s_perf_enable = false;
|
||||
static float s_perf_updates = 0.0f;
|
||||
static float s_perf_sum_fps = 0.0f;
|
||||
static float s_perf_sum_internal_fps = 0.0f;
|
||||
static float s_perf_sum_cpu_thread_usage = 0.0f;
|
||||
static float s_perf_sum_cpu_thread_time = 0.0f;
|
||||
static float s_perf_sum_gs_thread_usage = 0.0f;
|
||||
static float s_perf_sum_gs_thread_time = 0.0f;
|
||||
static float s_perf_sum_gpu_time = 0.0f;
|
||||
static float s_perf_sum_gpu_usage = 0.0f;
|
||||
|
||||
bool GSRunner::InitializeConfig()
|
||||
{
|
||||
@@ -278,39 +245,6 @@ void Host::BeginPresentFrame()
|
||||
std::string dump_path(fmt::format("{}_frame{:05}.png", s_output_prefix, s_dump_frame_number));
|
||||
GSQueueSnapshot(dump_path);
|
||||
}
|
||||
|
||||
if (GSIsHardwareRenderer())
|
||||
{
|
||||
const u32 last_draws = s_total_internal_draws;
|
||||
const u32 last_uploads = s_total_uploads;
|
||||
|
||||
static constexpr auto update_stat = [](GSPerfMon::counter_t counter, u64& dst, double& last) {
|
||||
// perfmon resets every 30 frames to zero
|
||||
const double val = g_perfmon.GetCounter(counter);
|
||||
dst += static_cast<u64>((val < last) ? val : (val - last));
|
||||
last = val;
|
||||
};
|
||||
|
||||
update_stat(GSPerfMon::Draw, s_total_internal_draws, s_last_internal_draws);
|
||||
update_stat(GSPerfMon::DrawCalls, s_total_draws, s_last_draws);
|
||||
update_stat(GSPerfMon::RenderPasses, s_total_render_passes, s_last_render_passes);
|
||||
update_stat(GSPerfMon::Barriers, s_total_barriers, s_last_barriers);
|
||||
update_stat(GSPerfMon::TextureCopies, s_total_copies, s_last_copies);
|
||||
update_stat(GSPerfMon::TextureUploads, s_total_uploads, s_last_uploads);
|
||||
update_stat(GSPerfMon::Readbacks, s_total_readbacks, s_last_readbacks);
|
||||
update_stat(GSPerfMon::TextureCopiesROV, s_total_copies_rov, s_last_depth_copies_rov);
|
||||
update_stat(GSPerfMon::DrawCallsROV, s_total_draws_rov, s_last_draws_rov);
|
||||
update_stat(GSPerfMon::BarriersROV, s_total_barriers_rov, s_last_barriers_rov);
|
||||
|
||||
const bool idle_frame = s_total_frames && (last_draws == s_total_internal_draws && last_uploads == s_total_uploads);
|
||||
|
||||
if (!idle_frame)
|
||||
s_total_drawn_frames++;
|
||||
|
||||
s_total_frames++;
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
void Host::RequestResizeHostDisplay(s32 width, s32 height)
|
||||
@@ -344,18 +278,6 @@ void Host::OnGameChanged(const std::string& title, const std::string& elf_overri
|
||||
|
||||
void Host::OnPerformanceMetricsUpdated()
|
||||
{
|
||||
if (s_perf_enable)
|
||||
{
|
||||
s_perf_updates += 1.0f;
|
||||
s_perf_sum_fps += PerformanceMetrics::GetFPS();
|
||||
s_perf_sum_internal_fps += PerformanceMetrics::GetInternalFPS();
|
||||
s_perf_sum_cpu_thread_usage += PerformanceMetrics::GetCPUThreadUsage();
|
||||
s_perf_sum_cpu_thread_time += PerformanceMetrics::GetCPUThreadAverageTime();
|
||||
s_perf_sum_gs_thread_usage += PerformanceMetrics::GetGSThreadUsage();
|
||||
s_perf_sum_gs_thread_time += PerformanceMetrics::GetGSThreadAverageTime();
|
||||
s_perf_sum_gpu_time += PerformanceMetrics::GetGPUAverageTime();
|
||||
s_perf_sum_gpu_usage += PerformanceMetrics::GetGPUUsage();
|
||||
}
|
||||
}
|
||||
|
||||
void Host::OnSaveStateLoading(const std::string_view filename)
|
||||
@@ -655,6 +577,7 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
{
|
||||
s_loop_count = StringUtil::FromChars<s32>(argv[++i]).value_or(0);
|
||||
Console.WriteLn("Looping dump playback %d times.", s_loop_count);
|
||||
s_settings_interface.SetIntValue("EmuCore/GS", "DumpReplayLoopCount", s_loop_count);
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG_PARAM("-renderer"))
|
||||
@@ -907,34 +830,6 @@ void GSRunner::SettingsOverride()
|
||||
}
|
||||
}
|
||||
|
||||
void GSRunner::DumpStats()
|
||||
{
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
Console.WriteLn(fmt::format("======= HW STATISTICS FOR {} ({}) FRAMES ========", s_total_frames, s_total_drawn_frames));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Draw Calls: {} (avg {})", s_total_draws, static_cast<u64>(std::ceil(s_total_draws / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Render Passes: {} (avg {})", s_total_render_passes, static_cast<u64>(std::ceil(s_total_render_passes / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Barriers: {} (avg {})", s_total_barriers, static_cast<u64>(std::ceil(s_total_barriers / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Copies: {} (avg {})", s_total_copies, static_cast<u64>(std::ceil(s_total_copies / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Uploads: {} (avg {})", s_total_uploads, static_cast<u64>(std::ceil(s_total_uploads / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Readbacks: {} (avg {})", s_total_readbacks, static_cast<u64>(std::ceil(s_total_readbacks / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Copies (ROV): {} (avg {})", s_total_copies_rov, static_cast<u64>(std::ceil(s_total_copies_rov / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Draws Calls (ROV): {} (avg {})", s_total_draws_rov, static_cast<u64>(std::ceil(s_total_draws_rov / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Barriers (ROV): {} (avg {})", s_total_barriers_rov, static_cast<u64>(std::ceil(s_total_barriers_rov / static_cast<double>(s_total_drawn_frames)))));
|
||||
if (s_perf_enable)
|
||||
{
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Minimum Frame Time: {:.3f} ms ({:.3f} FPS)", PerformanceMetrics::GetMinimumFrameTime(), 1000.0f / PerformanceMetrics::GetMinimumFrameTime()));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Average Frame Time: {:.3f} ms ({:.3f} FPS)", PerformanceMetrics::GetAverageFrameTime(), 1000.0f / PerformanceMetrics::GetAverageFrameTime()));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Maximum Frame Time: {:.3f} ms ({:.3f} FPS)", PerformanceMetrics::GetMaximumFrameTime(), 1000.0f / PerformanceMetrics::GetMaximumFrameTime()));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ CPU Thread Usage: {:.3f} %", s_perf_sum_cpu_thread_usage / s_perf_updates));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ GS Thread Usage: {:.3f} %", s_perf_sum_gs_thread_usage / s_perf_updates));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ GPU Usage: {:.3f} %", s_perf_sum_gpu_usage / s_perf_updates));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Average CPU Thread Time: {:.3f} ms", s_perf_sum_cpu_thread_time / s_perf_updates));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Average GS Thread Time: {:.3f} ms", s_perf_sum_gs_thread_time / s_perf_updates));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Average GPU Time: {:.3f} ms", s_perf_sum_gpu_time / s_perf_updates));
|
||||
}
|
||||
Console.WriteLn("============================================");
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// We can't handle unicode in filenames if we don't use wmain on Win32.
|
||||
#define main real_main
|
||||
@@ -948,12 +843,11 @@ static void CPUThreadMain(VMBootParameters* params, std::atomic<int>* ret)
|
||||
{
|
||||
// apply new settings (e.g. pick up renderer change)
|
||||
VMManager::ApplySettings();
|
||||
GSDumpReplayer::SetIsDumpRunner(true);
|
||||
GSDumpReplayer::SetIsDumpRunner(true, s_perf_enable);
|
||||
|
||||
if (VMManager::Initialize(*params) == VMBootResult::StartupSuccess)
|
||||
{
|
||||
// run until end
|
||||
GSDumpReplayer::SetLoopCount(s_loop_count);
|
||||
VMManager::SetState(VMState::Running);
|
||||
if (s_perf_enable)
|
||||
{
|
||||
@@ -963,7 +857,6 @@ static void CPUThreadMain(VMBootParameters* params, std::atomic<int>* ret)
|
||||
while (VMManager::GetState() == VMState::Running)
|
||||
VMManager::Execute();
|
||||
VMManager::Shutdown(false);
|
||||
GSRunner::DumpStats();
|
||||
ret->store(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<widget class="QGroupBox" name="groupBoxDrawDumping">
|
||||
<property name="title">
|
||||
<string>Draw Dumping</string>
|
||||
</property>
|
||||
@@ -240,6 +240,118 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxDumpReplay">
|
||||
<property name="title">
|
||||
<string>Dump Replay Options</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayoutDumpReplay">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayoutDumpReplay">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="replayUseFrameRange">
|
||||
<property name="text">
|
||||
<string>Use Frame Range</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelDumpReplay1">
|
||||
<property name="text">
|
||||
<string>Replay Frame Start:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>replayFrameStart</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="replayFrameStart">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelDumpReplay2">
|
||||
<property name="text">
|
||||
<string>Replay Frame End:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>replayFrameEnd</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="replayFrameEnd">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelDumpReplay3">
|
||||
<property name="text">
|
||||
<string>Replay Loop Count:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>replayLoopCount</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="replayLoopCount">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxPerfMetrics">
|
||||
<property name="title">
|
||||
<string>Performance Metrics Options</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayoutPerfMetrics">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelPerfMetrics1">
|
||||
<property name="text">
|
||||
<string>Saved Metrics Capture Time:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>savedMetricsCaptureSeconds</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="savedMetricsCaptureSeconds">
|
||||
<property name="suffix">
|
||||
<string> seconds</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -159,6 +159,16 @@ DebugSettingsWidget::DebugSettingsWidget(SettingsWindow* settings_dialog, QWidge
|
||||
tr("Destination directory for dumps generated by the hardware renderer."));
|
||||
dialog()->registerWidgetHelp(m_gs.swDumpDirectory, tr("Software Dump Directory"), tr("Default"),
|
||||
tr("Destination directory for dumps generated by the software renderer."));
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.replayUseFrameRange, "EmuCore/GS", "DumpReplayUseFrameRange", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.replayFrameStart, "EmuCore/GS", "DumpReplayFrameStart", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.replayFrameEnd, "EmuCore/GS", "DumpReplayFrameEnd", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.replayLoopCount, "EmuCore/GS", "DumpReplayLoopCount", 0);
|
||||
|
||||
connect(m_gs.replayUseFrameRange, &QCheckBox::checkStateChanged, this, &DebugSettingsWidget::onDumpReplayUseFrameRangeChanged);
|
||||
onDumpReplayUseFrameRangeChanged();
|
||||
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.savedMetricsCaptureSeconds, "EmuCore/GS", "SavedMetricsCaptureSeconds", 10);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -268,6 +278,13 @@ void DebugSettingsWidget::onDrawDumpingChanged()
|
||||
m_gs.swDumpOpen->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void DebugSettingsWidget::onDumpReplayUseFrameRangeChanged()
|
||||
{
|
||||
const bool enabled = dialog()->getEffectiveBoolValue("EmuCore/GS", "DumpReplayUseFrameRange", false);
|
||||
m_gs.replayFrameStart->setEnabled(enabled);
|
||||
m_gs.replayFrameEnd->setEnabled(enabled);
|
||||
}
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
void DebugSettingsWidget::onLoggingEnableChanged()
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
|
||||
private Q_SLOTS:
|
||||
void onDrawDumpingChanged();
|
||||
void onDumpReplayUseFrameRangeChanged();
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
void onLoggingEnableChanged();
|
||||
#endif
|
||||
|
||||
@@ -33,6 +33,7 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* settings_dialog
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.syncToHostRefreshRate, "EmuCore/GS", "SyncToHostRefreshRate", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useVSyncForTiming, "EmuCore/GS", "UseVSyncForTiming", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.skipPresentingDuplicateFrames, "EmuCore/GS", "SkipDuplicateFrames", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.advancedFrameDisplay, "EmuCore/GS", "AdvancedFrameDisplay", false);
|
||||
connect(m_ui.optimalFramePacing, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::onOptimalFramePacingChanged);
|
||||
connect(m_ui.vsync, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::updateUseVSyncForTimingEnabled);
|
||||
connect(m_ui.syncToHostRefreshRate, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::updateUseVSyncForTimingEnabled);
|
||||
@@ -155,6 +156,11 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* settings_dialog
|
||||
"rendered, it just means the GPU has more time to complete it (this is NOT frame skipping). Can smooth out frame time "
|
||||
"fluctuations when the CPU/GPU are near maximum utilization, but makes frame pacing more inconsistent and can increase "
|
||||
"input lag. Helps when using frame generation on 25/30fps games."));
|
||||
dialog()->registerWidgetHelp(m_ui.advancedFrameDisplay, tr("Advanced Frame Display"), tr("Unchecked"),
|
||||
tr("Displays the newest frame immediately at the beginning of the "
|
||||
"frame raster time, instead of at the end. Can reduce perceived "
|
||||
"input lag, but may cause problems with some games, such as "
|
||||
"Soulcalibur II and Baldur's Gate Dark Alliance II."));
|
||||
dialog()->registerWidgetHelp(m_ui.manuallySetRealTimeClock, tr("Manually Set Real-Time Clock"), tr("Unchecked"),
|
||||
tr("Manually set a real-time clock to use for the virtual PlayStation 2 instead of using your OS' system clock."));
|
||||
dialog()->registerWidgetHelp(m_ui.rtcDateTime, tr("Real-Time Clock"), tr("Current date and time"),
|
||||
|
||||
@@ -263,6 +263,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="advancedFrameDisplay">
|
||||
<property name="text">
|
||||
<string>Advanced Frame Display</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
+1476
-1392
File diff suppressed because it is too large
Load Diff
@@ -766,6 +766,7 @@ struct Pcsx2Config
|
||||
DisableFramebufferFetch : 1,
|
||||
DisableVertexShaderExpand : 1,
|
||||
SkipDuplicateFrames : 1,
|
||||
AdvancedFrameDisplay : 1,
|
||||
OsdShowSpeed : 1,
|
||||
OsdShowFPS : 1,
|
||||
OsdShowVPS : 1,
|
||||
@@ -825,6 +826,7 @@ struct Pcsx2Config
|
||||
SaveDrawStats : 1,
|
||||
SaveFrameStats : 1,
|
||||
SaveHWConfig : 1,
|
||||
DumpReplayUseFrameRange : 1,
|
||||
DumpReplaceableTextures : 1,
|
||||
DumpReplaceableMipmaps : 1,
|
||||
DumpTexturesWithFMVActive : 1,
|
||||
@@ -913,6 +915,10 @@ struct Pcsx2Config
|
||||
int SaveFrameStart = 0;
|
||||
int SaveFrameCount = -1;
|
||||
int SaveFrameBy = 1;
|
||||
int DumpReplayLoopCount = 0;
|
||||
int DumpReplayFrameStart = 0;
|
||||
int DumpReplayFrameEnd = 0;
|
||||
u32 SavedMetricsCaptureSeconds = 10;
|
||||
|
||||
s8 ExclusiveFullscreenControl = -1;
|
||||
GSScreenshotSize ScreenshotSize = GSScreenshotSize::WindowResolution;
|
||||
|
||||
+11
-2
@@ -494,9 +494,12 @@ static __fi void VSyncStart(u64 sCycle)
|
||||
|
||||
// Don't bother throttling if we're going to pause.
|
||||
if (!VMManager::Internal::IsExecutionInterrupted())
|
||||
VMManager::Internal::Throttle();
|
||||
VMManager::Internal::Throttle(true);
|
||||
|
||||
gsPostVsyncStart(); // MUST be after framelimit; doing so before causes funk with frame times!
|
||||
if (!EmuConfig.GS.AdvancedFrameDisplay)
|
||||
{
|
||||
gsPostVsyncStart(); // MUST be after framelimit; doing so before causes funk with frame times!
|
||||
}
|
||||
|
||||
// Poll input after MTGS frame push, just in case it has to stall to catch up.
|
||||
VMManager::Internal::PollInputOnCPUThread();
|
||||
@@ -566,6 +569,12 @@ static __fi void GSVSync()
|
||||
static __fi void VSyncEnd(u64 sCycle)
|
||||
{
|
||||
EECNT_LOG(" ================ EE COUNTER VSYNC END (frame: %d) ================", g_FrameCount);
|
||||
VMManager::Internal::Throttle(false);
|
||||
|
||||
if (EmuConfig.GS.AdvancedFrameDisplay)
|
||||
{
|
||||
gsPostVsyncStart();
|
||||
}
|
||||
|
||||
g_FrameCount++;
|
||||
if (!GSSMODE1reg.SINT)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "GS/GSPerfMon.h"
|
||||
#include "GS/GSUtil.h"
|
||||
#include "GS/MultiISA.h"
|
||||
#include "GS/GSPerfMon.h"
|
||||
#include "Host.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "MTGS.h"
|
||||
@@ -491,6 +492,23 @@ void GSStopGSDump()
|
||||
g_gs_renderer->StopGSDump();
|
||||
}
|
||||
|
||||
void GSStartSavingMetrics(u32 seconds)
|
||||
{
|
||||
if (g_gs_renderer)
|
||||
g_gs_renderer->StartSavingMetrics(seconds);
|
||||
}
|
||||
|
||||
void GSDumpSavedMetrics()
|
||||
{
|
||||
if (g_gs_renderer)
|
||||
g_gs_renderer->DumpSavedMetrics();
|
||||
}
|
||||
|
||||
bool GSIsSavingMetrics()
|
||||
{
|
||||
return g_gs_renderer && g_gs_renderer->IsSavingMetrics();
|
||||
}
|
||||
|
||||
bool GSBeginCapture(std::string filename)
|
||||
{
|
||||
if (g_gs_renderer)
|
||||
@@ -565,6 +583,11 @@ void GSSetVSyncMode(GSVSyncMode mode, bool allow_present_throttle)
|
||||
g_gs_device->SetVSyncMode(mode, allow_present_throttle);
|
||||
}
|
||||
|
||||
void GSResetStats()
|
||||
{
|
||||
g_perfmon.Reset();
|
||||
}
|
||||
|
||||
bool GSWantsExclusiveFullscreen()
|
||||
{
|
||||
if (!g_gs_device || !g_gs_device->SupportsExclusiveFullscreen())
|
||||
@@ -1226,6 +1249,24 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphic
|
||||
GSStopGSDump();
|
||||
});
|
||||
}},
|
||||
{"GSStartSavingMetricsVariableFrames", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Start Saving Performance Metrics (Press & Hold)"),
|
||||
[](s32 pressed) {
|
||||
MTGS::RunOnGSThread([pressed]() {
|
||||
if (pressed > 0)
|
||||
GSStartSavingMetrics(UINT32_MAX);
|
||||
else
|
||||
GSDumpSavedMetrics();
|
||||
});
|
||||
}},
|
||||
{"GSStartSavingMetricsFixedFrames", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Start Saving Performance Metrics (Capture Timer)"),
|
||||
[](s32 pressed) {
|
||||
MTGS::RunOnGSThread([pressed]() {
|
||||
if (pressed > 0 && !GSIsSavingMetrics())
|
||||
GSStartSavingMetrics(GSConfig.SavedMetricsCaptureSeconds);
|
||||
});
|
||||
}},
|
||||
{"ToggleSoftwareRendering", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Toggle Software Rendering"),
|
||||
[](s32 pressed) {
|
||||
|
||||
@@ -76,6 +76,9 @@ std::string GSGetBaseSnapshotFilename();
|
||||
std::string GSGetBaseVideoFilename();
|
||||
void GSQueueSnapshot(const std::string& path, u32 gsdump_frames = 0);
|
||||
void GSStopGSDump();
|
||||
void GSStartSavingMetrics(float time);
|
||||
void GSDumpSavedMetrics();
|
||||
bool GSIsSavingMetrics();
|
||||
bool GSBeginCapture(std::string filename);
|
||||
void GSEndCapture();
|
||||
void GSPresentCurrentFrame();
|
||||
@@ -86,6 +89,7 @@ bool GSHasDisplayWindow();
|
||||
void GSResizeDisplayWindow(u32 width, u32 height, float scale);
|
||||
void GSUpdateDisplayWindow();
|
||||
void GSSetVSyncMode(GSVSyncMode mode, bool allow_present_throttle);
|
||||
void GSResetStats();
|
||||
|
||||
GSRendererType GSGetCurrentRenderer();
|
||||
bool GSIsHardwareRenderer();
|
||||
|
||||
@@ -105,7 +105,6 @@ GSState::GSState()
|
||||
s_n = 0;
|
||||
s_transfer_n = 0;
|
||||
|
||||
|
||||
memset(&m_v, 0, sizeof(m_v));
|
||||
memset(m_mem.m_vm8, 0, m_mem.m_vmsize);
|
||||
|
||||
@@ -2504,6 +2503,11 @@ u32 GSState::CalcMask(int exp, int max_exp)
|
||||
return (1 << std::min(amount, 23)) - 1;
|
||||
}
|
||||
|
||||
void GSState::IncDraw()
|
||||
{
|
||||
s_n++;
|
||||
}
|
||||
|
||||
void GSState::FlushPrim()
|
||||
{
|
||||
if (m_index->tail > 0)
|
||||
@@ -2526,7 +2530,7 @@ void GSState::FlushPrim()
|
||||
GSVertex buff[2];
|
||||
GSVertexBuff& vtx_buff = *m_vertex;
|
||||
GSIndexBuff& idx_buff = *m_index;
|
||||
s_n++;
|
||||
IncDraw();
|
||||
|
||||
const u32 head = vtx_buff.head;
|
||||
const u32 tail = vtx_buff.tail;
|
||||
|
||||
+5
-3
@@ -318,9 +318,11 @@ public:
|
||||
static u64 s_last_transfer_draw_n;
|
||||
static u64 s_transfer_n;
|
||||
|
||||
GSPerfMon m_perfmon_frame; // Track stat across a frame.
|
||||
GSPerfMon m_perfmon_draw; // Track stat across a draw.
|
||||
|
||||
GSPerfMon m_perfmon_frame; // Track stats across a frame.
|
||||
GSPerfMon m_perfmon_draw; // Track stats across a draw.
|
||||
|
||||
void IncDraw();
|
||||
|
||||
static constexpr u32 STATE_VERSION = 9;
|
||||
|
||||
#define PRIM_REG_MASK 0x7FF
|
||||
|
||||
@@ -150,7 +150,7 @@ bool GSRenderer::Merge(int field)
|
||||
}
|
||||
}
|
||||
|
||||
s_n++;
|
||||
IncDraw();
|
||||
|
||||
GSVector4 src_gs_read[2] = {};
|
||||
GSVector4 dst[3] = {};
|
||||
@@ -524,6 +524,9 @@ bool GSRenderer::BeginPresentFrame(bool frame_skip)
|
||||
{
|
||||
Host::BeginPresentFrame();
|
||||
|
||||
if (GSDumpReplayer::IsReplayingDump())
|
||||
GSDumpReplayer::UpdateGSStats();
|
||||
|
||||
const GSDevice::PresentResult res = g_gs_device->BeginPresent(frame_skip);
|
||||
if (res == GSDevice::PresentResult::FrameSkipped)
|
||||
{
|
||||
@@ -805,6 +808,10 @@ void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
|
||||
}
|
||||
}
|
||||
|
||||
// metrics
|
||||
if (m_saving_metrics && !PerformanceMetrics::IsSavingMetrics())
|
||||
DumpSavedMetrics();
|
||||
|
||||
// capture
|
||||
if (GSCapture::IsCapturingVideo())
|
||||
{
|
||||
@@ -953,6 +960,29 @@ void GSRenderer::StopGSDump()
|
||||
m_dump_frames = 0;
|
||||
}
|
||||
|
||||
void GSRenderer::StartSavingMetrics(u32 seconds)
|
||||
{
|
||||
m_saving_metrics = true;
|
||||
PerformanceMetrics::StartSavingMetrics(seconds);
|
||||
Host::AddKeyedOSDMessage("GSMetrics",
|
||||
fmt::format(TRANSLATE_FS("GS", "Started saving performance metrics{}"),
|
||||
(0 < seconds && seconds < UINT32_MAX) ? fmt::format(" ({} seconds)", seconds) : ""),
|
||||
Host::OSD_INFO_DURATION);
|
||||
}
|
||||
|
||||
void GSRenderer::DumpSavedMetrics()
|
||||
{
|
||||
m_saving_metrics = false;
|
||||
PerformanceMetrics::DumpSavedMetrics();
|
||||
Host::AddKeyedOSDMessage("GSMetrics", fmt::format(TRANSLATE_FS("GS", "Logging saved performance metrics")),
|
||||
Host::OSD_INFO_DURATION);
|
||||
}
|
||||
|
||||
bool GSRenderer::IsSavingMetrics()
|
||||
{
|
||||
return m_saving_metrics;
|
||||
}
|
||||
|
||||
void GSRenderer::PresentCurrentFrame()
|
||||
{
|
||||
if (BeginPresentFrame(false))
|
||||
|
||||
@@ -19,6 +19,7 @@ private:
|
||||
std::string m_snapshot;
|
||||
u32 m_dump_frames = 0;
|
||||
u32 m_skipped_duplicate_frames = 0;
|
||||
bool m_saving_metrics = false;
|
||||
|
||||
// Tracking draw counters for idle frame detection.
|
||||
u64 m_last_draw_n = 0;
|
||||
@@ -56,6 +57,9 @@ public:
|
||||
|
||||
void QueueSnapshot(const std::string& path, const u32 gsdump_frames);
|
||||
void StopGSDump();
|
||||
void StartSavingMetrics(u32 seconds);
|
||||
void DumpSavedMetrics();
|
||||
bool IsSavingMetrics();
|
||||
void PresentCurrentFrame();
|
||||
bool BeginCapture(std::string filename, const GSVector2i& size = GSVector2i(0, 0));
|
||||
void EndCapture();
|
||||
|
||||
@@ -289,16 +289,12 @@ bool GSDevice12::CreateDevice(u32& vendor_id)
|
||||
|
||||
// Create the actual device.
|
||||
// Intel Haswell DX12 support is specific:
|
||||
// Newerest drivers have dx12 support disabled so the last driver to support dx12 is 15.40.42.5063.
|
||||
// Newer drivers have dx12 support disabled so the last driver to support dx12 is 15.40.42.5063.
|
||||
// Shader cache must be also disabled, and make sure Debug Device option is disabled as well.
|
||||
// Let's enable it on dev/debug for testing purposes so we don't have to change this all the time.
|
||||
// Let's enable it for testing purposes so we don't have to change this all the time, and
|
||||
// might be handy for the tweakers that want to run dx12.
|
||||
// TODO: Find out the status of Broadwell.
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
hr = D3D12CreateDevice(m_adapter.get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
|
||||
#else
|
||||
const bool isIntel = (vendor_id == 0x163C || vendor_id == 0x8086 || vendor_id == 0x8087);
|
||||
hr = D3D12CreateDevice(m_adapter.get(), isIntel ? D3D_FEATURE_LEVEL_12_0 : D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
|
||||
#endif
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
@@ -488,36 +484,8 @@ void GSDevice12::MoveToNextCommandList()
|
||||
if (res.sampler_allocator.ShouldReset())
|
||||
res.sampler_allocator.Reset();
|
||||
|
||||
if (res.has_timestamp_query)
|
||||
{
|
||||
// readback timestamp from the last time this cmdlist was used.
|
||||
// we don't need to worry about disjoint in dx12, the frequency is reliable within a single cmdlist.
|
||||
const u32 offset = (m_current_command_list * (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST));
|
||||
const D3D12_RANGE read_range = {offset, offset + (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST)};
|
||||
void* map;
|
||||
HRESULT hr = m_timestamp_query_buffer->Map(0, &read_range, &map);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
u64 timestamps[2];
|
||||
std::memcpy(timestamps, static_cast<const u8*>(map) + offset, sizeof(timestamps));
|
||||
m_accumulated_gpu_time +=
|
||||
static_cast<float>(static_cast<double>(timestamps[1] - timestamps[0]) / m_timestamp_frequency);
|
||||
|
||||
const D3D12_RANGE write_range = {};
|
||||
m_timestamp_query_buffer->Unmap(0, &write_range);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Warning("D3D12: Map() for timestamp query failed: %08X", hr);
|
||||
}
|
||||
}
|
||||
|
||||
res.has_timestamp_query = m_gpu_timing_enabled;
|
||||
if (m_gpu_timing_enabled)
|
||||
{
|
||||
res.command_lists[1].list4->EndQuery(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
|
||||
m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST);
|
||||
}
|
||||
ReadGPUTiming();
|
||||
StartGPUTiming();
|
||||
|
||||
if (res.pipeline_statistics_query == QueryState::Ready)
|
||||
{
|
||||
@@ -587,15 +555,7 @@ bool GSDevice12::ExecuteCommandList(WaitType wait_for_completion)
|
||||
m_vertex_constant_buffer.FlushMemory();
|
||||
m_pixel_constant_buffer.FlushMemory();
|
||||
|
||||
if (res.has_timestamp_query)
|
||||
{
|
||||
// write the timestamp back at the end of the cmdlist
|
||||
res.command_lists[1].list4->EndQuery(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
|
||||
(m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST) + 1);
|
||||
res.command_lists[1].list4->ResolveQueryData(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
|
||||
m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST, NUM_TIMESTAMP_QUERIES_PER_CMDLIST,
|
||||
m_timestamp_query_buffer.get(), m_current_command_list * (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST));
|
||||
}
|
||||
EndGPUTiming();
|
||||
|
||||
if ((res.pipeline_statistics_query == QueryState::Querying) || (res.pipeline_statistics_query == QueryState::Ready))
|
||||
{
|
||||
@@ -857,6 +817,64 @@ bool GSDevice12::SetGPUPipelineStatisticsEnabled(bool enabled)
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSDevice12::StartGPUTiming()
|
||||
{
|
||||
if (m_gpu_timing_enabled)
|
||||
{
|
||||
CommandListResources& res = m_command_lists[m_current_command_list];
|
||||
res.command_lists[1].list4->EndQuery(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
|
||||
m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST);
|
||||
res.timestamp_query_state = QueryState::Querying;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice12::EndGPUTiming()
|
||||
{
|
||||
CommandListResources& res = m_command_lists[m_current_command_list];
|
||||
if (res.timestamp_query_state == QueryState::Querying)
|
||||
{
|
||||
// write the timestamp back at the end of the cmdlist
|
||||
if (InRenderPass())
|
||||
EndRenderPass(); // Can't end query in a render pass
|
||||
res.command_lists[1].list4->EndQuery(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
|
||||
(m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST) + 1);
|
||||
res.command_lists[1].list4->ResolveQueryData(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
|
||||
m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST, NUM_TIMESTAMP_QUERIES_PER_CMDLIST,
|
||||
m_timestamp_query_buffer.get(), m_current_command_list * (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST));
|
||||
res.timestamp_query_state = QueryState::Ready;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDevice12::ReadGPUTiming()
|
||||
{
|
||||
CommandListResources& res = m_command_lists[m_current_command_list];
|
||||
if (res.timestamp_query_state == QueryState::Ready)
|
||||
{
|
||||
// readback timestamp from the last time this cmdlist was used.
|
||||
// we don't need to worry about disjoint in dx12, the frequency is reliable within a single cmdlist.
|
||||
const u32 offset = (m_current_command_list * (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST));
|
||||
const D3D12_RANGE read_range = { offset, offset + (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST) };
|
||||
void* map;
|
||||
HRESULT hr = m_timestamp_query_buffer->Map(0, &read_range, &map);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
u64 timestamps[2];
|
||||
std::memcpy(timestamps, static_cast<const u8*>(map) + offset, sizeof(timestamps));
|
||||
m_accumulated_gpu_time +=
|
||||
static_cast<float>(static_cast<double>(timestamps[1] - timestamps[0]) / m_timestamp_frequency);
|
||||
|
||||
const D3D12_RANGE write_range = {};
|
||||
m_timestamp_query_buffer->Unmap(0, &write_range);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Warning("D3D12: Map() for timestamp query failed: %08X", hr);
|
||||
}
|
||||
|
||||
res.timestamp_query_state = QueryState::None;
|
||||
}
|
||||
}
|
||||
|
||||
bool GSDevice12::AllocatePreinitializedGPUBuffer(u32 size, ID3D12Resource** gpu_buffer,
|
||||
D3D12MA::Allocation** gpu_allocation, const std::function<void(void*)>& fill_callback)
|
||||
{
|
||||
|
||||
@@ -191,7 +191,6 @@ public:
|
||||
void UploadIndices(D3D12StreamBuffer& buffer, const void* index, size_t count);
|
||||
|
||||
private:
|
||||
// For pipeline statistics
|
||||
enum class QueryState
|
||||
{
|
||||
None,
|
||||
@@ -209,7 +208,7 @@ private:
|
||||
std::vector<std::pair<D3D12DescriptorHeapManager&, u32>> pending_descriptors;
|
||||
u64 ready_fence_value = 0;
|
||||
bool init_command_list_used = false;
|
||||
bool has_timestamp_query = false;
|
||||
QueryState timestamp_query_state = QueryState::None;
|
||||
QueryState pipeline_statistics_query = QueryState::None;
|
||||
};
|
||||
|
||||
@@ -524,6 +523,9 @@ public:
|
||||
void EndPresent() override;
|
||||
|
||||
bool SetGPUTimingEnabled(bool enabled) override;
|
||||
void StartGPUTiming();
|
||||
void EndGPUTiming();
|
||||
void ReadGPUTiming();
|
||||
float GetAndResetAccumulatedGPUTime() override;
|
||||
|
||||
bool SetGPUPipelineStatisticsEnabled(bool enabled) override;
|
||||
|
||||
@@ -607,20 +607,6 @@ bool GSHwHack::GSC_TalesOfLegendia(GSRendererHW& r, int& skip)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_UltramanFightingEvolution(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
{
|
||||
if (!s_nativeres && RTME && RFBP == 0x2a00 && RFPSM == PSMZ24 && RTBP0 == 0x1c00 && RTPSM == PSMZ24)
|
||||
{
|
||||
// Don't enable hack on native res if crc is below aggressive.
|
||||
skip = 5; // blur
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_TalesofSymphonia(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
@@ -1468,9 +1454,6 @@ const GSHwHack::Entry<GSRendererHW::GSC_Ptr> GSHwHack::s_get_skip_count_function
|
||||
|
||||
// Depth Issue
|
||||
CRC_F(GSC_BurnoutGames),
|
||||
|
||||
// Upscaling hacks
|
||||
CRC_F(GSC_UltramanFightingEvolution),
|
||||
};
|
||||
|
||||
const GSHwHack::Entry<GSRendererHW::OI_Ptr> GSHwHack::s_before_draw_functions[] = {
|
||||
|
||||
@@ -18,7 +18,6 @@ public:
|
||||
static bool GSC_BlackAndBurnoutSky(GSRendererHW& r, int& skip);
|
||||
static bool GSC_MidnightClub3(GSRendererHW& r, int& skip);
|
||||
static bool GSC_TalesOfLegendia(GSRendererHW& r, int& skip);
|
||||
static bool GSC_UltramanFightingEvolution(GSRendererHW& r, int& skip);
|
||||
static bool GSC_TalesofSymphonia(GSRendererHW& r, int& skip);
|
||||
static bool GSC_UrbanReign(GSRendererHW& r, int& skip);
|
||||
static bool GSC_BlueTongueGames(GSRendererHW& r, int& skip);
|
||||
|
||||
@@ -1153,6 +1153,77 @@ bool GSDeviceVK::SetGPUPipelineStatisticsEnabled(bool enabled)
|
||||
return (enabled == m_gpu_pipeline_statistics_enabled);
|
||||
}
|
||||
|
||||
void GSDeviceVK::StartGPUTiming(u32 index)
|
||||
{
|
||||
if (m_gpu_timing_enabled || m_spin_timer)
|
||||
{
|
||||
FrameResources& resources = m_frame_resources[index];
|
||||
vkCmdResetQueryPool(resources.command_buffers[1], m_timestamp_query_pool, index * 2, 2);
|
||||
vkCmdWriteTimestamp(
|
||||
resources.command_buffers[1], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, m_timestamp_query_pool, index * 2);
|
||||
resources.timestamp_query_state = QueryState::Querying;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceVK::EndGPUTiming(u32 index)
|
||||
{
|
||||
FrameResources& resources = m_frame_resources[index];
|
||||
|
||||
const bool wants_timestamp = m_gpu_timing_enabled || m_spin_timer;
|
||||
|
||||
if (wants_timestamp && resources.timestamp_query_state == QueryState::Querying)
|
||||
{
|
||||
vkCmdWriteTimestamp(m_current_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, m_timestamp_query_pool,
|
||||
m_current_frame * 2 + 1);
|
||||
resources.timestamp_query_state = QueryState::Ready;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceVK::ReadGPUTiming(u32 index)
|
||||
{
|
||||
FrameResources& resources = m_frame_resources[index];
|
||||
|
||||
const bool wants_timestamps = m_gpu_timing_enabled || resources.spin_id >= 0;
|
||||
|
||||
if (wants_timestamps && resources.timestamp_query_state == QueryState::Ready)
|
||||
{
|
||||
std::array<u64, 2> timestamps;
|
||||
const VkResult res =
|
||||
vkGetQueryPoolResults(m_device, m_timestamp_query_pool, index * 2, static_cast<u32>(timestamps.size()),
|
||||
sizeof(u64) * timestamps.size(), timestamps.data(), sizeof(u64), VK_QUERY_RESULT_64_BIT);
|
||||
if (res == VK_SUCCESS)
|
||||
{
|
||||
// if we didn't write the timestamp at the start of the cmdbuffer (just enabled timing), the first TS will be zero
|
||||
if (timestamps[0] > 0 && m_gpu_timing_enabled)
|
||||
{
|
||||
const double ns_diff =
|
||||
(timestamps[1] - timestamps[0]) * static_cast<double>(m_device_properties.limits.timestampPeriod);
|
||||
m_accumulated_gpu_time += ns_diff / 1000000.0;
|
||||
}
|
||||
if (resources.spin_id >= 0)
|
||||
{
|
||||
if (m_optional_extensions.vk_ext_calibrated_timestamps && timestamps[1] > 0)
|
||||
{
|
||||
const u64 end = timestamps[1] * m_spin_timestamp_scale + m_spin_timestamp_offset;
|
||||
m_spin_manager.DrawCompleted(resources.spin_id, resources.submit_timestamp, end);
|
||||
}
|
||||
else if (!m_optional_extensions.vk_ext_calibrated_timestamps && timestamps[0] > 0)
|
||||
{
|
||||
const u64 begin = timestamps[0] * m_spin_timestamp_scale;
|
||||
const u64 end = timestamps[1] * m_spin_timestamp_scale;
|
||||
m_spin_manager.DrawCompleted(resources.spin_id, begin, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkGetQueryPoolResults failed: ");
|
||||
}
|
||||
|
||||
resources.timestamp_query_state = QueryState::None;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceVK::ScanForCommandBufferCompletion()
|
||||
{
|
||||
for (u32 check_index = (m_current_frame + 1) % NUM_COMMAND_BUFFERS; check_index != m_current_frame;
|
||||
@@ -1222,12 +1293,7 @@ void GSDeviceVK::SubmitCommandBuffer(VKSwapChain* present_swap_chain)
|
||||
}
|
||||
}
|
||||
|
||||
bool wants_timestamp = m_gpu_timing_enabled || m_spin_timer;
|
||||
if (wants_timestamp && resources.timestamp_written)
|
||||
{
|
||||
vkCmdWriteTimestamp(m_current_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, m_timestamp_query_pool,
|
||||
m_current_frame * 2 + 1);
|
||||
}
|
||||
EndGPUTiming(m_current_frame);
|
||||
|
||||
if (resources.pipeline_statistics_query == QueryState::Querying)
|
||||
{
|
||||
@@ -1363,43 +1429,7 @@ void GSDeviceVK::CommandBufferCompleted(u32 index)
|
||||
it();
|
||||
resources.cleanup_resources.clear();
|
||||
|
||||
bool wants_timestamps = m_gpu_timing_enabled || resources.spin_id >= 0;
|
||||
|
||||
if (wants_timestamps && resources.timestamp_written)
|
||||
{
|
||||
std::array<u64, 2> timestamps;
|
||||
VkResult res =
|
||||
vkGetQueryPoolResults(m_device, m_timestamp_query_pool, index * 2, static_cast<u32>(timestamps.size()),
|
||||
sizeof(u64) * timestamps.size(), timestamps.data(), sizeof(u64), VK_QUERY_RESULT_64_BIT);
|
||||
if (res == VK_SUCCESS)
|
||||
{
|
||||
// if we didn't write the timestamp at the start of the cmdbuffer (just enabled timing), the first TS will be zero
|
||||
if (timestamps[0] > 0 && m_gpu_timing_enabled)
|
||||
{
|
||||
const double ns_diff =
|
||||
(timestamps[1] - timestamps[0]) * static_cast<double>(m_device_properties.limits.timestampPeriod);
|
||||
m_accumulated_gpu_time += ns_diff / 1000000.0;
|
||||
}
|
||||
if (resources.spin_id >= 0)
|
||||
{
|
||||
if (m_optional_extensions.vk_ext_calibrated_timestamps && timestamps[1] > 0)
|
||||
{
|
||||
u64 end = timestamps[1] * m_spin_timestamp_scale + m_spin_timestamp_offset;
|
||||
m_spin_manager.DrawCompleted(resources.spin_id, resources.submit_timestamp, end);
|
||||
}
|
||||
else if (!m_optional_extensions.vk_ext_calibrated_timestamps && timestamps[0] > 0)
|
||||
{
|
||||
u64 begin = timestamps[0] * m_spin_timestamp_scale;
|
||||
u64 end = timestamps[1] * m_spin_timestamp_scale;
|
||||
m_spin_manager.DrawCompleted(resources.spin_id, begin, end);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkGetQueryPoolResults failed: ");
|
||||
}
|
||||
}
|
||||
ReadGPUTiming(index);
|
||||
}
|
||||
|
||||
void GSDeviceVK::MoveToNextCommandBuffer()
|
||||
@@ -1434,13 +1464,7 @@ void GSDeviceVK::ActivateCommandBuffer(u32 index)
|
||||
if (res != VK_SUCCESS)
|
||||
LOG_VULKAN_ERROR(res, "vkBeginCommandBuffer failed: ");
|
||||
|
||||
bool wants_timestamp = m_gpu_timing_enabled || m_spin_timer;
|
||||
if (wants_timestamp)
|
||||
{
|
||||
vkCmdResetQueryPool(resources.command_buffers[1], m_timestamp_query_pool, index * 2, 2);
|
||||
vkCmdWriteTimestamp(
|
||||
resources.command_buffers[1], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, m_timestamp_query_pool, index * 2);
|
||||
}
|
||||
StartGPUTiming(index);
|
||||
|
||||
if (resources.pipeline_statistics_query == QueryState::Ready)
|
||||
{
|
||||
@@ -1471,7 +1495,6 @@ void GSDeviceVK::ActivateCommandBuffer(u32 index)
|
||||
|
||||
resources.fence_counter = m_next_fence_counter++;
|
||||
resources.init_buffer_used = false;
|
||||
resources.timestamp_written = wants_timestamp;
|
||||
|
||||
m_current_frame = index;
|
||||
m_current_command_buffer = resources.command_buffers[1];
|
||||
|
||||
@@ -209,7 +209,6 @@ private:
|
||||
void CalibrateSpinTimestamp();
|
||||
u64 GetCPUTimestamp();
|
||||
|
||||
// For pipeline statistics
|
||||
enum class QueryState
|
||||
{
|
||||
None,
|
||||
@@ -228,7 +227,7 @@ private:
|
||||
u32 submit_timestamp = 0;
|
||||
bool init_buffer_used = false;
|
||||
bool needs_fence_wait = false;
|
||||
bool timestamp_written = false;
|
||||
QueryState timestamp_query_state = QueryState::None;
|
||||
QueryState pipeline_statistics_query = QueryState::None;
|
||||
|
||||
std::vector<std::function<void()>> cleanup_resources;
|
||||
@@ -575,6 +574,9 @@ public:
|
||||
bool IsPresenting() const;
|
||||
|
||||
bool SetGPUTimingEnabled(bool enabled) override;
|
||||
void StartGPUTiming(u32 index);
|
||||
void EndGPUTiming(u32 index);
|
||||
void ReadGPUTiming(u32 index);
|
||||
float GetAndResetAccumulatedGPUTime() override;
|
||||
|
||||
bool SetGPUPipelineStatisticsEnabled(bool enabled) override;
|
||||
|
||||
+164
-11
@@ -1,6 +1,8 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "PerformanceMetrics.h"
|
||||
#include "GS/GSPerfMon.h"
|
||||
#include "GS.h"
|
||||
#include "GS/GSLzma.h"
|
||||
#include "GSDumpReplayer.h"
|
||||
@@ -27,6 +29,7 @@
|
||||
#include "common/Timer.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cinttypes>
|
||||
|
||||
static void GSDumpReplayerCpuReserve();
|
||||
static void GSDumpReplayerCpuShutdown();
|
||||
@@ -46,6 +49,19 @@ static bool s_needs_state_loaded = false;
|
||||
static u64 s_frame_ticks = 0;
|
||||
static u64 s_next_frame_time = 0;
|
||||
static bool s_is_dump_runner = false;
|
||||
static bool s_dump_perf_metrics = true;
|
||||
|
||||
static bool s_use_frame_range = false;
|
||||
static bool s_init_frame_range = false;
|
||||
static u32 s_frame_start = 0;
|
||||
static u32 s_frame_end = 0;
|
||||
static u32 s_frame_start_packet = 0;
|
||||
static u32 s_frame_end_packet = 0;
|
||||
|
||||
static GSPerfMon s_total_gs_stats;
|
||||
static GSPerfMon s_last_g_perfmon;
|
||||
static u64 s_total_frames = 0;
|
||||
static u64 s_total_drawn_frames = 0;
|
||||
|
||||
R5900cpu GSDumpReplayerCpu = {
|
||||
GSDumpReplayerCpuReserve,
|
||||
@@ -70,9 +86,10 @@ bool GSDumpReplayer::IsRunner()
|
||||
return s_is_dump_runner;
|
||||
}
|
||||
|
||||
void GSDumpReplayer::SetIsDumpRunner(bool is_runner)
|
||||
void GSDumpReplayer::SetIsDumpRunner(bool is_runner, bool dump_perf)
|
||||
{
|
||||
s_is_dump_runner = is_runner;
|
||||
s_dump_perf_metrics = dump_perf;
|
||||
}
|
||||
|
||||
void GSDumpReplayer::SetLoopCount(s32 loop_count)
|
||||
@@ -85,6 +102,13 @@ int GSDumpReplayer::GetLoopCount()
|
||||
return s_dump_loop_count;
|
||||
}
|
||||
|
||||
void GSDumpReplayer::SetFrameRange(bool use, u32 start, u32 end)
|
||||
{
|
||||
s_use_frame_range = use;
|
||||
s_frame_start = start;
|
||||
s_frame_end = end;
|
||||
}
|
||||
|
||||
bool GSDumpReplayer::Initialize(const char* filename, Error* error)
|
||||
{
|
||||
Common::Timer timer;
|
||||
@@ -145,6 +169,8 @@ void GSDumpReplayer::Shutdown()
|
||||
{
|
||||
Console.WriteLn("(GSDumpReplayer) Shutting down.");
|
||||
|
||||
DumpStats();
|
||||
|
||||
Cpu = nullptr;
|
||||
psxCpu = nullptr;
|
||||
CpuVU0 = nullptr;
|
||||
@@ -196,6 +222,13 @@ void GSDumpReplayerCpuReset()
|
||||
s_needs_state_loaded = true;
|
||||
s_current_packet = 0;
|
||||
s_dump_frame_number = 0;
|
||||
s_total_gs_stats.Reset();
|
||||
s_last_g_perfmon.Reset();
|
||||
s_init_frame_range = false;
|
||||
s_frame_start_packet = 0;
|
||||
s_frame_end_packet = 0;
|
||||
s_total_frames = 0;
|
||||
s_total_drawn_frames = 0;
|
||||
}
|
||||
|
||||
static void GSDumpReplayerLoadInitialState()
|
||||
@@ -256,17 +289,10 @@ static void GSDumpReplayerFrameLimit()
|
||||
s_next_frame_time = std::max(now, s_next_frame_time + s_frame_ticks);
|
||||
}
|
||||
|
||||
void GSDumpReplayerCpuStep()
|
||||
void AdvanceNextLoop()
|
||||
{
|
||||
if (s_needs_state_loaded)
|
||||
{
|
||||
GSDumpReplayerLoadInitialState();
|
||||
s_needs_state_loaded = false;
|
||||
}
|
||||
|
||||
const GSDumpFile::GSData& packet = s_dump_file->GetPackets()[s_current_packet];
|
||||
s_current_packet = (s_current_packet + 1) % static_cast<u32>(s_dump_file->GetPackets().size());
|
||||
if (s_current_packet == 0)
|
||||
const bool end_of_dump = (s_current_packet == static_cast<u32>(s_dump_file->GetPackets().size()));
|
||||
if (end_of_dump || (s_init_frame_range && s_current_packet > s_frame_end_packet))
|
||||
{
|
||||
s_dump_frame_number = 0;
|
||||
if (s_dump_loop_count > 0)
|
||||
@@ -277,6 +303,55 @@ void GSDumpReplayerCpuStep()
|
||||
s_dump_running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateFrameRangePacketsOnVSync()
|
||||
{
|
||||
if (s_use_frame_range && !s_init_frame_range)
|
||||
{
|
||||
if (s_dump_frame_number == s_frame_start)
|
||||
{
|
||||
// +1 since the current packet is the previous frame VSync packet.
|
||||
s_frame_start_packet = s_current_packet + 1;
|
||||
}
|
||||
else if (s_dump_frame_number >= s_frame_end && s_frame_end > s_frame_start)
|
||||
{
|
||||
// Current packet is the VSync packet of the last frame we want to loop over.
|
||||
s_frame_end_packet = s_current_packet;
|
||||
s_init_frame_range = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckFrameRange()
|
||||
{
|
||||
if (s_init_frame_range)
|
||||
{
|
||||
if (s_current_packet > s_frame_end_packet || s_current_packet < s_frame_start_packet)
|
||||
{
|
||||
s_dump_frame_number = s_frame_start;
|
||||
s_current_packet = s_frame_start_packet;
|
||||
}
|
||||
}
|
||||
else if (s_current_packet == static_cast<u32>(s_dump_file->GetPackets().size()))
|
||||
{
|
||||
// This will run if the frame range goes past the end of the dump.
|
||||
s_frame_end_packet = s_current_packet;
|
||||
s_init_frame_range = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDumpReplayerCpuStep()
|
||||
{
|
||||
if (s_needs_state_loaded)
|
||||
{
|
||||
GSDumpReplayerLoadInitialState();
|
||||
s_needs_state_loaded = false;
|
||||
PerformanceMetrics::StartSavingMetrics(UINT32_MAX);
|
||||
}
|
||||
|
||||
// Get the next packet.
|
||||
const GSDumpFile::GSData& packet = s_dump_file->GetPackets()[s_current_packet];
|
||||
|
||||
switch (packet.id)
|
||||
{
|
||||
@@ -323,6 +398,7 @@ void GSDumpReplayerCpuStep()
|
||||
if (VMManager::Internal::IsExecutionInterrupted())
|
||||
GSDumpReplayerExitExecution();
|
||||
Host::PumpMessagesOnCPUThread();
|
||||
UpdateFrameRangePacketsOnVSync();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -343,6 +419,18 @@ void GSDumpReplayerCpuStep()
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Increment the packet counter.
|
||||
s_current_packet++;
|
||||
|
||||
// Increment the loop counter.
|
||||
AdvanceNextLoop();
|
||||
|
||||
// Adjust packet index based on the frame range we're replaying.
|
||||
CheckFrameRange();
|
||||
|
||||
// Loop packet index.
|
||||
s_current_packet %= static_cast<u32>(s_dump_file->GetPackets().size());
|
||||
}
|
||||
|
||||
void GSDumpReplayerCpuExecute()
|
||||
@@ -404,3 +492,68 @@ void GSDumpReplayer::RenderUI()
|
||||
|
||||
#undef DRAW_LINE
|
||||
}
|
||||
|
||||
static void UpdateSingleGSStat(GSPerfMon::counter_t counter)
|
||||
{
|
||||
const double curr = g_perfmon.GetCounter(counter);
|
||||
const double last = s_last_g_perfmon.GetCounter(counter);
|
||||
// GSPerfMon resets every 30 frames to zero.
|
||||
s_total_gs_stats.Put(counter, curr < last ? curr : (curr - last));
|
||||
};
|
||||
|
||||
void GSDumpReplayer::UpdateGSStats()
|
||||
{
|
||||
// Called on GS thread.
|
||||
if (GSIsHardwareRenderer())
|
||||
{
|
||||
const double last_draws = s_total_gs_stats.GetCounter(GSPerfMon::Draw);
|
||||
const double last_uploads = s_total_gs_stats.GetCounter(GSPerfMon::TextureUploads);
|
||||
|
||||
UpdateSingleGSStat(GSPerfMon::Draw);
|
||||
UpdateSingleGSStat(GSPerfMon::DrawCalls);
|
||||
UpdateSingleGSStat(GSPerfMon::RenderPasses);
|
||||
UpdateSingleGSStat(GSPerfMon::Barriers);
|
||||
UpdateSingleGSStat(GSPerfMon::TextureCopies);
|
||||
UpdateSingleGSStat(GSPerfMon::TextureUploads);
|
||||
UpdateSingleGSStat(GSPerfMon::Readbacks);
|
||||
UpdateSingleGSStat(GSPerfMon::TextureCopiesROV);
|
||||
UpdateSingleGSStat(GSPerfMon::DrawCallsROV);
|
||||
UpdateSingleGSStat(GSPerfMon::BarriersROV);
|
||||
|
||||
s_last_g_perfmon = g_perfmon;
|
||||
|
||||
const bool idle_frame = s_total_frames > 0 &&
|
||||
s_total_gs_stats.GetCounter(GSPerfMon::Draw) == last_draws &&
|
||||
s_total_gs_stats.GetCounter(GSPerfMon::TextureUploads) == last_uploads;
|
||||
|
||||
if (!idle_frame)
|
||||
s_total_drawn_frames++;
|
||||
|
||||
s_total_frames++;
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpStatAndAvg(const char* format, double stat)
|
||||
{
|
||||
Console.WriteLn(format, static_cast<u64>(stat), static_cast<u64>(std::ceil(stat / static_cast<double>(s_total_drawn_frames))));
|
||||
}
|
||||
|
||||
void GSDumpReplayer::DumpStats()
|
||||
{
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
Console.WriteLnFmt("======= HW STATISTICS FOR {} ({}) FRAMES ========", s_total_frames, s_total_drawn_frames);
|
||||
DumpStatAndAvg("@HWSTAT@ Draw Calls: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::DrawCalls));
|
||||
DumpStatAndAvg("@HWSTAT@ Render Passes: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::RenderPasses));
|
||||
DumpStatAndAvg("@HWSTAT@ Barriers: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::Barriers));
|
||||
DumpStatAndAvg("@HWSTAT@ Copies: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::TextureCopies));
|
||||
DumpStatAndAvg("@HWSTAT@ Uploads: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::TextureUploads));
|
||||
DumpStatAndAvg("@HWSTAT@ Readbacks: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::Readbacks));
|
||||
DumpStatAndAvg("@HWSTAT@ Copies (ROV): %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::TextureCopiesROV));
|
||||
DumpStatAndAvg("@HWSTAT@ Draws Calls (ROV): %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::DrawCallsROV));
|
||||
DumpStatAndAvg("@HWSTAT@ Barriers (ROV): %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::BarriersROV));
|
||||
if (s_dump_perf_metrics)
|
||||
PerformanceMetrics::DumpSavedMetrics();
|
||||
Console.WriteLnFmt("============================================");
|
||||
}
|
||||
@@ -16,7 +16,8 @@ namespace GSDumpReplayer
|
||||
void SetLoopCount(s32 loop_count = 0);
|
||||
int GetLoopCount();
|
||||
bool IsRunner();
|
||||
void SetIsDumpRunner(bool is_runner);
|
||||
void SetIsDumpRunner(bool is_runner, bool dump_perf = true);
|
||||
void SetFrameRange(bool use, u32 start, u32 end);
|
||||
|
||||
bool Initialize(const char* filename, Error* error = nullptr);
|
||||
bool ChangeDump(const char* filename);
|
||||
@@ -28,4 +29,8 @@ namespace GSDumpReplayer
|
||||
u32 GetFrameNumber();
|
||||
|
||||
void RenderUI();
|
||||
|
||||
void UpdateGSStats();
|
||||
|
||||
void DumpStats();
|
||||
} // namespace GSDumpReplayer
|
||||
|
||||
@@ -2658,6 +2658,13 @@ void FullscreenUI::DrawEmulationSettingsPage()
|
||||
SetSettingsChanged(bsi);
|
||||
}
|
||||
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_ANGLES_RIGHT, "Advanced Frame Display"),
|
||||
FSUI_CSTR("Displays the newest frame immediately at the beginning of the "
|
||||
"frame raster time, instead of at the end. Can reduce perceived "
|
||||
"input lag, but may cause problems with some games, such as "
|
||||
"Soulcalibur II and Baldur's Gate Dark Alliance II. "),
|
||||
"EmuCore/GS", "AdvancedFrameDisplay", false);
|
||||
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_ARROWS_SPIN, "Vertical Sync (VSync)"), FSUI_CSTR("Synchronizes frame presentation with host refresh."),
|
||||
"EmuCore/GS", "VsyncEnable", false);
|
||||
|
||||
@@ -5963,6 +5970,7 @@ TRANSLATE_NOOP("FullscreenUI", "Second of the minute (0-59).");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Frame Pacing / Latency Control");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Sets the number of frames which can be queued.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Synchronize EE and GS threads after each frame. Lowest input latency, but increases system requirements.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Displays the newest frame immediately at the beginning of the frame raster time, instead of at the end. Can reduce perceived input lag, but may cause problems with some games, such as Soulcalibur II and Baldur's Gate Dark Alliance II. ");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Synchronizes frame presentation with host refresh.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Speeds up emulation so that the guest refresh rate matches the host.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Disables PCSX2's internal frame timing, and uses host vsync instead.");
|
||||
@@ -6587,6 +6595,7 @@ TRANSLATE_NOOP("FullscreenUI", "Minute");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Second");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Maximum Frame Latency");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Optimal Frame Pacing");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Advanced Frame Display");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Vertical Sync (VSync)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Sync to Host Refresh Rate");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Use Host VSync Timing");
|
||||
|
||||
@@ -928,6 +928,8 @@ __ri void ImGuiManager::DrawSettingsOverlay(float scale, float margin, float spa
|
||||
APPEND("MTVU ");
|
||||
if (EmuConfig.GS.VsyncEnable)
|
||||
APPEND("VSYNC ");
|
||||
if (EmuConfig.GS.AdvancedFrameDisplay)
|
||||
APPEND("AFD ");
|
||||
|
||||
APPEND("EER={} EEC={} VUR={} VUC={} VQS={} ", static_cast<unsigned>(EmuConfig.Cpu.FPUFPCR.GetRoundMode()),
|
||||
EmuConfig.Cpu.Recompiler.GetEEClampMode(), static_cast<unsigned>(EmuConfig.Cpu.VU0FPCR.GetRoundMode()),
|
||||
|
||||
@@ -1048,6 +1048,13 @@ void MTGS::SetRunIdle(bool enabled)
|
||||
s_run_idle_flag.store(enabled, std::memory_order_release);
|
||||
}
|
||||
|
||||
void MTGS::ResetStats()
|
||||
{
|
||||
RunOnGSThread([]() {
|
||||
GSResetStats();
|
||||
});
|
||||
}
|
||||
|
||||
// Used in MTVU mode... MTVU will later complete a real packet
|
||||
void Gif_AddGSPacketMTVU(GS_Packet& gsPack, GIF_PATH path)
|
||||
{
|
||||
|
||||
@@ -78,6 +78,7 @@ namespace MTGS
|
||||
bool SaveMemorySnapshot(u32 window_width, u32 window_height, bool apply_aspect, bool crop_borders,
|
||||
u32* width, u32* height, std::vector<u32>* pixels);
|
||||
void SetRunIdle(bool enabled);
|
||||
void ResetStats();
|
||||
|
||||
// Size of the ringbuffer as a power of 2 -- size is a multiple of simd128s.
|
||||
// (actual size is 1<<m_RingBufferSizeFactor simd vectors [128-bit values])
|
||||
|
||||
@@ -723,6 +723,7 @@ Pcsx2Config::GSOptions::GSOptions()
|
||||
DisableFramebufferFetch = false;
|
||||
DisableVertexShaderExpand = false;
|
||||
SkipDuplicateFrames = true;
|
||||
AdvancedFrameDisplay = false;
|
||||
OsdMessagesPos = OsdOverlayPos::TopLeft;
|
||||
OsdPerformancePos = OsdOverlayPos::TopRight;
|
||||
OsdShowSpeed = false;
|
||||
@@ -875,6 +876,10 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
|
||||
OpEqu(SaveFrameStart) &&
|
||||
OpEqu(SaveFrameCount) &&
|
||||
OpEqu(SaveFrameBy) &&
|
||||
OpEqu(DumpReplayLoopCount) &&
|
||||
OpEqu(DumpReplayFrameStart) &&
|
||||
OpEqu(DumpReplayFrameEnd) &&
|
||||
OpEqu(SavedMetricsCaptureSeconds) &&
|
||||
|
||||
OpEqu(ExclusiveFullscreenControl) &&
|
||||
OpEqu(ScreenshotSize) &&
|
||||
@@ -961,6 +966,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||
SettingsWrapBitBool(DisableFramebufferFetch);
|
||||
SettingsWrapBitBool(DisableVertexShaderExpand);
|
||||
SettingsWrapBitBool(SkipDuplicateFrames);
|
||||
SettingsWrapBitBool(AdvancedFrameDisplay);
|
||||
SettingsWrapBitBool(OsdShowSpeed);
|
||||
SettingsWrapBitBool(OsdShowFPS);
|
||||
SettingsWrapBitBool(OsdShowVPS);
|
||||
@@ -1019,6 +1025,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||
SettingsWrapBitBoolEx(SaveDrawStats, "SaveDrawStats");
|
||||
SettingsWrapBitBoolEx(SaveFrameStats, "SaveFrameStats");
|
||||
SettingsWrapBitBoolEx(SaveHWConfig, "SaveHWConfig");
|
||||
SettingsWrapBitBoolEx(DumpReplayUseFrameRange, "DumpReplayUseFrameRange");
|
||||
SettingsWrapBitBool(DumpReplaceableTextures);
|
||||
SettingsWrapBitBool(DumpReplaceableMipmaps);
|
||||
SettingsWrapBitBool(DumpTexturesWithFMVActive);
|
||||
@@ -1093,6 +1100,10 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||
SettingsWrapBitfieldEx(SaveFrameStart, "SaveFrameStart");
|
||||
SettingsWrapBitfieldEx(SaveFrameCount, "SaveFrameCount");
|
||||
SettingsWrapBitfieldEx(SaveFrameBy, "SaveFrameBy");
|
||||
SettingsWrapBitfieldEx(DumpReplayLoopCount, "DumpReplayLoopCount");
|
||||
SettingsWrapBitfieldEx(DumpReplayFrameStart, "DumpReplayFrameStart");
|
||||
SettingsWrapBitfieldEx(DumpReplayFrameEnd, "DumpReplayFrameEnd");
|
||||
SettingsWrapBitfieldEx(SavedMetricsCaptureSeconds, "SavedMetricsCaptureSeconds");
|
||||
|
||||
SettingsWrapEntryEx(CaptureContainer, "CaptureContainer");
|
||||
SettingsWrapEntryEx(VideoCaptureCodec, "VideoCaptureCodec");
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include "common/Timer.h"
|
||||
#include "common/Threading.h"
|
||||
@@ -75,6 +76,10 @@ static double s_average_gpu_ps_invocations = 0.0;
|
||||
static u64 s_accumulated_gpu_vs_invocations = 0;
|
||||
static u64 s_accumulated_gpu_ps_invocations = 0;
|
||||
|
||||
static PerformanceMetrics::SavedMetrics s_saved_metrics;
|
||||
static PerformanceMetrics::SavedMetrics s_saved_metrics_std;
|
||||
static float s_saved_metrics_remaining_seconds = 0.0f;
|
||||
|
||||
void PerformanceMetrics::Clear()
|
||||
{
|
||||
Reset();
|
||||
@@ -85,6 +90,8 @@ void PerformanceMetrics::Clear()
|
||||
s_average_frame_time = 0.0f;
|
||||
s_maximum_frame_time = 0.0f;
|
||||
s_internal_fps_method = PerformanceMetrics::InternalFPSMethod::None;
|
||||
s_average_gpu_vs_invocations = 0.0;
|
||||
s_average_gpu_ps_invocations = 0.0;
|
||||
|
||||
s_cpu_thread_usage = 0.0f;
|
||||
s_cpu_thread_time = 0.0f;
|
||||
@@ -102,6 +109,10 @@ void PerformanceMetrics::Clear()
|
||||
|
||||
s_frame_time_history.fill(0.0f);
|
||||
s_frame_time_history_pos = 0;
|
||||
|
||||
s_saved_metrics = {};
|
||||
s_saved_metrics_std = {};
|
||||
s_saved_metrics_remaining_seconds = 0.0f;
|
||||
}
|
||||
|
||||
void PerformanceMetrics::Reset()
|
||||
@@ -113,6 +124,8 @@ void PerformanceMetrics::Reset()
|
||||
s_minimum_frame_time_accumulator = 0.0f;
|
||||
s_average_frame_time_accumulator = 0.0f;
|
||||
s_maximum_frame_time_accumulator = 0.0f;
|
||||
s_accumulated_gpu_vs_invocations = 0;
|
||||
s_accumulated_gpu_ps_invocations = 0;
|
||||
|
||||
s_accumulated_gpu_time = 0.0f;
|
||||
s_presents_since_last_update = 0;
|
||||
@@ -130,6 +143,17 @@ void PerformanceMetrics::Reset()
|
||||
stat.last_cpu_time = stat.handle.GetCPUTime();
|
||||
}
|
||||
|
||||
static double GetCPUTimeToPCTFactor(u64 ticks_delta)
|
||||
{
|
||||
return 100.0 * static_cast<double>(GetTickFrequency()) /
|
||||
(static_cast<double>(ticks_delta) * static_cast<double>(Threading::GetThreadTicksPerSecond()));
|
||||
}
|
||||
|
||||
static double GetCPUTimeToMSFactor(u64 frames)
|
||||
{
|
||||
return 1000.0 / static_cast<double>(Threading::GetThreadTicksPerSecond()) / static_cast<double>(frames);
|
||||
}
|
||||
|
||||
void PerformanceMetrics::Update(bool gs_register_write, bool fb_blit, bool is_skipping_present)
|
||||
{
|
||||
if (!is_skipping_present)
|
||||
@@ -191,11 +215,8 @@ void PerformanceMetrics::Update(bool gs_register_write, bool fb_blit, bool is_sk
|
||||
const u64 ticks_delta = ticks - s_last_ticks;
|
||||
s_last_ticks = ticks;
|
||||
|
||||
const double pct_divider =
|
||||
100.0 * (1.0 / ((static_cast<double>(ticks_delta) * static_cast<double>(Threading::GetThreadTicksPerSecond())) /
|
||||
static_cast<double>(GetTickFrequency())));
|
||||
const double time_divider = 1000.0 * (1.0 / static_cast<double>(Threading::GetThreadTicksPerSecond())) *
|
||||
(1.0 / static_cast<double>(s_frames_since_last_update));
|
||||
const double pct_divider = GetCPUTimeToPCTFactor(ticks_delta);
|
||||
const double time_divider = GetCPUTimeToMSFactor(s_frames_since_last_update);
|
||||
|
||||
const u64 cpu_time = s_cpu_thread_handle.GetCPUTime();
|
||||
const u64 gs_time = MTGS::GetThreadHandle().GetCPUTime();
|
||||
@@ -229,6 +250,32 @@ void PerformanceMetrics::Update(bool gs_register_write, bool fb_blit, bool is_sk
|
||||
thread.time = static_cast<double>(delta) * time_divider;
|
||||
}
|
||||
|
||||
if (s_saved_metrics_remaining_seconds > 0.0f)
|
||||
{
|
||||
auto UpdateSavedMetrics = [&](PerformanceMetrics::SavedMetrics& metrics, bool square) {
|
||||
auto Transform = [square](float f) { return square ? f * f : f; };
|
||||
|
||||
metrics.num_samples += 1.0f;
|
||||
metrics.frames += static_cast<float>(s_frames_since_last_update);
|
||||
metrics.time += time;
|
||||
metrics.fps += Transform(s_fps);
|
||||
metrics.internal_fps += Transform(s_internal_fps);
|
||||
metrics.cpu_thread_usage += Transform(s_cpu_thread_usage);
|
||||
metrics.cpu_thread_time += Transform(s_cpu_thread_time);
|
||||
metrics.gs_thread_usage += Transform(s_gs_thread_usage);
|
||||
metrics.gs_thread_time += Transform(s_gs_thread_time);
|
||||
metrics.gpu_time += Transform(s_average_gpu_time);;
|
||||
metrics.gpu_usage += Transform(s_gpu_usage);
|
||||
};
|
||||
|
||||
UpdateSavedMetrics(s_saved_metrics, false);
|
||||
UpdateSavedMetrics(s_saved_metrics_std, true);
|
||||
|
||||
s_saved_metrics_remaining_seconds -= std::min(s_saved_metrics_remaining_seconds, time);
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_release); // results might be read on another thread
|
||||
}
|
||||
|
||||
s_frames_since_last_update = 0;
|
||||
s_unskipped_frames_since_last_update = 0;
|
||||
s_presents_since_last_update = 0;
|
||||
@@ -391,3 +438,62 @@ u32 PerformanceMetrics::GetFrameTimeHistoryPos()
|
||||
{
|
||||
return s_frame_time_history_pos;
|
||||
}
|
||||
|
||||
void PerformanceMetrics::StartSavingMetrics(u32 seconds)
|
||||
{
|
||||
s_saved_metrics_remaining_seconds = static_cast<float>(seconds);
|
||||
s_saved_metrics = {};
|
||||
s_saved_metrics_std = {};
|
||||
}
|
||||
|
||||
bool PerformanceMetrics::IsSavingMetrics()
|
||||
{
|
||||
return s_saved_metrics_remaining_seconds > 0.0f;
|
||||
}
|
||||
|
||||
void PerformanceMetrics::DumpSavedMetrics()
|
||||
{
|
||||
s_saved_metrics_remaining_seconds = 0.0f;
|
||||
|
||||
SavedMetrics metrics = std::exchange(s_saved_metrics, SavedMetrics{});
|
||||
SavedMetrics metrics_std = std::exchange(s_saved_metrics_std, SavedMetrics{});
|
||||
|
||||
const float num_samples = metrics.num_samples;
|
||||
|
||||
if (num_samples > 0.0f)
|
||||
{
|
||||
const auto Square = [](float f) { return f * f; };
|
||||
const auto Average = [num_samples](float f) { return f / num_samples; };
|
||||
|
||||
metrics.fps = Average(metrics.fps);
|
||||
metrics.internal_fps = Average(metrics.internal_fps);
|
||||
metrics.cpu_thread_usage = Average(metrics.cpu_thread_usage);
|
||||
metrics.cpu_thread_time = Average(metrics.cpu_thread_time);
|
||||
metrics.gs_thread_usage = Average(metrics.gs_thread_usage);
|
||||
metrics.gs_thread_time = Average(metrics.gs_thread_time);
|
||||
metrics.gpu_time = Average(metrics.gpu_time);
|
||||
metrics.gpu_usage = Average(metrics.gpu_usage);
|
||||
|
||||
metrics_std.fps = std::sqrt((Average(metrics_std.fps) - Square(metrics.fps)));
|
||||
metrics_std.internal_fps = std::sqrt((Average(metrics_std.internal_fps) - Square(metrics.internal_fps)));
|
||||
metrics_std.cpu_thread_usage = std::sqrt((Average(metrics_std.cpu_thread_usage) - Square(metrics.cpu_thread_usage)));
|
||||
metrics_std.cpu_thread_time = std::sqrt((Average(metrics_std.cpu_thread_time) - Square(metrics.cpu_thread_time)));
|
||||
metrics_std.gs_thread_usage = std::sqrt((Average(metrics_std.gs_thread_usage) - Square(metrics.gs_thread_usage)));
|
||||
metrics_std.gs_thread_time = std::sqrt((Average(metrics_std.gs_thread_time) - Square(metrics.gs_thread_time)));
|
||||
metrics_std.gpu_time = std::sqrt((Average(metrics_std.gpu_time) - Square(metrics.gpu_time)));
|
||||
metrics_std.gpu_usage = std::sqrt((Average(metrics_std.gpu_usage) - Square(metrics.gpu_usage)));
|
||||
|
||||
Console.WriteLnFmt("@HWSTAT@ Frames: {} ({} samples)", metrics.frames, metrics.num_samples);
|
||||
Console.WriteLnFmt("@HWSTAT@ Time: {:.3f} sec", metrics.time);
|
||||
Console.WriteLnFmt("@HWSTAT@ FPS: {:.3f} ± {:.3f} ({:.3f} ± {:.3f} internal)", metrics.fps, metrics_std.fps, metrics.internal_fps, metrics_std.internal_fps);
|
||||
Console.WriteLnFmt("@HWSTAT@ Minimum Frame Time: {:.3f} ms ({:.3f} FPS)", GetMinimumFrameTime(), 1000.0f / GetMinimumFrameTime());
|
||||
Console.WriteLnFmt("@HWSTAT@ Average Frame Time: {:.3f} ms ({:.3f} FPS)", GetAverageFrameTime(), 1000.0f / GetAverageFrameTime());
|
||||
Console.WriteLnFmt("@HWSTAT@ Maximum Frame Time: {:.3f} ms ({:.3f} FPS)", GetMaximumFrameTime(), 1000.0f / GetMaximumFrameTime());
|
||||
Console.WriteLnFmt("@HWSTAT@ Average CPU Thread Usage: {:.3f} ± {:.3f} %", metrics.cpu_thread_usage, metrics_std.cpu_thread_usage);
|
||||
Console.WriteLnFmt("@HWSTAT@ Average GS Thread Usage: {:.3f} ± {:.3f} %", metrics.gs_thread_usage, metrics_std.gs_thread_usage);
|
||||
Console.WriteLnFmt("@HWSTAT@ Average GPU Usage: {:.3f} ± {:.3f} %", metrics.gpu_usage, metrics_std.gpu_usage);
|
||||
Console.WriteLnFmt("@HWSTAT@ Average CPU Thread Time: {:.3f} ± {:.3f} ms", metrics.cpu_thread_time, metrics_std.cpu_thread_time);
|
||||
Console.WriteLnFmt("@HWSTAT@ Average GS Thread Time: {:.3f} ± {:.3f} ms", metrics.gs_thread_time, metrics_std.gs_thread_time);
|
||||
Console.WriteLnFmt("@HWSTAT@ Average GPU Time: {:.3f} ± {:.3f} ms", metrics.gpu_time, metrics_std.gpu_time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,4 +62,23 @@ namespace PerformanceMetrics
|
||||
|
||||
const FrameTimeHistory& GetFrameTimeHistory();
|
||||
u32 GetFrameTimeHistoryPos();
|
||||
|
||||
struct SavedMetrics
|
||||
{
|
||||
float num_samples;
|
||||
float frames;
|
||||
float time;
|
||||
float fps;
|
||||
float internal_fps;
|
||||
float cpu_thread_usage;
|
||||
float cpu_thread_time;
|
||||
float gs_thread_usage;
|
||||
float gs_thread_time;
|
||||
float gpu_time;
|
||||
float gpu_usage;
|
||||
};
|
||||
|
||||
void StartSavingMetrics(u32 seconds);
|
||||
bool IsSavingMetrics();
|
||||
void DumpSavedMetrics();
|
||||
} // namespace PerformanceMetrics
|
||||
|
||||
@@ -232,6 +232,8 @@ void Pad::SetDefaultHotkeyConfig(SettingsInterface& si)
|
||||
si.SetStringValue("Hotkeys", "GSDumpMultiFrame", "Keyboard/Control & Keyboard/Shift & Keyboard/F8");
|
||||
si.SetStringValue("Hotkeys", "Screenshot", "Keyboard/F8");
|
||||
si.SetStringValue("Hotkeys", "GSDumpSingleFrame", "Keyboard/Shift & Keyboard/F8");
|
||||
si.SetStringValue("Hotkeys", "GSStartSavingMetricsVariableFrames", "Keyboard/F10");
|
||||
si.SetStringValue("Hotkeys", "GSStartSavingMetricsFixedFrames", "Keyboard/Control & Keyboard/F10");
|
||||
si.SetStringValue("Hotkeys", "ToggleSoftwareRendering", "Keyboard/F9");
|
||||
// si.SetStringValue("Hotkeys", "ToggleTextureDumping", "Keyboard"); TBD
|
||||
// si.SetStringValue("Hotkeys", "ToggleTextureReplacements", "Keyboard"); TBD
|
||||
|
||||
+13
-4
@@ -666,7 +666,12 @@ void VMManager::LoadCoreSettings(SettingsInterface& si)
|
||||
|
||||
// Force MTVU off when playing back GS dumps, it doesn't get used.
|
||||
if (GSDumpReplayer::IsReplayingDump())
|
||||
{
|
||||
EmuConfig.Speedhacks.vuThread = false;
|
||||
GSDumpReplayer::SetFrameRange(EmuConfig.GS.DumpReplayUseFrameRange,
|
||||
EmuConfig.GS.DumpReplayFrameStart, EmuConfig.GS.DumpReplayFrameEnd);
|
||||
GSDumpReplayer::SetLoopCount(EmuConfig.GS.DumpReplayLoopCount);
|
||||
}
|
||||
}
|
||||
|
||||
void VMManager::LoadInputBindings(SettingsInterface& si, std::unique_lock<std::mutex>& lock)
|
||||
@@ -1649,6 +1654,7 @@ VMBootResult VMManager::Initialize(const VMBootParameters& boot_params, Error* e
|
||||
}
|
||||
|
||||
PerformanceMetrics::Clear();
|
||||
MTGS::ResetStats();
|
||||
return VMBootResult::StartupSuccess;
|
||||
}
|
||||
|
||||
@@ -2272,14 +2278,14 @@ void VMManager::ResetFrameLimiter()
|
||||
s_limiter_frame_start = GetCPUTicks();
|
||||
}
|
||||
|
||||
void VMManager::Internal::Throttle()
|
||||
void VMManager::Internal::Throttle(bool vsync_start)
|
||||
{
|
||||
if (s_target_speed == 0.0f || s_use_vsync_for_timing)
|
||||
return;
|
||||
|
||||
const u64 uExpectedEnd =
|
||||
s_limiter_frame_start +
|
||||
s_limiter_ticks_per_frame; // Compute when we would expect this frame to end, assuming everything goes perfectly perfect.
|
||||
(vsync_start ? (s_limiter_ticks_per_frame * 0.9) : s_limiter_ticks_per_frame); // Compute when we would expect this frame to end, assuming everything goes perfectly perfect.
|
||||
const u64 iEnd = GetCPUTicks(); // The current tick we actually stopped on.
|
||||
const s64 sDeltaTime = iEnd - uExpectedEnd; // The diff between when we stopped and when we expected to.
|
||||
|
||||
@@ -2308,8 +2314,11 @@ void VMManager::Internal::Throttle()
|
||||
{
|
||||
}
|
||||
|
||||
// Finally, set our next frame start to when this one ends
|
||||
s_limiter_frame_start = uExpectedEnd;
|
||||
if (!vsync_start)
|
||||
{
|
||||
// Finally, set our next frame start to when this one ends
|
||||
s_limiter_frame_start = uExpectedEnd;
|
||||
}
|
||||
}
|
||||
|
||||
void VMManager::Internal::FrameRateChanged()
|
||||
|
||||
+1
-1
@@ -322,7 +322,7 @@ namespace VMManager
|
||||
void FrameRateChanged();
|
||||
|
||||
/// Throttles execution, or limits the frame rate.
|
||||
void Throttle();
|
||||
void Throttle(bool vsync_start);
|
||||
|
||||
/// Resets/clears all execution/code caches.
|
||||
void ClearCPUExecutionCaches();
|
||||
|
||||
Reference in New Issue
Block a user