mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-31 03:08:40 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
460a2dbbd3 | ||
|
|
228f4f1010 | ||
|
|
2703b91e41 | ||
|
|
24171787f8 | ||
|
|
49d3338d4a | ||
|
|
a9d693e1c3 | ||
|
|
4ef69248d0 | ||
|
|
247b3ed740 | ||
|
|
1edca6235c | ||
|
|
ab5c03b1d9 | ||
|
|
d4cb35469d | ||
|
|
fd1b1d0c24 | ||
|
|
bf96ceeacc | ||
|
|
2c08b385e5 | ||
|
|
051d13ec7a | ||
|
|
a2a9643123 | ||
|
|
1286bfe75b | ||
|
|
1f74f82796 | ||
|
|
876b576679 | ||
|
|
c927e4785b | ||
|
|
97672828e8 | ||
|
|
b96978494b | ||
|
|
2f105cbe15 | ||
|
|
2539a07b7d | ||
|
|
73f903f402 | ||
|
|
94c48a4c2d | ||
|
|
eb8d938c94 | ||
|
|
92b8316182 | ||
|
|
610cb2626b | ||
|
|
2033f813da | ||
|
|
a6fbd0fe69 | ||
|
|
abadb7f80f | ||
|
|
1c6be3f400 | ||
|
|
52111be20a | ||
|
|
eae29bb1f2 | ||
|
|
9191e8ce91 | ||
|
|
2b4c7d12b6 | ||
|
|
7dd1f7321a | ||
|
|
088630a999 | ||
|
|
d2a5cdcca7 | ||
|
|
4b50d016b5 | ||
|
|
7a073e0e8d | ||
|
|
b56958abe4 | ||
|
|
57d042ca4a | ||
|
|
3895f3c826 | ||
|
|
75aed7c44f | ||
|
|
041c0ce86c | ||
|
|
90aabdf499 | ||
|
|
40f7ec3ca1 | ||
|
|
1e32fcaebe | ||
|
|
9f23755a62 | ||
|
|
dad03478fd | ||
|
|
484b75f755 | ||
|
|
7138faa5cd | ||
|
|
fef1706fc8 | ||
|
|
1929b20a6c | ||
|
|
3991ff5d3a | ||
|
|
e4b1c89719 | ||
|
|
3d51eec89c | ||
|
|
f9016f3ea7 | ||
|
|
3dce969a5e | ||
|
|
542d257b8f | ||
|
|
2eb7c47572 | ||
|
|
32621a9369 | ||
|
|
7676a74f73 | ||
|
|
1fae35231b | ||
|
|
cd4daa115f | ||
|
|
ad0190d6ed | ||
|
|
296dcccd81 | ||
|
|
7ba7e04a13 | ||
|
|
3109c5ef67 | ||
|
|
d5776e8946 | ||
|
|
c59ea602c5 | ||
|
|
16bebbea50 | ||
|
|
0e21b6da3d | ||
|
|
b3403c40e1 | ||
|
|
863e8bb290 | ||
|
|
1a16a527b3 | ||
|
|
c72329d990 | ||
|
|
dffeb2b5dd | ||
|
|
fef06a1544 | ||
|
|
7d9ad6daab | ||
|
|
822b166753 | ||
|
|
8fad768d39 | ||
|
|
d46b8390f1 | ||
|
|
4262715590 | ||
|
|
9818446c7d | ||
|
|
22682e4150 | ||
|
|
1d63779b7d | ||
|
|
c82f800794 | ||
|
|
d96dea49bf | ||
|
|
c574c3e08c | ||
|
|
e7e6f765b5 | ||
|
|
240586875c | ||
|
|
d6c5903569 | ||
|
|
55da5cc397 | ||
|
|
943359e328 | ||
|
|
92c54cc1f8 | ||
|
|
6ec0b44487 | ||
|
|
85d2ca626f | ||
|
|
68865a2bca | ||
|
|
8362e6f435 | ||
|
|
3804a58729 | ||
|
|
fbb67a6ee9 | ||
|
|
19d8b59ca7 | ||
|
|
7ca726492f | ||
|
|
96a43ca254 | ||
|
|
bf34eb32ed | ||
|
|
433612cde0 | ||
|
|
807db91140 | ||
|
|
7791809224 | ||
|
|
9b3d31cd47 | ||
|
|
65a3a97ab2 | ||
|
|
e3593574b0 | ||
|
|
f81d391546 | ||
|
|
bd3b00793a | ||
|
|
757a72fb57 | ||
|
|
fbbec480af | ||
|
|
ba3b43c66c | ||
|
|
e040b83b2c | ||
|
|
76f4a5b2fe | ||
|
|
4f4b9956b3 | ||
|
|
ba37a0f3a9 | ||
|
|
d4acb95d7c | ||
|
|
2887baefb8 | ||
|
|
9678bf1e2f | ||
|
|
e2fc68ff2d | ||
|
|
4a7b641bc3 | ||
|
|
719b83bf42 | ||
|
|
f201a2e5dd | ||
|
|
fd6f47f5ca | ||
|
|
8524fbbaf9 | ||
|
|
a371c5b7d0 | ||
|
|
ef7ce4dfc8 | ||
|
|
189f6fa2a3 | ||
|
|
472f4922bd | ||
|
|
8ba2f342df | ||
|
|
5d6b9d25bd | ||
|
|
1231499aaa | ||
|
|
9c4788432d | ||
|
|
4ded2caa0b | ||
|
|
494afb9d43 | ||
|
|
c994e4828d | ||
|
|
e50f12a925 | ||
|
|
df75d70df4 | ||
|
|
c5aa04d4eb | ||
|
|
81ae1ce362 | ||
|
|
e1921e660d | ||
|
|
32aa24f6fd | ||
|
|
7fbc63b8e8 | ||
|
|
443adcdd5b | ||
|
|
05b064d513 | ||
|
|
b327033333 | ||
|
|
36c9b68b6c | ||
|
|
7d8d16091e | ||
|
|
c1c6bde429 | ||
|
|
8f0901e7a5 | ||
|
|
6edba3820b | ||
|
|
db1e1bcc1f | ||
|
|
51aeaeb508 | ||
|
|
dcd0a1f002 | ||
|
|
819b61937f | ||
|
|
9da7628083 | ||
|
|
c5f47a8db3 | ||
|
|
c2786b91ce | ||
|
|
4290c16997 | ||
|
|
475e90b654 | ||
|
|
ebb291e06d | ||
|
|
a2c9069dda | ||
|
|
48cfe9ca73 | ||
|
|
b53e9856b8 | ||
|
|
20420da326 |
+4
-4
@@ -115,11 +115,11 @@
|
||||
- 'pcsx2/IPU/*'
|
||||
- 'pcsx2/IPU/**/*'
|
||||
'Memory Card':
|
||||
- 'pcsx2/gui/MemoryCard*'
|
||||
- 'pcsx2/gui/**/MemoryCard*'
|
||||
- 'pcsx2/SIO/Memcard/*'
|
||||
- 'pcsx2/SIO/Memcard/**/*'
|
||||
'PAD':
|
||||
- 'pcsx2/PAD/*'
|
||||
- 'pcsx2/PAD/**/*'
|
||||
- 'pcsx2/SIO/Pad/*'
|
||||
- 'pcsx2/SIO/Pad/**/*'
|
||||
'SPU2':
|
||||
- 'pcsx2/SPU2/*'
|
||||
- 'pcsx2/SPU2/**/*'
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
name: 🌎 Update Base Translation
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # Every day at 12am UTC.
|
||||
workflow_dispatch: # As well as manually.
|
||||
|
||||
jobs:
|
||||
update:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Update Base Translation"
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Update Base Translation
|
||||
run: ./.github/workflows/scripts/common/update_base_translation.sh
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
title: "Qt: Update Base Translation"
|
||||
commit-message: "Qt: Update Base Translation"
|
||||
committer: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
author: "PCSX2 Bot <PCSX2Bot@users.noreply.github.com>"
|
||||
body: "Daily update of base translation sources."
|
||||
branch: update-base-translation
|
||||
delete-branch: true
|
||||
@@ -28,14 +28,14 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
detail:
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
patches_url:
|
||||
patchesUrl:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2_patches/releases/latest/download
|
||||
fetchTags:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
@@ -51,9 +51,9 @@ jobs:
|
||||
|
||||
# Hackity hack. When running the workflow on a schedule, we don't have the tag,
|
||||
# it doesn't fetch tags, therefore we don't get a version. So grab them manually.
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch tags
|
||||
if: inputs.publish == true
|
||||
id: fetch-tags
|
||||
if: ${{ inputs.fetchTags }}
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
@@ -61,7 +61,6 @@ jobs:
|
||||
shell: bash
|
||||
env:
|
||||
OS: linux
|
||||
GUI_FRAMEWORK: QT
|
||||
BUILD_SYSTEM: flatpak
|
||||
ARCH: ${{ inputs.platform }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
@@ -78,7 +77,7 @@ jobs:
|
||||
- name: Download patches
|
||||
run: |
|
||||
cd bin/resources
|
||||
aria2c -Z "${{ inputs.patches_url }}/patches.zip"
|
||||
aria2c -Z "${{ inputs.patchesUrl }}/patches.zip"
|
||||
|
||||
- name: Generate AppStream XML
|
||||
run: |
|
||||
@@ -98,7 +97,7 @@ jobs:
|
||||
branch: ${{ inputs.branch }}
|
||||
cache: true
|
||||
restore-cache: true
|
||||
cache-key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} ${{ inputs.detail }} flatpak ${{ hashFiles('.github/workflows/scripts/linux/flatpak/**/*.json') }}
|
||||
cache-key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} flatpak ${{ hashFiles('.github/workflows/scripts/linux/flatpak/**/*.json') }}
|
||||
|
||||
- name: Commit screenshots to OSTree
|
||||
run: |
|
||||
|
||||
@@ -14,7 +14,7 @@ jobs:
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
jobName: "AppImage Build"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
jobName: "Flatpak Build"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
publish: false
|
||||
|
||||
@@ -9,7 +9,7 @@ on:
|
||||
os:
|
||||
required: false
|
||||
type: string
|
||||
default: ubuntu-20.04
|
||||
default: ubuntu-22.04
|
||||
platform:
|
||||
required: false
|
||||
type: string
|
||||
@@ -28,10 +28,14 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
patches_url:
|
||||
patchesUrl:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2_patches/releases/latest/download
|
||||
fetchTags:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build_linux:
|
||||
@@ -52,12 +56,16 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch Tags
|
||||
if: ${{ inputs.fetchTags }}
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
env:
|
||||
OS: linux
|
||||
GUI_FRAMEWORK: QT
|
||||
ARCH: ${{ inputs.platform }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
@@ -87,7 +95,7 @@ jobs:
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/deps
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.gui }} deps ${{ hashFiles('.github/workflows/scripts/linux/build-dependencies-qt.sh') }}
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} deps ${{ hashFiles('.github/workflows/scripts/linux/build-dependencies-qt.sh') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
@@ -96,7 +104,7 @@ jobs:
|
||||
- name: Download patches
|
||||
run: |
|
||||
cd bin/resources
|
||||
aria2c -Z "${{ inputs.patches_url }}/patches.zip"
|
||||
aria2c -Z "${{ inputs.patchesUrl }}/patches.zip"
|
||||
|
||||
- name: Generate CMake
|
||||
env:
|
||||
@@ -120,9 +128,9 @@ jobs:
|
||||
env:
|
||||
NAME: ${{ steps.artifact-metadata.outputs.artifact-name }}
|
||||
run: |
|
||||
.github/workflows/scripts/linux/appimage-qt.sh "$(realpath .)" "$(realpath ./build)" "$HOME/deps" "$NAME"
|
||||
mkdir -p "$GITHUB_WORKSPACE"/ci-artifacts/
|
||||
mv "${NAME}.AppImage" "$GITHUB_WORKSPACE"/ci-artifacts/
|
||||
.github/workflows/scripts/linux/appimage-qt.sh "$(realpath .)" "$(realpath ./build)" "$HOME/deps" "$NAME"
|
||||
mkdir -p "$GITHUB_WORKSPACE"/ci-artifacts/
|
||||
mv "${NAME}.AppImage" "$GITHUB_WORKSPACE"/ci-artifacts/
|
||||
|
||||
- name: Upload artifact
|
||||
if: inputs.buildAppImage == true
|
||||
|
||||
@@ -10,17 +10,14 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
default: macos-13
|
||||
platform:
|
||||
required: false
|
||||
type: string
|
||||
default: x64
|
||||
gui:
|
||||
required: true
|
||||
type: string
|
||||
patches_url:
|
||||
patchesUrl:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2_patches/releases/latest/download
|
||||
fetchTags:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build_macos:
|
||||
@@ -42,6 +39,11 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch Tags
|
||||
if: ${{ inputs.fetchTags }}
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Use Xcode 14.3.1
|
||||
run: sudo xcode-select -s /Applications/Xcode_14.3.1.app
|
||||
|
||||
@@ -50,8 +52,6 @@ jobs:
|
||||
shell: bash
|
||||
env:
|
||||
OS: macos
|
||||
GUI_FRAMEWORK: ${{ inputs.gui }}
|
||||
ARCH: ${{ inputs.platform }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
PR_TITLE: ${{ github.event.pull_request.title }}
|
||||
PR_NUM: ${{ github.event.pull_request.number }}
|
||||
@@ -60,16 +60,16 @@ jobs:
|
||||
|
||||
- name: Install Packages
|
||||
env:
|
||||
PLATFORM: ${{ inputs.platform }}
|
||||
PLATFORM: "x64"
|
||||
HOMEBREW_NO_INSTALL_CLEANUP: 1
|
||||
HOMEBREW_NO_ANALYTICS: 1
|
||||
run: |
|
||||
brew unlink libjpeg || true # Conflicts with our self-built dependencies
|
||||
brew unlink libpng || true
|
||||
# Unlike other packages, brew's MoltenVK build uses MoltenVK's minimum macOS version of 10.13 so we can use it
|
||||
if ! brew install molten-vk ccache; then
|
||||
if ! brew install molten-vk ccache nasm; then
|
||||
brew update
|
||||
brew install molten-vk ccache
|
||||
brew install molten-vk ccache nasm
|
||||
fi
|
||||
|
||||
- name: Cache Dependencies
|
||||
@@ -77,18 +77,16 @@ jobs:
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/deps
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.gui }} deps ${{ hashFiles('.github/workflows/scripts/macos/build-dependencies.sh') }}
|
||||
key: ${{ inputs.os }} deps ${{ hashFiles('.github/workflows/scripts/macos/build-dependencies.sh') }}
|
||||
|
||||
- name: Build Dependencies
|
||||
if: steps.cache-deps.outputs.cache-hit != 'true'
|
||||
env:
|
||||
GUI: ${{ inputs.gui }}
|
||||
run: .github/workflows/scripts/macos/build-dependencies.sh
|
||||
|
||||
- name: Download patches
|
||||
run: |
|
||||
cd bin/resources
|
||||
aria2c -Z "${{ inputs.patches_url }}/patches.zip"
|
||||
aria2c -Z "${{ inputs.patchesUrl }}/patches.zip"
|
||||
|
||||
# -- SETUP CCACHE - https://cristianadam.eu/20200113/speeding-up-c-plus-plus-github-actions-using-ccache/
|
||||
- name: Prepare ccache timestamp
|
||||
@@ -99,8 +97,8 @@ jobs:
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .ccache
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.gui }} ccache ${{ steps.ccache_cache_timestamp.outputs.timestamp }}
|
||||
restore-keys: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.gui }} ccache
|
||||
key: ${{ inputs.os }} ccache ${{ steps.ccache_cache_timestamp.outputs.timestamp }}
|
||||
restore-keys: ${{ inputs.os }} ccache
|
||||
|
||||
- name: Generate CMake Files
|
||||
run: |
|
||||
@@ -111,6 +109,7 @@ jobs:
|
||||
-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \
|
||||
-DUSE_SYSTEM_LIBS=OFF \
|
||||
-DUSE_SYSTEM_SDL2=ON \
|
||||
-DUSE_LINKED_FFMPEG=ON \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_DISABLE_PRECOMPILE_HEADERS=ON \
|
||||
@@ -133,7 +132,6 @@ jobs:
|
||||
done
|
||||
|
||||
- name: Run Tests
|
||||
if: inputs.gui == 'Qt'
|
||||
working-directory: build
|
||||
run: make -j$(getconf _NPROCESSORS_ONLN) unittests
|
||||
|
||||
@@ -149,7 +147,7 @@ jobs:
|
||||
mv build/pcsx2*/PCSX2.app "$APPNAME.app"
|
||||
tar --options xz:compression-level=9 -cvJf "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" "$APPNAME.app"
|
||||
mkdir ci-artifacts
|
||||
cp "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" ci-artifacts/macOS-${{ inputs.gui }}.tar.xz
|
||||
cp "${{ steps.artifact-metadata.outputs.artifact-name }}.tar.xz" ci-artifacts/macOS.tar.xz
|
||||
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
|
||||
@@ -14,6 +14,5 @@ jobs:
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/macos_build.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
gui: "Qt"
|
||||
jobName: "MacOS Build"
|
||||
secrets: inherit
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
# Whenever a commit is pushed to master (ideally via a pull-request!)
|
||||
# this action will create the next release, which means:
|
||||
# 1. tag master with the proper version
|
||||
# 2. create a new draft release (pre-released if a nightly build)
|
||||
# 3. add release notes
|
||||
|
||||
name: 🏭 Create Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
# TODO - future work
|
||||
# workflow_dispatch:
|
||||
# inputs:
|
||||
# isStable:
|
||||
# description: 'Should it be a stable release?'
|
||||
# required: true
|
||||
# default: 'false'
|
||||
# versionTag:
|
||||
# description: 'The version to tag with'
|
||||
# required: true
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
cut-release:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
name: "Create Tag and Release"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Docs - https://github.com/mathieudutour/github-tag-action
|
||||
- name: Bump Version and Push Tag
|
||||
id: tag_version
|
||||
uses: mathieudutour/github-tag-action@v6.1
|
||||
with:
|
||||
github_token: ${{ github.token }}
|
||||
tag_prefix: v
|
||||
default_bump: patch
|
||||
|
||||
# TODO - we could do this and remove the node.js script, but auto-generated notes only work
|
||||
# with PRs -- not commits (determine how much we care).
|
||||
# - name: Create Draft Release
|
||||
# run: |
|
||||
# echo "Creating release with tag - ${{ steps.tag_version.outputs.new_tag }}"
|
||||
# gh release create ${{ steps.tag_version.outputs.new_tag }} --draft --generate-notes -title ${{ steps.tag_version.outputs.new_tag }}
|
||||
|
||||
- name: Generate Release Notes
|
||||
env:
|
||||
OWNER: PCSX2
|
||||
REPO: pcsx2
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
COMMIT_SHA: ${{ github.SHA }}
|
||||
run: |
|
||||
cd ./.github/workflows/scripts/releases/generate-release-notes
|
||||
npm ci
|
||||
node index.js
|
||||
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
|
||||
|
||||
- name: Create a GitHub Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: steps.tag_version.outputs.new_tag
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
draft: true
|
||||
prerelease: true
|
||||
tag_name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
|
||||
# Build Everything
|
||||
# Linux
|
||||
build_linux_qt:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
needs:
|
||||
- cut-release
|
||||
name: "Linux"
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "AppImage Build"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
fetchTags: true
|
||||
secrets: inherit
|
||||
|
||||
build_linux_flatpak:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
needs:
|
||||
- cut-release
|
||||
name: "Linux"
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
jobName: "Flatpak Build"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
branch: "stable"
|
||||
publish: false
|
||||
fetchTags: true
|
||||
secrets: inherit
|
||||
|
||||
# Windows
|
||||
build_windows_qt:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
needs:
|
||||
- cut-release
|
||||
name: "Windows"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: "Windows Build"
|
||||
configuration: CMake
|
||||
buildSystem: cmake
|
||||
cmakeFlags: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
|
||||
fetchTags: true
|
||||
secrets: inherit
|
||||
|
||||
# MacOS
|
||||
build_macos_qt:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
needs:
|
||||
- cut-release
|
||||
name: "MacOS"
|
||||
uses: ./.github/workflows/macos_build.yml
|
||||
with:
|
||||
jobName: "MacOS Build"
|
||||
fetchTags: true
|
||||
secrets: inherit
|
||||
|
||||
# Upload the Artifacts
|
||||
upload_artifacts:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
needs:
|
||||
- build_linux_flatpak
|
||||
- build_linux_qt
|
||||
- build_windows_qt
|
||||
- build_macos_qt
|
||||
name: "Upload Artifacts"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch Tags
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Prepare Artifact Folder
|
||||
run: mkdir ./ci-artifacts/
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
name: Download all Artifacts
|
||||
with:
|
||||
path: ./ci-artifacts/
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls ./ci-artifacts/
|
||||
|
||||
# Prepare artifacts, they are all zips from github!
|
||||
- name: Prepare Artifacts
|
||||
working-directory: ./ci-artifacts/
|
||||
run: for d in *windows*/; do 7z a "${d}asset.7z" ./$d/*; done
|
||||
|
||||
# Artifact Naming:
|
||||
# MacOS: PCSX2-<tag>-macOS-[additional hyphen seperated tags]
|
||||
# Windows|Linux: PCSX2-<tag>-<windows|linux>-<32bit|64bit>--[additional hyphen seperated tags]
|
||||
- name: Name and Upload the Release Assets
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
SCAN_DIR: ${{ github.WORKSPACE }}/ci-artifacts
|
||||
OUT_DIR: ${{ github.WORKSPACE }}/ci-artifacts/out
|
||||
run: |
|
||||
TAG_VAL=$(git tag --points-at HEAD)
|
||||
echo "TAG_VAL=${TAG_VAL}"
|
||||
gh release list --repo PCSX2/pcsx2
|
||||
mkdir -p ${{ github.WORKSPACE }}/ci-artifacts/out
|
||||
TAG_VAL=${TAG_VAL} python ./.github/workflows/scripts/releases/rename-release-assets.py
|
||||
ls ${{ github.WORKSPACE }}/ci-artifacts/out
|
||||
gh release upload "${TAG_VAL}" ${{ github.WORKSPACE }}/ci-artifacts/out/* --repo PCSX2/pcsx2 --clobber
|
||||
|
||||
- name: Publish Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
TAG_VAL=$(git tag --points-at HEAD)
|
||||
echo "TAG_VAL=${TAG_VAL}"
|
||||
gh release edit ${TAG_VAL} --draft=false --repo PCSX2/pcsx2
|
||||
@@ -1,71 +0,0 @@
|
||||
# Whenever a commit is pushed to master (ideally via a pull-request!)
|
||||
# this action will create the next release, which means:
|
||||
# 1. tag master with the proper version
|
||||
# 2. create a new draft release (pre-released if a nightly build)
|
||||
# 3. add release notes
|
||||
|
||||
name: 🏭 Create Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
# TODO - future work
|
||||
# workflow_dispatch:
|
||||
# inputs:
|
||||
# isStable:
|
||||
# description: 'Should it be a stable release?'
|
||||
# required: true
|
||||
# default: 'false'
|
||||
# versionTag:
|
||||
# description: 'The version to tag with'
|
||||
# required: true
|
||||
|
||||
jobs:
|
||||
cut-release:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
runs-on: ubuntu-latest
|
||||
name: "Create Tag and Release"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# Docs - https://github.com/mathieudutour/github-tag-action
|
||||
- name: Bump Version and Push Tag
|
||||
id: tag_version
|
||||
uses: mathieudutour/github-tag-action@v6.1
|
||||
with:
|
||||
# Workflows cannot trigger other workflows implicitly
|
||||
# - https://github.community/t/github-actions-workflow-not-triggering-with-tag-push/17053/7
|
||||
github_token: ${{ secrets.BOT_PAT }}
|
||||
tag_prefix: v
|
||||
default_bump: patch
|
||||
|
||||
# TODO - we could do this and remove the node.js script, but auto-generated notes only work
|
||||
# with PRs -- not commits (determine how much we care).
|
||||
# - name: Create Draft Release
|
||||
# env:
|
||||
# GITHUB_TOKEN: ${{ secrets.BOT_PAT }}
|
||||
# run: |
|
||||
# echo "Creating release with tag - ${{ steps.tag_version.outputs.new_tag }}"
|
||||
# gh release create ${{ steps.tag_version.outputs.new_tag }} --draft --generate-notes -title ${{ steps.tag_version.outputs.new_tag }}
|
||||
|
||||
- name: Generate Release Notes
|
||||
env:
|
||||
OWNER: PCSX2
|
||||
REPO: pcsx2
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COMMIT_SHA: ${{ github.SHA }}
|
||||
run: |
|
||||
cd ./.github/workflows/scripts/releases/generate-release-notes
|
||||
npm ci
|
||||
node index.js
|
||||
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
|
||||
|
||||
- name: Create a GitHub Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
if: steps.tag_version.outputs.new_tag
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
draft: true
|
||||
prerelease: true
|
||||
tag_name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
@@ -1,107 +0,0 @@
|
||||
name: 🏭 Release Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- v*
|
||||
|
||||
jobs:
|
||||
# Build Everything
|
||||
# Linux
|
||||
build_linux_qt:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Linux"
|
||||
uses: ./.github/workflows/linux_build_qt.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
buildAppImage: true
|
||||
secrets: inherit
|
||||
build_linux_flatpak:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Linux"
|
||||
uses: ./.github/workflows/linux_build_flatpak.yml
|
||||
with:
|
||||
jobName: "Flatpak"
|
||||
compiler: clang
|
||||
cmakeflags: ""
|
||||
branch: "stable"
|
||||
publish: false
|
||||
secrets: inherit
|
||||
|
||||
# Windows
|
||||
build_windows_qt:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "Windows"
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
configuration: CMake
|
||||
buildSystem: cmake
|
||||
cmakeFlags: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl
|
||||
secrets: inherit
|
||||
|
||||
# MacOS
|
||||
build_macos_qt:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
name: "MacOS"
|
||||
uses: ./.github/workflows/macos_build.yml
|
||||
with:
|
||||
jobName: "Qt"
|
||||
gui: "Qt"
|
||||
secrets: inherit
|
||||
|
||||
# Upload the Artifacts
|
||||
upload_artifacts:
|
||||
if: github.repository == 'PCSX2/pcsx2'
|
||||
needs:
|
||||
- build_linux_flatpak
|
||||
- build_linux_qt
|
||||
- build_windows_qt
|
||||
- build_macos_qt
|
||||
name: "Upload Artifacts"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Prepare Artifact Folder
|
||||
run: mkdir ./ci-artifacts/
|
||||
|
||||
- uses: actions/download-artifact@v3
|
||||
name: Download all Artifacts
|
||||
with:
|
||||
path: ./ci-artifacts/
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls ./ci-artifacts/
|
||||
|
||||
# Prepare artifacts, they are all zips from github!
|
||||
- name: Prepare Artifacts
|
||||
working-directory: ./ci-artifacts/
|
||||
run: for d in *windows*/; do 7z a "${d}asset.7z" ./$d/*; done
|
||||
|
||||
# Artifact Naming:
|
||||
# MacOS: PCSX2-<tag>-macOS-[additional hyphen seperated tags]
|
||||
# Windows|Linux: PCSX2-<tag>-<windows|linux>-<32bit|64bit>--[additional hyphen seperated tags]
|
||||
- name: Name and Upload the Release Assets
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
TAG: ${{ github.REF }}
|
||||
SCAN_DIR: ${{ github.WORKSPACE }}/ci-artifacts
|
||||
OUT_DIR: ${{ github.WORKSPACE }}/ci-artifacts/out
|
||||
run: |
|
||||
gh release list --repo PCSX2/pcsx2
|
||||
mkdir -p ${{ github.WORKSPACE }}/ci-artifacts/out
|
||||
python ./.github/workflows/scripts/releases/rename-release-assets.py
|
||||
ls ${{ github.WORKSPACE }}/ci-artifacts/out
|
||||
TAG_VAL=$(echo ${{ github.REF }} | awk -F'refs/tags/' '{print $2}')
|
||||
gh release upload "${TAG_VAL}" ${{ github.WORKSPACE }}/ci-artifacts/out/* --repo PCSX2/pcsx2 --clobber
|
||||
|
||||
- name: Publish Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_PAT }}
|
||||
run: |
|
||||
TAG_VAL=$(echo ${{ github.REF }} | awk -F'refs/tags/' '{print $2}')
|
||||
gh release edit ${TAG_VAL} --draft=false --repo PCSX2/pcsx2
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Artifact Naming Scheme:
|
||||
# PCSX2-<OS>-<GUI>-[ARCH]-[SIMD]-[pr\[PR_NUM\]]-[title|sha\[SHA|PR_TITLE\]
|
||||
# PCSX2-<OS>-Qt-[ARCH]-[SIMD]-[pr\[PR_NUM\]]-[title|sha\[SHA|PR_TITLE\]
|
||||
# -- limited to 200 chars
|
||||
# Outputs:
|
||||
# - artifact-name
|
||||
@@ -9,7 +9,6 @@
|
||||
# Inputs as env-vars
|
||||
# OS
|
||||
# BUILD_SYSTEM
|
||||
# GUI_FRAMEWORK
|
||||
# ARCH
|
||||
# SIMD
|
||||
# EVENT_NAME
|
||||
@@ -20,11 +19,12 @@
|
||||
NAME=""
|
||||
|
||||
if [ "${OS}" == "macos" ]; then
|
||||
NAME="PCSX2-${OS}-${GUI_FRAMEWORK}"
|
||||
# MacOS has combined binaries for x64 and ARM64.
|
||||
NAME="PCSX2-${OS}-Qt"
|
||||
elif [[ ("${OS}" == "windows" && "$BUILD_SYSTEM" != "cmake") ]]; then
|
||||
NAME="PCSX2-${OS}-${GUI_FRAMEWORK}-${ARCH}-${SIMD}"
|
||||
NAME="PCSX2-${OS}-Qt-${ARCH}-${SIMD}"
|
||||
else
|
||||
NAME="PCSX2-${OS}-${GUI_FRAMEWORK}-${ARCH}"
|
||||
NAME="PCSX2-${OS}-Qt-${ARCH}"
|
||||
fi
|
||||
|
||||
# Add cmake if used to differentate it from msbuild builds
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
source "$SCRIPTDIR/../linux/functions.sh"
|
||||
|
||||
set -e
|
||||
|
||||
# While we use custom Qt builds for our releases, the Qt6 package will be good enough
|
||||
# for just updating translations. Saves building it for this action alone.
|
||||
retry_command sudo apt-get -y install qt6-l10n-tools
|
||||
|
||||
PATH=/usr/lib/qt6/bin:$PATH "$SCRIPTDIR/../../../../pcsx2-qt/Translations/update_en_translation.sh"
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
APPDIR=$(dirname "$0")
|
||||
exec "$APPDIR/usr/bin/pcsx2-qt" "$@"
|
||||
@@ -40,255 +40,118 @@ NAME=$4
|
||||
|
||||
BINARY=pcsx2-qt
|
||||
APPDIRNAME=PCSX2.AppDir
|
||||
STRIP=llvm-strip-12
|
||||
STRIP=strip
|
||||
|
||||
declare -a SYSLIBS=(
|
||||
"libaio.so.1"
|
||||
"libz.so.1"
|
||||
"libuuid.so.1"
|
||||
"libapparmor.so.1"
|
||||
"libblkid.so.1"
|
||||
"libbsd.so.0"
|
||||
"libdbus-1.so.3"
|
||||
"libgcrypt.so.20"
|
||||
"liblzma.so.5"
|
||||
"libmount.so.1"
|
||||
"libnsl.so.1"
|
||||
"libpcre.so.3"
|
||||
"libselinux.so.1"
|
||||
"libsystemd.so.0"
|
||||
"libudev.so.1"
|
||||
"libwrap.so.0"
|
||||
"libharfbuzz.so.0"
|
||||
"libFLAC.so.8"
|
||||
"libXau.so.6"
|
||||
"libXcomposite.so.1"
|
||||
"libXcursor.so.1"
|
||||
"libXdamage.so.1"
|
||||
"libXdmcp.so.6"
|
||||
"libXext.so.6"
|
||||
"libXfixes.so.3"
|
||||
"libXi.so.6"
|
||||
"libXinerama.so.1"
|
||||
"libXrandr.so.2"
|
||||
"libXrender.so.1"
|
||||
"libXxf86vm.so.1"
|
||||
"libasyncns.so.0"
|
||||
"libcrypto.so.1.1"
|
||||
"libjpeg.so.8"
|
||||
"liblz4.so.1"
|
||||
"libogg.so.0"
|
||||
"libpcap.so.0.8"
|
||||
"libpng16.so.16"
|
||||
"libpulse.so.0"
|
||||
"libsamplerate.so.0"
|
||||
"libsndfile.so.1"
|
||||
"libvorbis.so.0"
|
||||
"libvorbisenc.so.2"
|
||||
"libxcb.so.1"
|
||||
"libxcb-cursor.so.0"
|
||||
"libxcb-render.so.0"
|
||||
"libxcb-shm.so.0"
|
||||
"libxkbcommon.so.0"
|
||||
"libxkbcommon-x11.so.0"
|
||||
"pulseaudio/libpulsecommon-13.99.so"
|
||||
"libasound.so.2"
|
||||
"libfreetype.so.6"
|
||||
"libpcre2-16.so.0"
|
||||
"libexpat.so.1"
|
||||
"libffi.so.7"
|
||||
"libgraphite2.so.3"
|
||||
"libresolv.so.2"
|
||||
"libgpg-error.so.0"
|
||||
"libpcre2-16.so.0"
|
||||
"libpng16.so.16"
|
||||
"libxcb-icccm.so.4"
|
||||
"libxcb-image.so.0"
|
||||
"libxcb-keysyms.so.1"
|
||||
"libxcb-randr.so.0"
|
||||
"libxcb-render.so.0"
|
||||
"libxcb-render-util.so.0"
|
||||
"libxcb-shape.so.0"
|
||||
"libxcb-sync.so.1"
|
||||
"libxcb-util.so.1"
|
||||
"libxcb-xfixes.so.0"
|
||||
"libxcb-xkb.so.1"
|
||||
"libevdev.so.2"
|
||||
"libgudev-1.0.so.0"
|
||||
"libinput.so.10"
|
||||
"libjpeg.so.8"
|
||||
"libmtdev.so.1"
|
||||
"libpng16.so.16"
|
||||
"libudev.so.1"
|
||||
"libuuid.so.1"
|
||||
"libcurl.so.4"
|
||||
"libnghttp2.so.14"
|
||||
"libidn2.so.0"
|
||||
"librtmp.so.1"
|
||||
"libssh.so.4"
|
||||
"libpsl.so.5"
|
||||
"libssl.so.1.1"
|
||||
"libnettle.so.7"
|
||||
"libgnutls.so.30"
|
||||
"libgssapi_krb5.so.2"
|
||||
"libldap_r-2.4.so.2"
|
||||
"liblber-2.4.so.2"
|
||||
"libbrotlidec.so.1"
|
||||
"libunistring.so.2"
|
||||
"libhogweed.so.5"
|
||||
"libgmp.so.10"
|
||||
"libp11-kit.so.0"
|
||||
"libtasn1.so.6"
|
||||
"libkrb5.so.3"
|
||||
"libk5crypto.so.3"
|
||||
"libcom_err.so.2"
|
||||
"libkrb5support.so.0"
|
||||
"libsasl2.so.2"
|
||||
"libgssapi.so.3"
|
||||
"libbrotlicommon.so.1"
|
||||
"libkeyutils.so.1"
|
||||
"libheimntlm.so.0"
|
||||
"libkrb5.so.26"
|
||||
"libasn1.so.8"
|
||||
"libhcrypto.so.4"
|
||||
"libroken.so.18"
|
||||
"libwind.so.0"
|
||||
"libheimbase.so.1"
|
||||
"libhx509.so.5"
|
||||
"libsqlite3.so.0"
|
||||
"libcrypt.so.1"
|
||||
"libdbus-1.so.3"
|
||||
)
|
||||
|
||||
declare -a DEPLIBS=(
|
||||
"libSDL2-2.0.so.0"
|
||||
)
|
||||
|
||||
declare -a QTLIBS=(
|
||||
"libQt6Core.so.6"
|
||||
"libQt6Gui.so.6"
|
||||
"libQt6Network.so.6"
|
||||
"libQt6OpenGL.so.6"
|
||||
"libQt6Svg.so.6"
|
||||
"libQt6WaylandClient.so.6"
|
||||
"libQt6WaylandCompositor.so.6"
|
||||
declare -a MANUAL_QT_LIBS=(
|
||||
"libQt6WaylandEglClientHwIntegration.so.6"
|
||||
"libQt6WaylandEglCompositorHwIntegration.so.6"
|
||||
"libQt6Widgets.so.6"
|
||||
"libQt6XcbQpa.so.6"
|
||||
)
|
||||
|
||||
declare -a QTPLUGINS=(
|
||||
"plugins/iconengines"
|
||||
"plugins/imageformats"
|
||||
"plugins/platforms"
|
||||
#"plugins/platformthemes" # Enable this if we want to ship GTK+ themes at any point.
|
||||
"plugins/tls"
|
||||
"plugins/wayland-decoration-client"
|
||||
"plugins/wayland-graphics-integration-client"
|
||||
"plugins/wayland-graphics-integration-server"
|
||||
"plugins/wayland-shell-integration"
|
||||
"plugins/xcbglintegrations"
|
||||
declare -a MANUAL_QT_PLUGINS=(
|
||||
"wayland-decoration-client"
|
||||
"wayland-graphics-integration-client"
|
||||
"wayland-shell-integration"
|
||||
)
|
||||
|
||||
set -e
|
||||
|
||||
if [ ! -f appimagetool-x86_64.AppImage ]; then
|
||||
retry_command wget -O appimagetool-x86_64.AppImage https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
chmod +x appimagetool-x86_64.AppImage
|
||||
LINUXDEPLOY=./linuxdeploy-x86_64.AppImage
|
||||
LINUXDEPLOY_PLUGIN_QT=./linuxdeploy-plugin-qt-x86_64.AppImage
|
||||
APPIMAGETOOL=./appimagetool-x86_64.AppImage
|
||||
PATCHELF=patchelf
|
||||
|
||||
if [ ! -f "$LINUXDEPLOY" ]; then
|
||||
retry_command wget -O "$LINUXDEPLOY" https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
||||
chmod +x "$LINUXDEPLOY"
|
||||
fi
|
||||
|
||||
if [ ! -f "$LINUXDEPLOY_PLUGIN_QT" ]; then
|
||||
retry_command wget -O "$LINUXDEPLOY_PLUGIN_QT" https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
|
||||
chmod +x "$LINUXDEPLOY_PLUGIN_QT"
|
||||
fi
|
||||
|
||||
if [ ! -f "$APPIMAGETOOL" ]; then
|
||||
retry_command wget -O "$APPIMAGETOOL" https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
|
||||
chmod +x "$APPIMAGETOOL"
|
||||
fi
|
||||
|
||||
OUTDIR=$(realpath "./$APPDIRNAME")
|
||||
SCRIPTDIR=$(dirname "${BASH_SOURCE[0]}")
|
||||
rm -fr "$OUTDIR"
|
||||
mkdir "$OUTDIR"
|
||||
mkdir "$OUTDIR/usr"
|
||||
|
||||
echo "Copying binary and resources..."
|
||||
cp -a "$BUILDDIR/bin" "$OUTDIR/usr"
|
||||
# Why the nastyness? linuxdeploy strips our main binary, and there's no option to turn it off.
|
||||
# It also doesn't strip the Qt libs. We can't strip them after running linuxdeploy, because
|
||||
# patchelf corrupts the libraries (but they still work), but patchelf+strip makes them crash
|
||||
# on load. So, make a backup copy, strip the original (since that's where linuxdeploy finds
|
||||
# the libs to copy), then swap them back after we're done.
|
||||
# Isn't Linux packaging amazing?
|
||||
|
||||
# Get rid of unit tests, we don't want them bloating the squashfs.
|
||||
rm -fv "$OUTDIR"/usr/bin/*_test
|
||||
|
||||
# Patch RPATH so the binary goes hunting for shared libraries in the AppDir instead of system.
|
||||
echo "Patching RPATH in ${BINARY}..."
|
||||
patchelf --set-rpath '$ORIGIN/../lib' "$OUTDIR/usr/bin/$BINARY"
|
||||
|
||||
# Currently we leave the main binary unstripped, uncomment if this is not desired.
|
||||
#$STRIP "$OUTDIR/usr/bin/$BINARY"
|
||||
|
||||
# Libraries we pull in from the system.
|
||||
echo "Copying system libraries..."
|
||||
mkdir -p "$OUTDIR/usr/lib" "$OUTDIR/usr/lib/pulseaudio"
|
||||
for lib in "${SYSLIBS[@]}"; do
|
||||
blib=$(basename "$lib")
|
||||
if [ -f "/lib/x86_64-linux-gnu/$lib" ]; then
|
||||
cp "/lib/x86_64-linux-gnu/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
elif [ -f "$CHROOT/usr/lib/x86_64-linux-gnu/$lib" ]; then
|
||||
cp "$CHROOT/usr/lib/x86_64-linux-gnu/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
elif [ -f "$CHROOT/lib/$lib" ]; then
|
||||
cp "$CHROOT/lib/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
elif [ -f "$CHROOT/usr/lib/$lib" ]; then
|
||||
cp "$CHROOT/usr/lib/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
else
|
||||
echo "*** Failed to find '$blib'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$STRIP "$OUTDIR/usr/lib/$blib"
|
||||
rm -fr "$DEPSDIR.bak"
|
||||
cp -a "$DEPSDIR" "$DEPSDIR.bak"
|
||||
IFS="
|
||||
"
|
||||
for i in $(find "$DEPSDIR" -iname '*.so'); do
|
||||
echo "Stripping deps library ${i}"
|
||||
strip "$i"
|
||||
done
|
||||
|
||||
# Dependencies we built, at this point it's just SDL.
|
||||
echo "Copying dependency libraries..."
|
||||
for lib in "${DEPLIBS[@]}"; do
|
||||
blib=$(basename "$lib")
|
||||
if [ -f "$DEPSDIR/lib/$lib" ]; then
|
||||
cp "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib/$blib"
|
||||
else
|
||||
echo "*** Failed to find '$blib'"
|
||||
exit 1
|
||||
fi
|
||||
echo "Copying desktop file..."
|
||||
cp "$PCSX2DIR/.github/workflows/scripts/linux/pcsx2-qt.desktop" "net.pcsx2.PCSX2.desktop"
|
||||
cp "$PCSX2DIR/bin/resources/icons/AppIconLarge.png" "PCSX2.png"
|
||||
|
||||
$STRIP "$OUTDIR/usr/lib/$blib"
|
||||
echo "Running linuxdeploy to create AppDir..."
|
||||
EXTRA_QT_PLUGINS="core;gui;network;svg;waylandclient;widgets;xcbqpa" \
|
||||
EXTRA_PLATFORM_PLUGINS="libqwayland-egl.so;libqwayland-generic.so" \
|
||||
QMAKE="$DEPSDIR/bin/qmake" \
|
||||
NO_STRIP="1" \
|
||||
$LINUXDEPLOY --plugin qt --appdir="$OUTDIR" --executable="$BUILDDIR/bin/pcsx2-qt" \
|
||||
--desktop-file="net.pcsx2.PCSX2.desktop" --icon-file="PCSX2.png"
|
||||
|
||||
echo "Copying resources into AppDir..."
|
||||
cp -a "$BUILDDIR/bin/resources" "$OUTDIR/usr/bin"
|
||||
|
||||
# LinuxDeploy's Qt plugin doesn't include Wayland support. So manually copy in the additional Wayland libraries.
|
||||
echo "Copying Qt Wayland libraries..."
|
||||
for lib in "${MANUAL_QT_LIBS[@]}"; do
|
||||
srcpath="$DEPSDIR/lib/$lib"
|
||||
dstpath="$OUTDIR/usr/lib/$lib"
|
||||
echo " $srcpath -> $dstpath"
|
||||
cp "$srcpath" "$dstpath"
|
||||
$PATCHELF --set-rpath '$ORIGIN' "$dstpath"
|
||||
done
|
||||
|
||||
echo "Copying Qt libraries..."
|
||||
for lib in "${QTLIBS[@]}"; do
|
||||
cp -aL "$DEPSDIR/lib/$lib" "$OUTDIR/usr/lib"
|
||||
$STRIP "$OUTDIR/usr/lib/$lib"
|
||||
# .. and plugins.
|
||||
echo "Copying Qt Wayland plugins..."
|
||||
for GROUP in "${MANUAL_QT_PLUGINS[@]}"; do
|
||||
srcpath="$DEPSDIR/plugins/$GROUP"
|
||||
dstpath="$OUTDIR/usr/plugins/$GROUP"
|
||||
echo " $srcpath -> $dstpath"
|
||||
mkdir -p "$dstpath"
|
||||
|
||||
for srcsopath in $(find "$DEPSDIR/plugins/$GROUP" -iname '*.so'); do
|
||||
# This is ../../ because it's usually plugins/group/name.so
|
||||
soname=$(basename "$srcsopath")
|
||||
dstsopath="$dstpath/$soname"
|
||||
echo " $srcsopath -> $dstsopath"
|
||||
cp "$srcsopath" "$dstsopath"
|
||||
$PATCHELF --set-rpath '$ORIGIN/../../lib:$ORIGIN' "$dstsopath"
|
||||
done
|
||||
done
|
||||
|
||||
echo "Copying Qt plugins..."
|
||||
mkdir -p "$OUTDIR/usr/lib/plugins"
|
||||
for plugin in "${QTPLUGINS[@]}"; do
|
||||
mkdir -p "$OUTDIR/usr/lib/$plugin"
|
||||
cp -aL "$DEPSDIR/$plugin"/*.so "$OUTDIR/usr/lib/$plugin/"
|
||||
done
|
||||
# Restore unstripped deps (for cache).
|
||||
rm -fr "$DEPSDIR"
|
||||
mv "$DEPSDIR.bak" "$DEPSDIR"
|
||||
|
||||
for so in $(find "$OUTDIR/usr/lib/plugins" -iname '*.so'); do
|
||||
# This is ../../ because it's usually plugins/group/name.so
|
||||
echo "Patching RPATH in ${so}..."
|
||||
patchelf --set-rpath '$ORIGIN/../..' "$so"
|
||||
$STRIP "$so"
|
||||
done
|
||||
# Fix up translations.
|
||||
rm -fr "$OUTDIR/usr/bin/translations"
|
||||
mv "$OUTDIR/usr/translations" "$OUTDIR/usr/bin"
|
||||
cp -a "$BUILDDIR/bin/translations" "$OUTDIR/usr/bin"
|
||||
|
||||
for so in $(find "$OUTDIR/usr/lib" -maxdepth 1); do
|
||||
if [ -f "$so" ]; then
|
||||
echo "Patching RPATH in ${so}"
|
||||
patchelf --set-rpath '$ORIGIN' "$so"
|
||||
fi
|
||||
done
|
||||
# Generate AppStream meta-info.
|
||||
echo "Generating AppStream metainfo..."
|
||||
mkdir -p "$OUTDIR/usr/share/metainfo"
|
||||
"$SCRIPTDIR/generate-metainfo.sh" "$OUTDIR/usr/share/metainfo/net.pcsx2.PCSX2.appdata.xml"
|
||||
|
||||
echo "Creating qt.conf..."
|
||||
cat > "$OUTDIR/usr/bin/qt.conf" << EOF
|
||||
[Paths]
|
||||
Plugins = ../lib/plugins
|
||||
EOF
|
||||
echo "Generating AppImage..."
|
||||
rm -f "$NAME.AppImage"
|
||||
$APPIMAGETOOL -v "$OUTDIR" "$NAME.AppImage"
|
||||
|
||||
echo "Copy desktop/icon..."
|
||||
cp "$PCSX2DIR/bin/resources/icons/AppIconLarge.png" "$OUTDIR/PCSX2.png"
|
||||
cp "$SCRIPTDIR/pcsx2-qt.desktop" "$OUTDIR/PCSX2.desktop"
|
||||
cp "$SCRIPTDIR/AppRun-qt" "$OUTDIR/AppRun"
|
||||
|
||||
echo "Generate AppImage"
|
||||
./appimagetool-x86_64.AppImage -v "$OUTDIR" "$NAME.AppImage"
|
||||
|
||||
@@ -5,7 +5,7 @@ set -e
|
||||
INSTALLDIR="$HOME/deps"
|
||||
NPROCS="$(getconf _NPROCESSORS_ONLN)"
|
||||
SDL=SDL2-2.28.1
|
||||
QT=6.5.0
|
||||
QT=6.5.2
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
|
||||
mkdir -p deps-build
|
||||
@@ -14,17 +14,19 @@ cd deps-build
|
||||
cat > SHASUMS <<EOF
|
||||
4977ceba5c0054dbe6c2f114641aced43ce3bf2b41ea64b6a372d6ba129cb15d $SDL.tar.gz
|
||||
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
|
||||
fde1aa7b4fbe64ec1b4fc576a57f4688ad1453d2fab59cbadd948a10a6eaf5ef qtbase-everywhere-src-$QT.tar.xz
|
||||
64ca7e61f44d51e28bcbb4e0509299b53a9a7e38879e00a7fe91643196067a4f qtsvg-everywhere-src-$QT.tar.xz
|
||||
49c33d96b0a44988be954269b8ce3d1a495b439726e03a6be7c0d50a686369c4 qttools-everywhere-src-$QT.tar.xz
|
||||
fc85d0fd8393f518653ccada1014177a56df6e73f30f3b64eea0c2e4a0067a3d qttranslations-everywhere-src-$QT.tar.xz
|
||||
ccc57fa277fc5f1c1c2c4733eae80a60996b67a067233c47809e542aa31759a3 qtwayland-everywhere-src-$QT.tar.xz
|
||||
3db4c729b4d80a9d8fda8dd77128406353baff4755ca619177eda4cddae71269 qtbase-everywhere-src-$QT.tar.xz
|
||||
aae0c08924c6a5e47f9d57e031673d611ffff7aab2bee2e1cc460471ecac6743 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
48b4cc1093af2e0ab3bea30f60651bddd877a2335d16e7207879a2e9e81963a3 qtsvg-everywhere-src-$QT.tar.xz
|
||||
551ffb22751d8fd4d88e9ebd55b9131f4ca55341ee497fdbbba4da8d10d94341 qttools-everywhere-src-$QT.tar.xz
|
||||
337c45637e757e754c2f0ea65c20de3e6e53a841dda1253db15baa622515beeb qttranslations-everywhere-src-$QT.tar.xz
|
||||
3020be86fb7fd0abb8509906ca6583cadcaee168159abceaeb5b3e9d42563c9a qtwayland-everywhere-src-$QT.tar.xz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
-O "https://libsdl.org/release/$SDL.tar.gz" \
|
||||
-O "https://github.com/ianlancetaylor/libbacktrace/archive/$LIBBACKTRACE.zip" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
@@ -73,6 +75,16 @@ cmake --build . --parallel
|
||||
cmake --install .
|
||||
cd ../../
|
||||
|
||||
echo "Building Qt Image Formats..."
|
||||
tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
|
||||
cd "qtimageformats-everywhere-src-$QT"
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build . --parallel
|
||||
cmake --install .
|
||||
cd ../../
|
||||
|
||||
echo "Building Qt Wayland..."
|
||||
tar xf "qtwayland-everywhere-src-$QT.tar.xz"
|
||||
cd "qtwayland-everywhere-src-$QT"
|
||||
|
||||
@@ -22,7 +22,8 @@
|
||||
"--socket=fallback-x11",
|
||||
"--socket=wayland",
|
||||
"--socket=pulseaudio",
|
||||
"--filesystem=host:ro"
|
||||
"--filesystem=host:ro",
|
||||
"--talk-name=org.freedesktop.ScreenSaver"
|
||||
],
|
||||
"modules": [
|
||||
"modules/10-libpcap.json",
|
||||
|
||||
@@ -49,7 +49,7 @@ retry_command sudo flatpak -y install "${FLATPAK_PACKAGES[@]}"
|
||||
echo "Downloading flat-manager-client"
|
||||
mkdir -p "$FLAT_MANAGER_CLIENT_DIR"
|
||||
pushd "$FLAT_MANAGER_CLIENT_DIR"
|
||||
aria2c -Z "https://raw.githubusercontent.com/flatpak/flat-manager/master/flat-manager-client"
|
||||
aria2c -Z "https://raw.githubusercontent.com/flatpak/flat-manager/9401efbdc0d6bd489507d8401c567ba219d735d5/flat-manager-client"
|
||||
chmod +x flat-manager-client
|
||||
echo "$FLAT_MANAGER_CLIENT_DIR" >> $GITHUB_PATH
|
||||
popd
|
||||
|
||||
@@ -8,14 +8,13 @@ set -e
|
||||
# Packages - Build and Qt
|
||||
declare -a BUILD_PACKAGES=(
|
||||
"build-essential"
|
||||
"g++"
|
||||
"git"
|
||||
"cmake"
|
||||
"ccache"
|
||||
"ninja-build"
|
||||
"libclang-dev" # Qt goes hunting for libclang-11 specifically.
|
||||
"libclang-11-dev"
|
||||
"libclang-12-dev"
|
||||
"patchelf"
|
||||
"libfuse2"
|
||||
"libglib2.0-dev"
|
||||
"libfontconfig1-dev"
|
||||
"libharfbuzz-dev"
|
||||
@@ -64,16 +63,12 @@ declare -a PCSX2_PACKAGES=(
|
||||
"zlib1g-dev"
|
||||
)
|
||||
|
||||
if [ "${COMPILER}" = "gcc" ]; then
|
||||
BUILD_PACKAGES+=("g++-10")
|
||||
else
|
||||
if [ "${COMPILER}" = "clang" ]; then
|
||||
BUILD_PACKAGES+=("llvm-16" "lld-16" "clang-16")
|
||||
|
||||
# Ubuntu 20.04 doesn't ship with LLVM 16, so we need to pull it from the llvm.org repos.
|
||||
# Ubuntu 22.04 doesn't ship with LLVM 16, so we need to pull it from the llvm.org repos.
|
||||
retry_command wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add -
|
||||
sudo apt-add-repository -n 'deb http://apt.llvm.org/focal/ llvm-toolchain-focal-16 main'
|
||||
retry_command sudo apt-get update
|
||||
retry_command sudo apt-get install clang-16 lld-16
|
||||
sudo apt-add-repository -n 'deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-16 main'
|
||||
fi
|
||||
|
||||
retry_command sudo apt-get -qq update && break
|
||||
|
||||
@@ -13,6 +13,11 @@
|
||||
</description>
|
||||
<url type="homepage">https://pcsx2.net/</url>
|
||||
<url type="bugtracker">https://github.com/PCSX2/pcsx2/issues</url>
|
||||
<url type="donation">https://github.com/sponsors/PCSX2</url>
|
||||
<url type="faq">https://pcsx2.net/docs/</url>
|
||||
<url type="help">https://discord.com/invite/TCz3t9k</url>
|
||||
<url type="translate">https://crowdin.com/project/pcsx2-emulator</url>
|
||||
<url type="vcs-browser">https://github.com/PCSX2/pcsx2</url>
|
||||
<screenshots>
|
||||
<screenshot type="default">
|
||||
<image>https://raw.githubusercontent.com/PCSX2/pcsx2/master/.github/workflows/scripts/linux/flatpak/screenshots/screenshot1.png</image>
|
||||
|
||||
@@ -10,7 +10,8 @@ SDL=SDL2-2.28.1
|
||||
PNG=1.6.37
|
||||
JPG=9e
|
||||
SOUNDTOUCH=soundtouch-2.3.1
|
||||
QT=6.4.3
|
||||
FFMPEG=6.0
|
||||
QT=6.4.3 # Currently stuck on Qt 6.4 due to 6.5 requiring macOS 11.0.
|
||||
|
||||
mkdir deps-build
|
||||
cd deps-build
|
||||
@@ -25,7 +26,9 @@ cat > SHASUMS <<EOF
|
||||
505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca libpng-$PNG.tar.xz
|
||||
4077d6a6a75aeb01884f708919d25934c93305e49f7e3f36db9129320e6f4f3d jpegsrc.v$JPG.tar.gz
|
||||
6900996607258496ce126924a19fe9d598af9d892cf3f33d1e4daaa9b42ae0b1 $SOUNDTOUCH.tar.gz
|
||||
57be87c22d9b49c112b6d24bc67d42508660e6b718b3db89c44e47e289137082 ffmpeg-$FFMPEG.tar.xz
|
||||
5087c9e5b0165e7bc3c1a4ab176b35d0cd8f52636aea903fa377bdba00891a60 qtbase-everywhere-src-$QT.tar.xz
|
||||
0aff58062e74b84617c5da8325d8cdad5368d8f4d2a11ceafcd58329fe99b798 qtimageformats-everywhere-src-$QT.tar.xz
|
||||
88315f886cf81898705e487cedba6e6160724359d23c518c92c333c098879a4a qtsvg-everywhere-src-$QT.tar.xz
|
||||
867df829cd5cd3ae8efe62e825503123542764b13c96953511e567df70c5a091 qttools-everywhere-src-$QT.tar.xz
|
||||
79e56b7800d49649a8a8010818538c367a829e0b7a09d5f60bd3aecf5abe972c qttranslations-everywhere-src-$QT.tar.xz
|
||||
@@ -36,7 +39,9 @@ curl -L \
|
||||
-O "https://downloads.sourceforge.net/project/libpng/libpng16/$PNG/libpng-$PNG.tar.xz" \
|
||||
-O "https://www.ijg.org/files/jpegsrc.v$JPG.tar.gz" \
|
||||
-O "https://www.surina.net/soundtouch/$SOUNDTOUCH.tar.gz" \
|
||||
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttools-everywhere-src-$QT.tar.xz" \
|
||||
-O "https://download.qt.io/official_releases/qt/${QT%.*}/$QT/submodules/qttranslations-everywhere-src-$QT.tar.xz" \
|
||||
@@ -75,10 +80,106 @@ make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
|
||||
echo "Installing FFmpeg..."
|
||||
tar xf "ffmpeg-$FFMPEG.tar.xz"
|
||||
cd "ffmpeg-$FFMPEG"
|
||||
./configure --prefix="$INSTALLDIR" --disable-all --disable-autodetect --disable-static --enable-shared \
|
||||
--enable-avcodec --enable-avformat --enable-avutil --enable-swresample --enable-swscale \
|
||||
--enable-audiotoolbox --enable-videotoolbox \
|
||||
--enable-encoder=ffv1,qtrle,pcm_s16be,pcm_s16le,*_at,*_videotoolbox \
|
||||
--enable-muxer=avi,matroska,mov,mp3,mp4,wav \
|
||||
--enable-protocol=file
|
||||
make "-j$NPROCS"
|
||||
make install
|
||||
cd ..
|
||||
|
||||
echo "Installing Qt Base..."
|
||||
tar xf "qtbase-everywhere-src-$QT.tar.xz"
|
||||
cd "qtbase-everywhere-src-$QT"
|
||||
# Qt's panel:shouldEnableURL: implementation does a whole bunch of things that activate macOS's sandbox permissions dialog
|
||||
# Since this is called on every file being displayed in the open/save panel, that spams users with permissions dialogs
|
||||
# Simple solution: Hopefully no one needs any filters that aren't simple file extension filters, remove all other handling
|
||||
patch -u src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm <<EOF
|
||||
--- src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
|
||||
+++ src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
|
||||
@@ -133,7 +133,5 @@
|
||||
NSURL *url = [NSURL fileURLWithPath:filepath isDirectory:info.isDir()];
|
||||
- bool selectable = (m_options->acceptMode() == QFileDialogOptions::AcceptSave)
|
||||
- || [self panel:m_panel shouldEnableURL:url];
|
||||
|
||||
m_panel.directoryURL = [NSURL fileURLWithPath:m_currentDirectory];
|
||||
- m_panel.nameFieldStringValue = selectable ? info.fileName().toNSString() : @"";
|
||||
+ m_panel.nameFieldStringValue = info.fileName().toNSString();
|
||||
|
||||
@@ -203,61 +201,2 @@
|
||||
return hidden;
|
||||
-}
|
||||
-
|
||||
-- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url
|
||||
-{
|
||||
- Q_UNUSED(sender);
|
||||
-
|
||||
- NSString *filename = url.path;
|
||||
- if (!filename.length)
|
||||
- return NO;
|
||||
-
|
||||
- // Always accept directories regardless of their names (unless it is a bundle):
|
||||
- NSFileManager *fm = NSFileManager.defaultManager;
|
||||
- NSDictionary *fileAttrs = [fm attributesOfItemAtPath:filename error:nil];
|
||||
- if (!fileAttrs)
|
||||
- return NO; // Error accessing the file means 'no'.
|
||||
- NSString *fileType = fileAttrs.fileType;
|
||||
- bool isDir = [fileType isEqualToString:NSFileTypeDirectory];
|
||||
- if (isDir) {
|
||||
- if (!m_panel.treatsFilePackagesAsDirectories) {
|
||||
- if ([NSWorkspace.sharedWorkspace isFilePackageAtPath:filename] == NO)
|
||||
- return YES;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- // Treat symbolic links and aliases to directories like directories
|
||||
- QFileInfo fileInfo(QString::fromNSString(filename));
|
||||
- if (fileInfo.isSymLink() && QFileInfo(fileInfo.symLinkTarget()).isDir())
|
||||
- return YES;
|
||||
-
|
||||
- QString qtFileName = fileInfo.fileName();
|
||||
- // No filter means accept everything
|
||||
- bool nameMatches = m_selectedNameFilter->isEmpty();
|
||||
- // Check if the current file name filter accepts the file:
|
||||
- for (int i = 0; !nameMatches && i < m_selectedNameFilter->size(); ++i) {
|
||||
- if (QDir::match(m_selectedNameFilter->at(i), qtFileName))
|
||||
- nameMatches = true;
|
||||
- }
|
||||
- if (!nameMatches)
|
||||
- return NO;
|
||||
-
|
||||
- QDir::Filters filter = m_options->filter();
|
||||
- if ((!(filter & (QDir::Dirs | QDir::AllDirs)) && isDir)
|
||||
- || (!(filter & QDir::Files) && [fileType isEqualToString:NSFileTypeRegular])
|
||||
- || ((filter & QDir::NoSymLinks) && [fileType isEqualToString:NSFileTypeSymbolicLink]))
|
||||
- return NO;
|
||||
-
|
||||
- bool filterPermissions = ((filter & QDir::PermissionMask)
|
||||
- && (filter & QDir::PermissionMask) != QDir::PermissionMask);
|
||||
- if (filterPermissions) {
|
||||
- if ((!(filter & QDir::Readable) && [fm isReadableFileAtPath:filename])
|
||||
- || (!(filter & QDir::Writable) && [fm isWritableFileAtPath:filename])
|
||||
- || (!(filter & QDir::Executable) && [fm isExecutableFileAtPath:filename]))
|
||||
- return NO;
|
||||
- }
|
||||
- if (!(filter & QDir::Hidden)
|
||||
- && (qtFileName.startsWith(u'.') || [self isHiddenFileAtURL:url]))
|
||||
- return NO;
|
||||
-
|
||||
- return YES;
|
||||
}
|
||||
@@ -406,5 +345,2 @@
|
||||
{
|
||||
- if (m_options->acceptMode() != QFileDialogOptions::AcceptSave)
|
||||
- return nil; // panel:shouldEnableURL: does the file filtering for NSOpenPanel
|
||||
-
|
||||
QStringList fileTypes;
|
||||
EOF
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=Release -DFEATURE_optimize_size=ON -DFEATURE_dbus=OFF -DFEATURE_framework=OFF -DFEATURE_icu=OFF -DFEATURE_opengl=OFF -DFEATURE_printsupport=OFF -DFEATURE_sql=OFF -DFEATURE_gssapi=OFF
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
@@ -90,6 +191,13 @@ cmake -B build -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTAL
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
echo "Installing Qt Image Formats..."
|
||||
tar xf "qtimageformats-everywhere-src-$QT.tar.xz"
|
||||
cd "qtimageformats-everywhere-src-$QT"
|
||||
cmake -B build -DCMAKE_PREFIX_PATH="$INSTALLDIR" -DCMAKE_INSTALL_PREFIX="$INSTALLDIR" -DCMAKE_BUILD_TYPE=MinSizeRel
|
||||
make -C build "-j$NPROCS"
|
||||
make -C build install
|
||||
cd ..
|
||||
echo "Installing Qt Tools..."
|
||||
tar xf "qttools-everywhere-src-$QT.tar.xz"
|
||||
cd "qttools-everywhere-src-$QT"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
tag = os.environ['TAG'].split("refs/tags/")[1]
|
||||
tag = os.environ['TAG_VAL']
|
||||
scan_dir = os.environ['SCAN_DIR']
|
||||
output_dir = os.environ['OUT_DIR']
|
||||
accepted_exts = ["AppImage", "flatpak", "tar.xz", "7z"]
|
||||
@@ -13,11 +13,11 @@ for dir_name in os.listdir(scan_dir):
|
||||
asset_name += "-macos"
|
||||
elif "linux" in dir_name.lower():
|
||||
if "flatpak" in dir_name.lower():
|
||||
asset_name += "-linux-Flatpak-64bit"
|
||||
asset_name += "-linux-flatpak-x64"
|
||||
else:
|
||||
asset_name += "-linux-AppImage-64bit"
|
||||
asset_name += "-linux-appimage-x64"
|
||||
elif "windows" in dir_name.lower():
|
||||
asset_name += "-windows-64bit"
|
||||
asset_name += "-windows-x64"
|
||||
else:
|
||||
continue;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
jobName: "MSVC SSE4"
|
||||
configuration: Release
|
||||
simd: "SSE4"
|
||||
secrets: inherit
|
||||
@@ -37,7 +37,7 @@ jobs:
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
jobName: "MSVC AVX2"
|
||||
configuration: Release AVX2
|
||||
secrets: inherit
|
||||
|
||||
@@ -46,7 +46,7 @@ jobs:
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt
|
||||
jobName: "CMake MSVC"
|
||||
configuration: CMake
|
||||
buildSystem: cmake
|
||||
secrets: inherit
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt Clang
|
||||
jobName: "Clang SSE4"
|
||||
configuration: Release Clang
|
||||
simd: "SSE4"
|
||||
secrets: inherit
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt Clang
|
||||
jobName: "Clang AVX2"
|
||||
configuration: Release Clang AVX2
|
||||
secrets: inherit
|
||||
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
if: github.repository != 'PCSX2/pcsx2' || github.event_name == 'pull_request'
|
||||
uses: ./.github/workflows/windows_build_qt.yml
|
||||
with:
|
||||
jobName: Qt Clang
|
||||
jobName: "CMake Clang"
|
||||
configuration: CMake
|
||||
buildSystem: cmake
|
||||
cmakeFlags: -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COMPILER=clang-cl -DPCSX2_EXE_NAME=pcsx2-qt-clang
|
||||
|
||||
@@ -37,10 +37,14 @@ on:
|
||||
required: false
|
||||
type: string
|
||||
default: 3rdparty\qt\6.5.0\msvc2022_64
|
||||
patches_url:
|
||||
patchesUrl:
|
||||
required: false
|
||||
type: string
|
||||
default: https://github.com/PCSX2/pcsx2_patches/releases/latest/download
|
||||
fetchTags:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
build_windows_qt:
|
||||
@@ -57,13 +61,17 @@ jobs:
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
# actions/checkout elides tags, fetch them primarily for releases
|
||||
- name: Fetch Tags
|
||||
if: ${{ inputs.fetchTags }}
|
||||
run: git fetch --tags --no-recurse-submodules
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
shell: bash
|
||||
env:
|
||||
OS: windows
|
||||
BUILD_SYSTEM: ${{ inputs.buildSystem }}
|
||||
GUI_FRAMEWORK: Qt
|
||||
ARCH: ${{ inputs.platform }}
|
||||
SIMD: ${{ inputs.simd }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
@@ -88,7 +96,7 @@ jobs:
|
||||
shell: cmd
|
||||
run: |
|
||||
cd bin/resources
|
||||
aria2c -Z "${{ inputs.patches_url }}/patches.zip"
|
||||
aria2c -Z "${{ inputs.patchesUrl }}/patches.zip"
|
||||
|
||||
- name: Generate CMake
|
||||
if: inputs.configuration == 'CMake'
|
||||
|
||||
Vendored
-63
@@ -1,63 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GSL_ALGORITHM_H
|
||||
#define GSL_ALGORITHM_H
|
||||
|
||||
#include <gsl/assert> // for Expects
|
||||
#include <gsl/span> // for dynamic_extent, span
|
||||
|
||||
#include <algorithm> // for copy_n
|
||||
#include <cstddef> // for ptrdiff_t
|
||||
#include <type_traits> // for is_assignable
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
|
||||
// turn off some warnings that are noisy about our Expects statements
|
||||
#pragma warning(disable : 4127) // conditional expression is constant
|
||||
#pragma warning(disable : 4996) // unsafe use of std::copy_n
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
// Note: this will generate faster code than std::copy using span iterator in older msvc+stl
|
||||
// not necessary for msvc since VS2017 15.8 (_MSC_VER >= 1915)
|
||||
template <class SrcElementType, std::size_t SrcExtent, class DestElementType,
|
||||
std::size_t DestExtent>
|
||||
void copy(span<SrcElementType, SrcExtent> src, span<DestElementType, DestExtent> dest)
|
||||
{
|
||||
static_assert(std::is_assignable<decltype(*dest.data()), decltype(*src.data())>::value,
|
||||
"Elements of source span can not be assigned to elements of destination span");
|
||||
static_assert(SrcExtent == dynamic_extent || DestExtent == dynamic_extent ||
|
||||
(SrcExtent <= DestExtent),
|
||||
"Source range is longer than target range");
|
||||
|
||||
Expects(dest.size() >= src.size());
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(stl.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
std::copy_n(src.data(), src.size(), dest.data());
|
||||
}
|
||||
|
||||
} // namespace gsl
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#endif // GSL_ALGORITHM_H
|
||||
Vendored
-136
@@ -1,136 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GSL_CONTRACTS_H
|
||||
#define GSL_CONTRACTS_H
|
||||
|
||||
//
|
||||
// Temporary until MSVC STL supports no-exceptions mode.
|
||||
// Currently terminate is a no-op in this mode, so we add termination behavior back
|
||||
//
|
||||
#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
|
||||
#define GSL_KERNEL_MODE
|
||||
|
||||
#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
|
||||
#include <intrin.h>
|
||||
#define RANGE_CHECKS_FAILURE 0
|
||||
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Winvalid-noreturn"
|
||||
#endif // defined(__clang__)
|
||||
|
||||
#else // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) &&
|
||||
// !_HAS_EXCEPTIONS))
|
||||
|
||||
#include <exception>
|
||||
|
||||
#endif // defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) &&
|
||||
// !_HAS_EXCEPTIONS))
|
||||
|
||||
//
|
||||
// make suppress attributes parse for some compilers
|
||||
// Hopefully temporary until suppression standardization occurs
|
||||
//
|
||||
#if defined(__clang__)
|
||||
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
|
||||
#else
|
||||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
|
||||
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
|
||||
#else
|
||||
#define GSL_SUPPRESS(x)
|
||||
#endif // _MSC_VER
|
||||
#endif // __clang__
|
||||
|
||||
#define GSL_STRINGIFY_DETAIL(x) #x
|
||||
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
|
||||
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#define GSL_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#define GSL_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
#else
|
||||
|
||||
#define GSL_LIKELY(x) (!!(x))
|
||||
#define GSL_UNLIKELY(x) (!!(x))
|
||||
#endif // defined(__clang__) || defined(__GNUC__)
|
||||
|
||||
//
|
||||
// GSL_ASSUME(cond)
|
||||
//
|
||||
// Tell the optimizer that the predicate cond must hold. It is unspecified
|
||||
// whether or not cond is actually evaluated.
|
||||
//
|
||||
#ifdef _MSC_VER
|
||||
#define GSL_ASSUME(cond) __assume(cond)
|
||||
#elif defined(__GNUC__)
|
||||
#define GSL_ASSUME(cond) ((cond) ? static_cast<void>(0) : __builtin_unreachable())
|
||||
#else
|
||||
#define GSL_ASSUME(cond) static_cast<void>((cond) ? 0 : 0)
|
||||
#endif
|
||||
|
||||
//
|
||||
// GSL.assert: assertions
|
||||
//
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
|
||||
namespace details
|
||||
{
|
||||
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
|
||||
|
||||
typedef void(__cdecl* terminate_handler)();
|
||||
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
[[noreturn]] inline void __cdecl default_terminate_handler()
|
||||
{
|
||||
__fastfail(RANGE_CHECKS_FAILURE);
|
||||
}
|
||||
|
||||
inline gsl::details::terminate_handler& get_terminate_handler() noexcept
|
||||
{
|
||||
static terminate_handler handler = &default_terminate_handler;
|
||||
return handler;
|
||||
}
|
||||
|
||||
#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
|
||||
|
||||
[[noreturn]] inline void terminate() noexcept
|
||||
{
|
||||
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
|
||||
(*gsl::details::get_terminate_handler())();
|
||||
#else
|
||||
std::terminate();
|
||||
#endif // defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND)
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace gsl
|
||||
|
||||
#define GSL_CONTRACT_CHECK(type, cond) \
|
||||
(GSL_LIKELY(cond) ? static_cast<void>(0) : gsl::details::terminate())
|
||||
|
||||
#define Expects(cond) GSL_CONTRACT_CHECK("Precondition", cond)
|
||||
#define Ensures(cond) GSL_CONTRACT_CHECK("Postcondition", cond)
|
||||
|
||||
#if defined(GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND) && defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // GSL_CONTRACTS_H
|
||||
Vendored
-213
@@ -1,213 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GSL_BYTE_H
|
||||
#define GSL_BYTE_H
|
||||
|
||||
//
|
||||
// make suppress attributes work for some compilers
|
||||
// Hopefully temporary until suppression standardization occurs
|
||||
//
|
||||
#if defined(__clang__)
|
||||
#define GSL_SUPPRESS(x) [[gsl::suppress("x")]]
|
||||
#else
|
||||
#if defined(_MSC_VER) && !defined(__INTEL_COMPILER)
|
||||
#define GSL_SUPPRESS(x) [[gsl::suppress(x)]]
|
||||
#else
|
||||
#define GSL_SUPPRESS(x)
|
||||
#endif // _MSC_VER
|
||||
#endif // __clang__
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
// VS2017 15.8 added support for the __cpp_lib_byte definition
|
||||
// To do: drop _HAS_STD_BYTE when support for pre 15.8 expires
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#pragma warning(push)
|
||||
|
||||
// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
|
||||
#pragma warning(disable : 26493) // don't use c-style casts // TODO: MSVC suppression in templates
|
||||
// does not always work
|
||||
|
||||
#ifndef GSL_USE_STD_BYTE
|
||||
// this tests if we are under MSVC and the standard lib has std::byte and it is enabled
|
||||
#if (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || \
|
||||
(defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603)
|
||||
|
||||
#define GSL_USE_STD_BYTE 1
|
||||
|
||||
#else // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >=
|
||||
// 201603)
|
||||
|
||||
#define GSL_USE_STD_BYTE 0
|
||||
|
||||
#endif // (defined(_HAS_STD_BYTE) && _HAS_STD_BYTE) || (defined(__cpp_lib_byte) && __cpp_lib_byte >=
|
||||
// 201603)
|
||||
#endif // GSL_USE_STD_BYTE
|
||||
|
||||
#else // _MSC_VER
|
||||
|
||||
#ifndef GSL_USE_STD_BYTE
|
||||
#include <cstddef> /* __cpp_lib_byte */
|
||||
// this tests if we are under GCC or Clang with enough -std=c++1z power to get us std::byte
|
||||
// also check if libc++ version is sufficient (> 5.0) or libstdc++ actually contains std::byte
|
||||
#if defined(__cplusplus) && (__cplusplus >= 201703L) && \
|
||||
(defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) || \
|
||||
defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
|
||||
|
||||
#define GSL_USE_STD_BYTE 1
|
||||
|
||||
#else // defined(__cplusplus) && (__cplusplus >= 201703L) &&
|
||||
// (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
|
||||
// defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
|
||||
|
||||
#define GSL_USE_STD_BYTE 0
|
||||
|
||||
#endif // defined(__cplusplus) && (__cplusplus >= 201703L) &&
|
||||
// (defined(__cpp_lib_byte) && (__cpp_lib_byte >= 201603) ||
|
||||
// defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 5000))
|
||||
#endif // GSL_USE_STD_BYTE
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
// Use __may_alias__ attribute on gcc and clang
|
||||
#if defined __clang__ || (defined(__GNUC__) && __GNUC__ > 5)
|
||||
#define byte_may_alias __attribute__((__may_alias__))
|
||||
#else // defined __clang__ || defined __GNUC__
|
||||
#define byte_may_alias
|
||||
#endif // defined __clang__ || defined __GNUC__
|
||||
|
||||
#if GSL_USE_STD_BYTE
|
||||
#include <cstddef>
|
||||
#endif
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
#if GSL_USE_STD_BYTE
|
||||
|
||||
using std::byte;
|
||||
using std::to_integer;
|
||||
|
||||
#else // GSL_USE_STD_BYTE
|
||||
|
||||
// This is a simple definition for now that allows
|
||||
// use of byte within span<> to be standards-compliant
|
||||
enum class byte_may_alias byte : unsigned char
|
||||
{
|
||||
};
|
||||
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte& operator<<=(byte& b, IntegerType shift) noexcept
|
||||
{
|
||||
return b = byte(static_cast<unsigned char>(b) << shift);
|
||||
}
|
||||
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte operator<<(byte b, IntegerType shift) noexcept
|
||||
{
|
||||
return byte(static_cast<unsigned char>(b) << shift);
|
||||
}
|
||||
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte& operator>>=(byte& b, IntegerType shift) noexcept
|
||||
{
|
||||
return b = byte(static_cast<unsigned char>(b) >> shift);
|
||||
}
|
||||
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr byte operator>>(byte b, IntegerType shift) noexcept
|
||||
{
|
||||
return byte(static_cast<unsigned char>(b) >> shift);
|
||||
}
|
||||
|
||||
constexpr byte& operator|=(byte& l, byte r) noexcept
|
||||
{
|
||||
return l = byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
|
||||
}
|
||||
|
||||
constexpr byte operator|(byte l, byte r) noexcept
|
||||
{
|
||||
return byte(static_cast<unsigned char>(l) | static_cast<unsigned char>(r));
|
||||
}
|
||||
|
||||
constexpr byte& operator&=(byte& l, byte r) noexcept
|
||||
{
|
||||
return l = byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
|
||||
}
|
||||
|
||||
constexpr byte operator&(byte l, byte r) noexcept
|
||||
{
|
||||
return byte(static_cast<unsigned char>(l) & static_cast<unsigned char>(r));
|
||||
}
|
||||
|
||||
constexpr byte& operator^=(byte& l, byte r) noexcept
|
||||
{
|
||||
return l = byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
|
||||
}
|
||||
|
||||
constexpr byte operator^(byte l, byte r) noexcept
|
||||
{
|
||||
return byte(static_cast<unsigned char>(l) ^ static_cast<unsigned char>(r));
|
||||
}
|
||||
|
||||
constexpr byte operator~(byte b) noexcept { return byte(~static_cast<unsigned char>(b)); }
|
||||
|
||||
template <class IntegerType, class = std::enable_if_t<std::is_integral<IntegerType>::value>>
|
||||
constexpr IntegerType to_integer(byte b) noexcept
|
||||
{
|
||||
return static_cast<IntegerType>(b);
|
||||
}
|
||||
|
||||
#endif // GSL_USE_STD_BYTE
|
||||
|
||||
template <bool E, typename T>
|
||||
constexpr byte to_byte_impl(T t) noexcept
|
||||
{
|
||||
static_assert(
|
||||
E, "gsl::to_byte(t) must be provided an unsigned char, otherwise data loss may occur. "
|
||||
"If you are calling to_byte with an integer contant use: gsl::to_byte<t>() version.");
|
||||
return static_cast<byte>(t);
|
||||
}
|
||||
template <>
|
||||
// NOTE: need suppression since c++14 does not allow "return {t}"
|
||||
// GSL_SUPPRESS(type.4) // NO-FORMAT: attribute // TODO: suppression does not work
|
||||
constexpr byte to_byte_impl<true, unsigned char>(unsigned char t) noexcept
|
||||
{
|
||||
return byte(t);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr byte to_byte(T t) noexcept
|
||||
{
|
||||
return to_byte_impl<std::is_same<T, unsigned char>::value, T>(t);
|
||||
}
|
||||
|
||||
template <int I>
|
||||
constexpr byte to_byte() noexcept
|
||||
{
|
||||
static_assert(I >= 0 && I <= 255,
|
||||
"gsl::byte only has 8 bits of storage, values must be in range 0-255");
|
||||
return static_cast<byte>(I);
|
||||
}
|
||||
|
||||
} // namespace gsl
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#endif // GSL_BYTE_H
|
||||
Vendored
-32
@@ -1,32 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GSL_GSL_H
|
||||
#define GSL_GSL_H
|
||||
|
||||
#include <gsl/algorithm> // copy
|
||||
#include <gsl/assert> // Ensures/Expects
|
||||
#include <gsl/byte> // byte
|
||||
#include <gsl/pointers> // owner, not_null
|
||||
#include <gsl/span> // span
|
||||
#include <gsl/string_span> // zstring, string_span, zstring_builder...
|
||||
#include <gsl/util> // finally()/narrow_cast()...
|
||||
|
||||
#ifdef __cpp_exceptions
|
||||
#include <gsl/narrow> // narrow()
|
||||
#endif
|
||||
|
||||
#endif // GSL_GSL_H
|
||||
Vendored
-4
@@ -1,4 +0,0 @@
|
||||
#pragma once
|
||||
#pragma message( \
|
||||
"This header will soon be removed. Use <gsl/algorithm> instead of <gsl/gsl_algorithm>")
|
||||
#include <gsl/algorithm>
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
#pragma message("This header will soon be removed. Use <gsl/assert> instead of <gsl/gsl_assert>")
|
||||
#include <gsl/assert>
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
#pragma message("This header will soon be removed. Use <gsl/byte> instead of <gsl/gsl_byte>")
|
||||
#include <gsl/byte>
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
#pragma message("This header will soon be removed. Use <gsl/narrow> instead of <gsl/gsl_narrow>")
|
||||
#include <gsl/narrow>
|
||||
Vendored
-3
@@ -1,3 +0,0 @@
|
||||
#pragma once
|
||||
#pragma message("This header will soon be removed. Use <gsl/util> instead of <gsl/gsl_util>")
|
||||
#include <gsl/util>
|
||||
Vendored
-71
@@ -1,71 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GSL_NARROW_H
|
||||
#define GSL_NARROW_H
|
||||
#include <gsl/assert> // for Expects
|
||||
#include <gsl/util> // for narrow_cast
|
||||
namespace gsl
|
||||
{
|
||||
struct narrowing_error : public std::exception
|
||||
{
|
||||
const char* what() const noexcept override { return "narrowing_error"; }
|
||||
};
|
||||
|
||||
// narrow() : a checked version of narrow_cast() that throws if the cast changed the value
|
||||
template <class T, class U, typename std::enable_if<std::is_arithmetic<T>::value>::type* = nullptr>
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
|
||||
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
|
||||
// clang-format on
|
||||
constexpr T narrow(U u) noexcept(false)
|
||||
{
|
||||
constexpr const bool is_different_signedness =
|
||||
(std::is_signed<T>::value != std::is_signed<U>::value);
|
||||
|
||||
GSL_SUPPRESS(es.103) // NO-FORMAT: attribute // don't overflow
|
||||
GSL_SUPPRESS(es.104) // NO-FORMAT: attribute // don't underflow
|
||||
GSL_SUPPRESS(p.2) // NO-FORMAT: attribute // don't rely on undefined behavior
|
||||
const T t = narrow_cast<T>(u); // While this is technically undefined behavior in some cases (i.e., if the source value is of floating-point type
|
||||
// and cannot fit into the destination integral type), the resultant behavior is benign on the platforms
|
||||
// that we target (i.e., no hardware trap representations are hit).
|
||||
|
||||
if (static_cast<U>(t) != u || (is_different_signedness && ((t < T{}) != (u < U{}))))
|
||||
{
|
||||
throw narrowing_error{};
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
template <class T, class U, typename std::enable_if<!std::is_arithmetic<T>::value>::type* = nullptr>
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
|
||||
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
|
||||
// clang-format on
|
||||
constexpr T narrow(U u) noexcept(false)
|
||||
{
|
||||
const T t = narrow_cast<T>(u);
|
||||
|
||||
if (static_cast<U>(t) != u)
|
||||
{
|
||||
throw narrowing_error{};
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
} // namespace gsl
|
||||
#endif // GSL_NARROW_H
|
||||
Vendored
-323
@@ -1,323 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GSL_POINTERS_H
|
||||
#define GSL_POINTERS_H
|
||||
|
||||
#include <gsl/assert> // for Ensures, Expects
|
||||
|
||||
#include <algorithm> // for forward
|
||||
#include <cstddef> // for ptrdiff_t, nullptr_t, size_t
|
||||
#include <memory> // for shared_ptr, unique_ptr
|
||||
#include <system_error> // for hash
|
||||
#include <type_traits> // for enable_if_t, is_convertible, is_assignable
|
||||
|
||||
#if !defined(GSL_NO_IOSTREAMS)
|
||||
#include <iosfwd> // for ostream
|
||||
#endif // !defined(GSL_NO_IOSTREAMS)
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
|
||||
namespace details
|
||||
{
|
||||
template <typename T, typename = void>
|
||||
struct is_comparable_to_nullptr : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct is_comparable_to_nullptr<
|
||||
T,
|
||||
std::enable_if_t<std::is_convertible<decltype(std::declval<T>() != nullptr), bool>::value>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
} // namespace details
|
||||
|
||||
//
|
||||
// GSL.owner: ownership pointers
|
||||
//
|
||||
using std::shared_ptr;
|
||||
using std::unique_ptr;
|
||||
|
||||
//
|
||||
// owner
|
||||
//
|
||||
// owner<T> is designed as a bridge for code that must deal directly with owning pointers for some
|
||||
// reason
|
||||
//
|
||||
// T must be a pointer type
|
||||
// - disallow construction from any type other than pointer type
|
||||
//
|
||||
template <class T, class = std::enable_if_t<std::is_pointer<T>::value>>
|
||||
using owner = T;
|
||||
|
||||
//
|
||||
// not_null
|
||||
//
|
||||
// Restricts a pointer or smart pointer to only hold non-null values.
|
||||
//
|
||||
// Has zero size overhead over T.
|
||||
//
|
||||
// If T is a pointer (i.e. T == U*) then
|
||||
// - allow construction from U*
|
||||
// - disallow construction from nullptr_t
|
||||
// - disallow default construction
|
||||
// - ensure construction from null U* fails
|
||||
// - allow implicit conversion to U*
|
||||
//
|
||||
template <class T>
|
||||
class not_null
|
||||
{
|
||||
public:
|
||||
static_assert(details::is_comparable_to_nullptr<T>::value, "T cannot be compared to nullptr.");
|
||||
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
|
||||
constexpr not_null(U&& u) : ptr_(std::forward<U>(u))
|
||||
{
|
||||
Expects(ptr_ != nullptr);
|
||||
}
|
||||
|
||||
template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
|
||||
constexpr not_null(T u) : ptr_(std::move(u))
|
||||
{
|
||||
Expects(ptr_ != nullptr);
|
||||
}
|
||||
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
|
||||
constexpr not_null(const not_null<U>& other) : not_null(other.get())
|
||||
{}
|
||||
|
||||
not_null(const not_null& other) = default;
|
||||
not_null& operator=(const not_null& other) = default;
|
||||
constexpr std::conditional_t<std::is_copy_constructible<T>::value, T, const T&> get() const
|
||||
{
|
||||
Ensures(ptr_ != nullptr);
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
constexpr operator T() const { return get(); }
|
||||
constexpr decltype(auto) operator->() const { return get(); }
|
||||
constexpr decltype(auto) operator*() const { return *get(); }
|
||||
|
||||
// prevents compilation when someone attempts to assign a null pointer constant
|
||||
not_null(std::nullptr_t) = delete;
|
||||
not_null& operator=(std::nullptr_t) = delete;
|
||||
|
||||
// unwanted operators...pointers only point to single objects!
|
||||
not_null& operator++() = delete;
|
||||
not_null& operator--() = delete;
|
||||
not_null operator++(int) = delete;
|
||||
not_null operator--(int) = delete;
|
||||
not_null& operator+=(std::ptrdiff_t) = delete;
|
||||
not_null& operator-=(std::ptrdiff_t) = delete;
|
||||
void operator[](std::ptrdiff_t) const = delete;
|
||||
|
||||
private:
|
||||
T ptr_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
auto make_not_null(T&& t) noexcept
|
||||
{
|
||||
return not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
|
||||
}
|
||||
|
||||
#if !defined(GSL_NO_IOSTREAMS)
|
||||
template <class T>
|
||||
std::ostream& operator<<(std::ostream& os, const not_null<T>& val)
|
||||
{
|
||||
os << val.get();
|
||||
return os;
|
||||
}
|
||||
#endif // !defined(GSL_NO_IOSTREAMS)
|
||||
|
||||
template <class T, class U>
|
||||
auto operator==(const not_null<T>& lhs,
|
||||
const not_null<U>& rhs) noexcept(noexcept(lhs.get() == rhs.get()))
|
||||
-> decltype(lhs.get() == rhs.get())
|
||||
{
|
||||
return lhs.get() == rhs.get();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
auto operator!=(const not_null<T>& lhs,
|
||||
const not_null<U>& rhs) noexcept(noexcept(lhs.get() != rhs.get()))
|
||||
-> decltype(lhs.get() != rhs.get())
|
||||
{
|
||||
return lhs.get() != rhs.get();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
auto operator<(const not_null<T>& lhs,
|
||||
const not_null<U>& rhs) noexcept(noexcept(lhs.get() < rhs.get()))
|
||||
-> decltype(lhs.get() < rhs.get())
|
||||
{
|
||||
return lhs.get() < rhs.get();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
auto operator<=(const not_null<T>& lhs,
|
||||
const not_null<U>& rhs) noexcept(noexcept(lhs.get() <= rhs.get()))
|
||||
-> decltype(lhs.get() <= rhs.get())
|
||||
{
|
||||
return lhs.get() <= rhs.get();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
auto operator>(const not_null<T>& lhs,
|
||||
const not_null<U>& rhs) noexcept(noexcept(lhs.get() > rhs.get()))
|
||||
-> decltype(lhs.get() > rhs.get())
|
||||
{
|
||||
return lhs.get() > rhs.get();
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
auto operator>=(const not_null<T>& lhs,
|
||||
const not_null<U>& rhs) noexcept(noexcept(lhs.get() >= rhs.get()))
|
||||
-> decltype(lhs.get() >= rhs.get())
|
||||
{
|
||||
return lhs.get() >= rhs.get();
|
||||
}
|
||||
|
||||
// more unwanted operators
|
||||
template <class T, class U>
|
||||
std::ptrdiff_t operator-(const not_null<T>&, const not_null<U>&) = delete;
|
||||
template <class T>
|
||||
not_null<T> operator-(const not_null<T>&, std::ptrdiff_t) = delete;
|
||||
template <class T>
|
||||
not_null<T> operator+(const not_null<T>&, std::ptrdiff_t) = delete;
|
||||
template <class T>
|
||||
not_null<T> operator+(std::ptrdiff_t, const not_null<T>&) = delete;
|
||||
|
||||
} // namespace gsl
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class T>
|
||||
struct hash<gsl::not_null<T>>
|
||||
{
|
||||
std::size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value.get()); }
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
|
||||
//
|
||||
// strict_not_null
|
||||
//
|
||||
// Restricts a pointer or smart pointer to only hold non-null values,
|
||||
//
|
||||
// - provides a strict (i.e. explicit constructor from T) wrapper of not_null
|
||||
// - to be used for new code that wishes the design to be cleaner and make not_null
|
||||
// checks intentional, or in old code that would like to make the transition.
|
||||
//
|
||||
// To make the transition from not_null, incrementally replace not_null
|
||||
// by strict_not_null and fix compilation errors
|
||||
//
|
||||
// Expect to
|
||||
// - remove all unneeded conversions from raw pointer to not_null and back
|
||||
// - make API clear by specifying not_null in parameters where needed
|
||||
// - remove unnecessary asserts
|
||||
//
|
||||
template <class T>
|
||||
class strict_not_null : public not_null<T>
|
||||
{
|
||||
public:
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
|
||||
constexpr explicit strict_not_null(U&& u) : not_null<T>(std::forward<U>(u))
|
||||
{}
|
||||
|
||||
template <typename = std::enable_if_t<!std::is_same<std::nullptr_t, T>::value>>
|
||||
constexpr explicit strict_not_null(T u) : not_null<T>(u)
|
||||
{}
|
||||
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
|
||||
constexpr strict_not_null(const not_null<U>& other) : not_null<T>(other)
|
||||
{}
|
||||
|
||||
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
|
||||
constexpr strict_not_null(const strict_not_null<U>& other) : not_null<T>(other)
|
||||
{}
|
||||
|
||||
strict_not_null(strict_not_null&& other) = default;
|
||||
strict_not_null(const strict_not_null& other) = default;
|
||||
strict_not_null& operator=(const strict_not_null& other) = default;
|
||||
strict_not_null& operator=(const not_null<T>& other)
|
||||
{
|
||||
not_null<T>::operator=(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// prevents compilation when someone attempts to assign a null pointer constant
|
||||
strict_not_null(std::nullptr_t) = delete;
|
||||
strict_not_null& operator=(std::nullptr_t) = delete;
|
||||
|
||||
// unwanted operators...pointers only point to single objects!
|
||||
strict_not_null& operator++() = delete;
|
||||
strict_not_null& operator--() = delete;
|
||||
strict_not_null operator++(int) = delete;
|
||||
strict_not_null operator--(int) = delete;
|
||||
strict_not_null& operator+=(std::ptrdiff_t) = delete;
|
||||
strict_not_null& operator-=(std::ptrdiff_t) = delete;
|
||||
void operator[](std::ptrdiff_t) const = delete;
|
||||
};
|
||||
|
||||
// more unwanted operators
|
||||
template <class T, class U>
|
||||
std::ptrdiff_t operator-(const strict_not_null<T>&, const strict_not_null<U>&) = delete;
|
||||
template <class T>
|
||||
strict_not_null<T> operator-(const strict_not_null<T>&, std::ptrdiff_t) = delete;
|
||||
template <class T>
|
||||
strict_not_null<T> operator+(const strict_not_null<T>&, std::ptrdiff_t) = delete;
|
||||
template <class T>
|
||||
strict_not_null<T> operator+(std::ptrdiff_t, const strict_not_null<T>&) = delete;
|
||||
|
||||
template <class T>
|
||||
auto make_strict_not_null(T&& t) noexcept
|
||||
{
|
||||
return strict_not_null<std::remove_cv_t<std::remove_reference_t<T>>>{std::forward<T>(t)};
|
||||
}
|
||||
|
||||
#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
|
||||
|
||||
// deduction guides to prevent the ctad-maybe-unsupported warning
|
||||
template <class T>
|
||||
not_null(T) -> not_null<T>;
|
||||
template <class T>
|
||||
strict_not_null(T) -> strict_not_null<T>;
|
||||
|
||||
#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) )
|
||||
|
||||
} // namespace gsl
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <class T>
|
||||
struct hash<gsl::strict_not_null<T>>
|
||||
{
|
||||
std::size_t operator()(const gsl::strict_not_null<T>& value) const
|
||||
{
|
||||
return hash<T>{}(value.get());
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // GSL_POINTERS_H
|
||||
Vendored
-821
@@ -1,821 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GSL_SPAN_H
|
||||
#define GSL_SPAN_H
|
||||
|
||||
#include <gsl/assert> // for Expects
|
||||
#include <gsl/byte> // for byte
|
||||
#include <gsl/util> // for narrow_cast
|
||||
|
||||
#include <array> // for array
|
||||
#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
|
||||
#include <gsl/span_ext> // for span specialization of gsl::at and other span-related extensions
|
||||
#include <iterator> // for reverse_iterator, distance, random_access_...
|
||||
#include <type_traits> // for enable_if_t, declval, is_convertible, inte...
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma warning(push)
|
||||
|
||||
// turn off some warnings that are noisy about our Expects statements
|
||||
#pragma warning(disable : 4127) // conditional expression is constant
|
||||
#pragma warning( \
|
||||
disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
|
||||
#pragma warning(disable : 4702) // unreachable code
|
||||
|
||||
// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
|
||||
#pragma warning(disable : 26495) // uninitalized member when constructor calls constructor
|
||||
#pragma warning(disable : 26446) // parser bug does not allow attributes on some templates
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
// See if we have enough C++17 power to use a static constexpr data member
|
||||
// without needing an out-of-line definition
|
||||
#if !(defined(__cplusplus) && (__cplusplus >= 201703L))
|
||||
#define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
|
||||
#endif // !(defined(__cplusplus) && (__cplusplus >= 201703L))
|
||||
|
||||
// GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t)
|
||||
// While there is a conversion from signed to unsigned, it happens at
|
||||
// compiletime, so the compiler wouldn't have to warn indiscriminately, but
|
||||
// could check if the source value actually doesn't fit into the target type
|
||||
// and only warn in those cases.
|
||||
#if defined(__GNUC__) && __GNUC__ > 6
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
|
||||
// implementation details
|
||||
namespace details
|
||||
{
|
||||
template <class T>
|
||||
struct is_span_oracle : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
struct is_span_oracle<gsl::span<ElementType, Extent>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_span : public is_span_oracle<std::remove_cv_t<T>>
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_std_array_oracle : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
struct is_std_array_oracle<std::array<ElementType, Extent>> : std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct is_std_array : is_std_array_oracle<std::remove_cv_t<T>>
|
||||
{
|
||||
};
|
||||
|
||||
template <std::size_t From, std::size_t To>
|
||||
struct is_allowed_extent_conversion
|
||||
: std::integral_constant<bool, From == To || To == dynamic_extent>
|
||||
{
|
||||
};
|
||||
|
||||
template <class From, class To>
|
||||
struct is_allowed_element_type_conversion
|
||||
: std::integral_constant<bool, std::is_convertible<From (*)[], To (*)[]>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template <class Type>
|
||||
class span_iterator
|
||||
{
|
||||
public:
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using value_type = std::remove_cv_t<Type>;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = Type*;
|
||||
using reference = Type&;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
using _Unchecked_type = pointer;
|
||||
#endif // _MSC_VER
|
||||
constexpr span_iterator() = default;
|
||||
|
||||
constexpr span_iterator(pointer begin, pointer end, pointer current)
|
||||
: begin_(begin), end_(end), current_(current)
|
||||
{}
|
||||
|
||||
constexpr operator span_iterator<const Type>() const noexcept
|
||||
{
|
||||
return {begin_, end_, current_};
|
||||
}
|
||||
|
||||
constexpr reference operator*() const noexcept
|
||||
{
|
||||
Expects(begin_ && end_);
|
||||
Expects(begin_ <= current_ && current_ < end_);
|
||||
return *current_;
|
||||
}
|
||||
|
||||
constexpr pointer operator->() const noexcept
|
||||
{
|
||||
Expects(begin_ && end_);
|
||||
Expects(begin_ <= current_ && current_ < end_);
|
||||
return current_;
|
||||
}
|
||||
constexpr span_iterator& operator++() noexcept
|
||||
{
|
||||
Expects(begin_ && current_ && end_);
|
||||
Expects(current_ < end_);
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
++current_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr span_iterator operator++(int) noexcept
|
||||
{
|
||||
span_iterator ret = *this;
|
||||
++*this;
|
||||
return ret;
|
||||
}
|
||||
|
||||
constexpr span_iterator& operator--() noexcept
|
||||
{
|
||||
Expects(begin_ && end_);
|
||||
Expects(begin_ < current_);
|
||||
--current_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr span_iterator operator--(int) noexcept
|
||||
{
|
||||
span_iterator ret = *this;
|
||||
--*this;
|
||||
return ret;
|
||||
}
|
||||
|
||||
constexpr span_iterator& operator+=(const difference_type n) noexcept
|
||||
{
|
||||
if (n != 0) Expects(begin_ && current_ && end_);
|
||||
if (n > 0) Expects(end_ - current_ >= n);
|
||||
if (n < 0) Expects(current_ - begin_ >= -n);
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
current_ += n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr span_iterator operator+(const difference_type n) const noexcept
|
||||
{
|
||||
span_iterator ret = *this;
|
||||
ret += n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
friend constexpr span_iterator operator+(const difference_type n,
|
||||
const span_iterator& rhs) noexcept
|
||||
{
|
||||
return rhs + n;
|
||||
}
|
||||
|
||||
constexpr span_iterator& operator-=(const difference_type n) noexcept
|
||||
{
|
||||
if (n != 0) Expects(begin_ && current_ && end_);
|
||||
if (n > 0) Expects(current_ - begin_ >= n);
|
||||
if (n < 0) Expects(end_ - current_ >= -n);
|
||||
current_ -= n;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr span_iterator operator-(const difference_type n) const noexcept
|
||||
{
|
||||
span_iterator ret = *this;
|
||||
ret -= n;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <
|
||||
class Type2,
|
||||
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
|
||||
constexpr difference_type operator-(const span_iterator<Type2>& rhs) const noexcept
|
||||
{
|
||||
Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
|
||||
return current_ - rhs.current_;
|
||||
}
|
||||
|
||||
constexpr reference operator[](const difference_type n) const noexcept
|
||||
{
|
||||
return *(*this + n);
|
||||
}
|
||||
|
||||
template <
|
||||
class Type2,
|
||||
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
|
||||
constexpr bool operator==(const span_iterator<Type2>& rhs) const noexcept
|
||||
{
|
||||
Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
|
||||
return current_ == rhs.current_;
|
||||
}
|
||||
|
||||
template <
|
||||
class Type2,
|
||||
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
|
||||
constexpr bool operator!=(const span_iterator<Type2>& rhs) const noexcept
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
template <
|
||||
class Type2,
|
||||
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
|
||||
constexpr bool operator<(const span_iterator<Type2>& rhs) const noexcept
|
||||
{
|
||||
Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
|
||||
return current_ < rhs.current_;
|
||||
}
|
||||
|
||||
template <
|
||||
class Type2,
|
||||
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
|
||||
constexpr bool operator>(const span_iterator<Type2>& rhs) const noexcept
|
||||
{
|
||||
return rhs < *this;
|
||||
}
|
||||
|
||||
template <
|
||||
class Type2,
|
||||
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
|
||||
constexpr bool operator<=(const span_iterator<Type2>& rhs) const noexcept
|
||||
{
|
||||
return !(rhs < *this);
|
||||
}
|
||||
|
||||
template <
|
||||
class Type2,
|
||||
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
|
||||
constexpr bool operator>=(const span_iterator<Type2>& rhs) const noexcept
|
||||
{
|
||||
return !(*this < rhs);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// MSVC++ iterator debugging support; allows STL algorithms in 15.8+
|
||||
// to unwrap span_iterator to a pointer type after a range check in STL
|
||||
// algorithm calls
|
||||
friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept
|
||||
{ // test that [lhs, rhs) forms a valid range inside an STL algorithm
|
||||
Expects(lhs.begin_ == rhs.begin_ // range spans have to match
|
||||
&& lhs.end_ == rhs.end_ &&
|
||||
lhs.current_ <= rhs.current_); // range must not be transposed
|
||||
}
|
||||
|
||||
constexpr void _Verify_offset(const difference_type n) const noexcept
|
||||
{ // test that *this + n is within the range of this call
|
||||
if (n != 0) Expects(begin_ && current_ && end_);
|
||||
if (n > 0) Expects(end_ - current_ >= n);
|
||||
if (n < 0) Expects(current_ - begin_ >= -n);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
constexpr pointer _Unwrapped() const noexcept
|
||||
{ // after seeking *this to a high water mark, or using one of the
|
||||
// _Verify_xxx functions above, unwrap this span_iterator to a raw
|
||||
// pointer
|
||||
return current_;
|
||||
}
|
||||
|
||||
// Tell the STL that span_iterator should not be unwrapped if it can't
|
||||
// validate in advance, even in release / optimized builds:
|
||||
#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
|
||||
static constexpr const bool _Unwrap_when_unverified = false;
|
||||
#else
|
||||
static constexpr bool _Unwrap_when_unverified = false;
|
||||
#endif
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive
|
||||
// clang-format on
|
||||
constexpr void _Seek_to(const pointer p) noexcept
|
||||
{ // adjust the position of *this to previously verified location p
|
||||
// after _Unwrapped
|
||||
current_ = p;
|
||||
}
|
||||
#endif
|
||||
|
||||
pointer begin_ = nullptr;
|
||||
pointer end_ = nullptr;
|
||||
pointer current_ = nullptr;
|
||||
};
|
||||
|
||||
template <std::size_t Ext>
|
||||
class extent_type
|
||||
{
|
||||
public:
|
||||
using size_type = std::size_t;
|
||||
|
||||
constexpr extent_type() noexcept = default;
|
||||
|
||||
constexpr explicit extent_type(extent_type<dynamic_extent>);
|
||||
|
||||
constexpr explicit extent_type(size_type size) { Expects(size == Ext); }
|
||||
|
||||
constexpr size_type size() const noexcept { return Ext; }
|
||||
|
||||
private:
|
||||
#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
|
||||
static constexpr const size_type size_ = Ext; // static size equal to Ext
|
||||
#else
|
||||
static constexpr size_type size_ = Ext; // static size equal to Ext
|
||||
#endif
|
||||
};
|
||||
|
||||
template <>
|
||||
class extent_type<dynamic_extent>
|
||||
{
|
||||
public:
|
||||
using size_type = std::size_t;
|
||||
|
||||
template <size_type Other>
|
||||
constexpr explicit extent_type(extent_type<Other> ext) : size_(ext.size())
|
||||
{}
|
||||
|
||||
constexpr explicit extent_type(size_type size) : size_(size)
|
||||
{
|
||||
Expects(size != dynamic_extent);
|
||||
}
|
||||
|
||||
constexpr size_type size() const noexcept { return size_; }
|
||||
|
||||
private:
|
||||
size_type size_;
|
||||
};
|
||||
|
||||
template <std::size_t Ext>
|
||||
constexpr extent_type<Ext>::extent_type(extent_type<dynamic_extent> ext)
|
||||
{
|
||||
Expects(ext.size() == Ext);
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent, std::size_t Offset, std::size_t Count>
|
||||
struct calculate_subspan_type
|
||||
{
|
||||
using type = span<ElementType, Count != dynamic_extent
|
||||
? Count
|
||||
: (Extent != dynamic_extent ? Extent - Offset : Extent)>;
|
||||
};
|
||||
} // namespace details
|
||||
|
||||
// [span], class template span
|
||||
template <class ElementType, std::size_t Extent>
|
||||
class span
|
||||
{
|
||||
public:
|
||||
// constants and types
|
||||
using element_type = ElementType;
|
||||
using value_type = std::remove_cv_t<ElementType>;
|
||||
using size_type = std::size_t;
|
||||
using pointer = element_type*;
|
||||
using const_pointer = const element_type*;
|
||||
using reference = element_type&;
|
||||
using const_reference = const element_type&;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
using iterator = details::span_iterator<ElementType>;
|
||||
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||
|
||||
#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
|
||||
static constexpr const size_type extent{Extent};
|
||||
#else
|
||||
static constexpr size_type extent{Extent};
|
||||
#endif
|
||||
|
||||
// [span.cons], span constructors, copy, assignment, and destructor
|
||||
template <bool Dependent = false,
|
||||
// "Dependent" is needed to make "std::enable_if_t<Dependent || Extent == 0 || Extent
|
||||
// == dynamic_extent>" SFINAE, since "std::enable_if_t<Extent == 0 || Extent ==
|
||||
// dynamic_extent>" is ill-formed when Extent is greater than 0.
|
||||
class = std::enable_if_t<(Dependent ||
|
||||
details::is_allowed_extent_conversion<0, Extent>::value)>>
|
||||
constexpr span() noexcept : storage_(nullptr, details::extent_type<0>())
|
||||
{}
|
||||
|
||||
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != dynamic_extent, int> = 0>
|
||||
constexpr explicit span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
|
||||
{
|
||||
Expects(count == Extent);
|
||||
}
|
||||
|
||||
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == dynamic_extent, int> = 0>
|
||||
constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
|
||||
{}
|
||||
|
||||
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != dynamic_extent, int> = 0>
|
||||
constexpr explicit span(pointer firstElem, pointer lastElem) noexcept
|
||||
: storage_(firstElem, narrow_cast<std::size_t>(lastElem - firstElem))
|
||||
{
|
||||
Expects(lastElem - firstElem == static_cast<difference_type>(Extent));
|
||||
}
|
||||
|
||||
template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == dynamic_extent, int> = 0>
|
||||
constexpr span(pointer firstElem, pointer lastElem) noexcept
|
||||
: storage_(firstElem, narrow_cast<std::size_t>(lastElem - firstElem))
|
||||
{}
|
||||
|
||||
template <std::size_t N,
|
||||
std::enable_if_t<details::is_allowed_extent_conversion<N, Extent>::value, int> = 0>
|
||||
constexpr span(element_type (&arr)[N]) noexcept
|
||||
: storage_(KnownNotNull{arr}, details::extent_type<N>())
|
||||
{}
|
||||
|
||||
template <
|
||||
class T, std::size_t N,
|
||||
std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value &&
|
||||
details::is_allowed_element_type_conversion<T, element_type>::value),
|
||||
int> = 0>
|
||||
constexpr span(std::array<T, N>& arr) noexcept
|
||||
: storage_(KnownNotNull{arr.data()}, details::extent_type<N>())
|
||||
{}
|
||||
|
||||
template <class T, std::size_t N,
|
||||
std::enable_if_t<
|
||||
(details::is_allowed_extent_conversion<N, Extent>::value &&
|
||||
details::is_allowed_element_type_conversion<const T, element_type>::value),
|
||||
int> = 0>
|
||||
constexpr span(const std::array<T, N>& arr) noexcept
|
||||
: storage_(KnownNotNull{arr.data()}, details::extent_type<N>())
|
||||
{}
|
||||
|
||||
// NB: the SFINAE on these constructors uses .data() as an incomplete/imperfect proxy for the
|
||||
// requirement on Container to be a contiguous sequence container.
|
||||
template <std::size_t MyExtent = Extent, class Container,
|
||||
std::enable_if_t<
|
||||
MyExtent != dynamic_extent && !details::is_span<Container>::value &&
|
||||
!details::is_std_array<Container>::value &&
|
||||
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
|
||||
std::is_convertible<
|
||||
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
|
||||
element_type (*)[]>::value,
|
||||
int> = 0>
|
||||
constexpr explicit span(Container& cont) noexcept : span(cont.data(), cont.size())
|
||||
{}
|
||||
|
||||
template <std::size_t MyExtent = Extent, class Container,
|
||||
std::enable_if_t<
|
||||
MyExtent == dynamic_extent && !details::is_span<Container>::value &&
|
||||
!details::is_std_array<Container>::value &&
|
||||
std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
|
||||
std::is_convertible<
|
||||
std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
|
||||
element_type (*)[]>::value,
|
||||
int> = 0>
|
||||
constexpr span(Container& cont) noexcept : span(cont.data(), cont.size())
|
||||
{}
|
||||
|
||||
template <
|
||||
std::size_t MyExtent = Extent, class Container,
|
||||
std::enable_if_t<
|
||||
MyExtent != dynamic_extent && std::is_const<element_type>::value &&
|
||||
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
|
||||
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
|
||||
std::is_convertible<
|
||||
std::remove_pointer_t<decltype(std::declval<const Container&>().data())> (*)[],
|
||||
element_type (*)[]>::value,
|
||||
int> = 0>
|
||||
constexpr explicit span(const Container& cont) noexcept : span(cont.data(), cont.size())
|
||||
{}
|
||||
|
||||
template <
|
||||
std::size_t MyExtent = Extent, class Container,
|
||||
std::enable_if_t<
|
||||
MyExtent == dynamic_extent && std::is_const<element_type>::value &&
|
||||
!details::is_span<Container>::value && !details::is_std_array<Container>::value &&
|
||||
std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
|
||||
std::is_convertible<
|
||||
std::remove_pointer_t<decltype(std::declval<const Container&>().data())> (*)[],
|
||||
element_type (*)[]>::value,
|
||||
int> = 0>
|
||||
constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size())
|
||||
{}
|
||||
|
||||
constexpr span(const span& other) noexcept = default;
|
||||
|
||||
template <class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
|
||||
std::enable_if_t<(MyExtent == dynamic_extent || MyExtent == OtherExtent) &&
|
||||
details::is_allowed_element_type_conversion<OtherElementType,
|
||||
element_type>::value,
|
||||
int> = 0>
|
||||
constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
|
||||
: storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
|
||||
{}
|
||||
|
||||
template <class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
|
||||
std::enable_if_t<MyExtent != dynamic_extent && OtherExtent == dynamic_extent &&
|
||||
details::is_allowed_element_type_conversion<OtherElementType,
|
||||
element_type>::value,
|
||||
int> = 0>
|
||||
constexpr explicit span(const span<OtherElementType, OtherExtent>& other) noexcept
|
||||
: storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
|
||||
{}
|
||||
|
||||
~span() noexcept = default;
|
||||
constexpr span& operator=(const span& other) noexcept = default;
|
||||
|
||||
// [span.sub], span subviews
|
||||
template <std::size_t Count>
|
||||
constexpr span<element_type, Count> first() const noexcept
|
||||
{
|
||||
Expects(Count <= size());
|
||||
return span<element_type, Count>{data(), Count};
|
||||
}
|
||||
|
||||
template <std::size_t Count>
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
constexpr span<element_type, Count> last() const noexcept
|
||||
{
|
||||
Expects(Count <= size());
|
||||
return span<element_type, Count>{data() + (size() - Count), Count};
|
||||
}
|
||||
|
||||
template <std::size_t Offset, std::size_t Count = dynamic_extent>
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
constexpr auto subspan() const noexcept ->
|
||||
typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type
|
||||
{
|
||||
Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset)));
|
||||
using type =
|
||||
typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type;
|
||||
return type{data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
|
||||
}
|
||||
|
||||
constexpr span<element_type, dynamic_extent> first(size_type count) const noexcept
|
||||
{
|
||||
Expects(count <= size());
|
||||
return {data(), count};
|
||||
}
|
||||
|
||||
constexpr span<element_type, dynamic_extent> last(size_type count) const noexcept
|
||||
{
|
||||
Expects(count <= size());
|
||||
return make_subspan(size() - count, dynamic_extent, subspan_selector<Extent>{});
|
||||
}
|
||||
|
||||
constexpr span<element_type, dynamic_extent>
|
||||
subspan(size_type offset, size_type count = dynamic_extent) const noexcept
|
||||
{
|
||||
return make_subspan(offset, count, subspan_selector<Extent>{});
|
||||
}
|
||||
|
||||
// [span.obs], span observers
|
||||
constexpr size_type size() const noexcept { return storage_.size(); }
|
||||
|
||||
constexpr size_type size_bytes() const noexcept
|
||||
{
|
||||
Expects(size() < dynamic_extent / sizeof(element_type));
|
||||
return size() * sizeof(element_type);
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept { return size() == 0; }
|
||||
|
||||
// [span.elem], span element access
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
constexpr reference operator[](size_type idx) const noexcept
|
||||
{
|
||||
Expects(idx < size());
|
||||
return data()[idx];
|
||||
}
|
||||
|
||||
constexpr reference front() const noexcept
|
||||
{
|
||||
Expects(size() > 0);
|
||||
return data()[0];
|
||||
}
|
||||
|
||||
constexpr reference back() const noexcept
|
||||
{
|
||||
Expects(size() > 0);
|
||||
return data()[size() - 1];
|
||||
}
|
||||
|
||||
constexpr pointer data() const noexcept { return storage_.data(); }
|
||||
|
||||
// [span.iter], span iterator support
|
||||
constexpr iterator begin() const noexcept
|
||||
{
|
||||
const auto data = storage_.data();
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
return {data, data + size(), data};
|
||||
}
|
||||
|
||||
constexpr iterator end() const noexcept
|
||||
{
|
||||
const auto data = storage_.data();
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
const auto endData = data + storage_.size();
|
||||
return {data, endData, endData};
|
||||
}
|
||||
|
||||
constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
|
||||
constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Tell MSVC how to unwrap spans in range-based-for
|
||||
constexpr pointer _Unchecked_begin() const noexcept { return data(); }
|
||||
constexpr pointer _Unchecked_end() const noexcept
|
||||
{
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
return data() + size();
|
||||
}
|
||||
#endif // _MSC_VER
|
||||
|
||||
private:
|
||||
// Needed to remove unnecessary null check in subspans
|
||||
struct KnownNotNull
|
||||
{
|
||||
pointer p;
|
||||
};
|
||||
|
||||
// this implementation detail class lets us take advantage of the
|
||||
// empty base class optimization to pay for only storage of a single
|
||||
// pointer in the case of fixed-size spans
|
||||
template <class ExtentType>
|
||||
class storage_type : public ExtentType
|
||||
{
|
||||
public:
|
||||
// KnownNotNull parameter is needed to remove unnecessary null check
|
||||
// in subspans and constructors from arrays
|
||||
template <class OtherExtentType>
|
||||
constexpr storage_type(KnownNotNull data, OtherExtentType ext)
|
||||
: ExtentType(ext), data_(data.p)
|
||||
{
|
||||
Expects(ExtentType::size() != dynamic_extent);
|
||||
}
|
||||
|
||||
template <class OtherExtentType>
|
||||
constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data)
|
||||
{
|
||||
Expects(ExtentType::size() != dynamic_extent);
|
||||
Expects(data || ExtentType::size() == 0);
|
||||
}
|
||||
|
||||
constexpr pointer data() const noexcept { return data_; }
|
||||
|
||||
private:
|
||||
pointer data_;
|
||||
};
|
||||
|
||||
storage_type<details::extent_type<Extent>> storage_;
|
||||
|
||||
// The rest is needed to remove unnecessary null check
|
||||
// in subspans and constructors from arrays
|
||||
constexpr span(KnownNotNull ptr, size_type count) noexcept : storage_(ptr, count) {}
|
||||
|
||||
template <std::size_t CallerExtent>
|
||||
class subspan_selector
|
||||
{
|
||||
};
|
||||
|
||||
template <std::size_t CallerExtent>
|
||||
constexpr span<element_type, dynamic_extent>
|
||||
make_subspan(size_type offset, size_type count, subspan_selector<CallerExtent>) const noexcept
|
||||
{
|
||||
const span<element_type, dynamic_extent> tmp(*this);
|
||||
return tmp.subspan(offset, count);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
constexpr span<element_type, dynamic_extent>
|
||||
make_subspan(size_type offset, size_type count, subspan_selector<dynamic_extent>) const noexcept
|
||||
{
|
||||
Expects(size() >= offset);
|
||||
|
||||
if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; }
|
||||
|
||||
Expects(size() - offset >= count);
|
||||
return {KnownNotNull{data() + offset}, count};
|
||||
}
|
||||
};
|
||||
|
||||
#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
|
||||
|
||||
// Deduction Guides
|
||||
template <class Type, std::size_t Extent>
|
||||
span(Type (&)[Extent]) -> span<Type, Extent>;
|
||||
|
||||
template <class Type, std::size_t Size>
|
||||
span(std::array<Type, Size>&) -> span<Type, Size>;
|
||||
|
||||
template <class Type, std::size_t Size>
|
||||
span(const std::array<Type, Size>&) -> span<const Type, Size>;
|
||||
|
||||
template <class Container,
|
||||
class Element = std::remove_pointer_t<decltype(std::declval<Container&>().data())>>
|
||||
span(Container&) -> span<Element>;
|
||||
|
||||
template <class Container,
|
||||
class Element = std::remove_pointer_t<decltype(std::declval<const Container&>().data())>>
|
||||
span(const Container&) -> span<Element>;
|
||||
|
||||
#endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) )
|
||||
|
||||
#if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr const typename span<ElementType, Extent>::size_type span<ElementType, Extent>::extent;
|
||||
#endif
|
||||
|
||||
namespace details
|
||||
{
|
||||
// if we only supported compilers with good constexpr support then
|
||||
// this pair of classes could collapse down to a constexpr function
|
||||
|
||||
// we should use a narrow_cast<> to go to std::size_t, but older compilers may not see it as
|
||||
// constexpr
|
||||
// and so will fail compilation of the template
|
||||
template <class ElementType, std::size_t Extent>
|
||||
struct calculate_byte_size : std::integral_constant<std::size_t, sizeof(ElementType) * Extent>
|
||||
{
|
||||
static_assert(Extent < dynamic_extent / sizeof(ElementType), "Size is too big.");
|
||||
};
|
||||
|
||||
template <class ElementType>
|
||||
struct calculate_byte_size<ElementType, dynamic_extent>
|
||||
: std::integral_constant<std::size_t, dynamic_extent>
|
||||
{
|
||||
};
|
||||
} // namespace details
|
||||
|
||||
// [span.objectrep], views of object representation
|
||||
template <class ElementType, std::size_t Extent>
|
||||
span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
|
||||
as_bytes(span<ElementType, Extent> s) noexcept
|
||||
{
|
||||
using type = span<const byte, details::calculate_byte_size<ElementType, Extent>::value>;
|
||||
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
return type{reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent,
|
||||
std::enable_if_t<!std::is_const<ElementType>::value, int> = 0>
|
||||
span<byte, details::calculate_byte_size<ElementType, Extent>::value>
|
||||
as_writable_bytes(span<ElementType, Extent> s) noexcept
|
||||
{
|
||||
using type = span<byte, details::calculate_byte_size<ElementType, Extent>::value>;
|
||||
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
return type{reinterpret_cast<byte*>(s.data()), s.size_bytes()};
|
||||
}
|
||||
|
||||
} // namespace gsl
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ > 6
|
||||
#pragma GCC diagnostic pop
|
||||
#endif // __GNUC__ > 6
|
||||
|
||||
#endif // GSL_SPAN_H
|
||||
Vendored
-212
@@ -1,212 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GSL_SPAN_EXT_H
|
||||
#define GSL_SPAN_EXT_H
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// File: span_ext
|
||||
// Purpose: continue offering features that have been cut from the official
|
||||
// implementation of span.
|
||||
// While modernizing gsl::span a number of features needed to be removed to
|
||||
// be compliant with the design of std::span
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <gsl/assert> // GSL_KERNEL_MODE
|
||||
#include <gsl/util> // for narrow_cast, narrow
|
||||
|
||||
#include <cstddef> // for ptrdiff_t, size_t
|
||||
#include <utility>
|
||||
|
||||
#ifndef GSL_KERNEL_MODE
|
||||
#include <algorithm> // for lexicographical_compare
|
||||
#endif // GSL_KERNEL_MODE
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
|
||||
// [span.views.constants], constants
|
||||
constexpr const std::size_t dynamic_extent = narrow_cast<std::size_t>(-1);
|
||||
|
||||
template <class ElementType, std::size_t Extent = dynamic_extent>
|
||||
class span;
|
||||
|
||||
// std::equal and std::lexicographical_compare are not /kernel compatible
|
||||
// so all comparison operators must be removed for kernel mode.
|
||||
#ifndef GSL_KERNEL_MODE
|
||||
|
||||
// [span.comparison], span comparison operators
|
||||
template <class ElementType, std::size_t FirstExtent, std::size_t SecondExtent>
|
||||
constexpr bool operator==(span<ElementType, FirstExtent> l, span<ElementType, SecondExtent> r)
|
||||
{
|
||||
return std::equal(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr bool operator!=(span<ElementType, Extent> l, span<ElementType, Extent> r)
|
||||
{
|
||||
return !(l == r);
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr bool operator<(span<ElementType, Extent> l, span<ElementType, Extent> r)
|
||||
{
|
||||
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr bool operator<=(span<ElementType, Extent> l, span<ElementType, Extent> r)
|
||||
{
|
||||
return !(l > r);
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr bool operator>(span<ElementType, Extent> l, span<ElementType, Extent> r)
|
||||
{
|
||||
return r < l;
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr bool operator>=(span<ElementType, Extent> l, span<ElementType, Extent> r)
|
||||
{
|
||||
return !(l < r);
|
||||
}
|
||||
|
||||
#endif // GSL_KERNEL_MODE
|
||||
|
||||
//
|
||||
// make_span() - Utility functions for creating spans
|
||||
//
|
||||
template <class ElementType>
|
||||
constexpr span<ElementType> make_span(ElementType* ptr, typename span<ElementType>::size_type count)
|
||||
{
|
||||
return span<ElementType>(ptr, count);
|
||||
}
|
||||
|
||||
template <class ElementType>
|
||||
constexpr span<ElementType> make_span(ElementType* firstElem, ElementType* lastElem)
|
||||
{
|
||||
return span<ElementType>(firstElem, lastElem);
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t N>
|
||||
constexpr span<ElementType, N> make_span(ElementType (&arr)[N]) noexcept
|
||||
{
|
||||
return span<ElementType, N>(arr);
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
constexpr span<typename Container::value_type> make_span(Container& cont)
|
||||
{
|
||||
return span<typename Container::value_type>(cont);
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
constexpr span<const typename Container::value_type> make_span(const Container& cont)
|
||||
{
|
||||
return span<const typename Container::value_type>(cont);
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
constexpr span<typename Ptr::element_type> make_span(Ptr& cont, std::size_t count)
|
||||
{
|
||||
return span<typename Ptr::element_type>(cont, count);
|
||||
}
|
||||
|
||||
template <class Ptr>
|
||||
constexpr span<typename Ptr::element_type> make_span(Ptr& cont)
|
||||
{
|
||||
return span<typename Ptr::element_type>(cont);
|
||||
}
|
||||
|
||||
// Specialization of gsl::at for span
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr ElementType& at(span<ElementType, Extent> s, index i)
|
||||
{
|
||||
// No bounds checking here because it is done in span::operator[] called below
|
||||
Ensures(i >= 0);
|
||||
return s[narrow_cast<std::size_t>(i)];
|
||||
}
|
||||
|
||||
// [span.obs] Free observer functions
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr std::ptrdiff_t ssize(const span<ElementType, Extent>& s) noexcept
|
||||
{
|
||||
return static_cast<std::ptrdiff_t>(s.size());
|
||||
}
|
||||
|
||||
// [span.iter] Free functions for begin/end functions
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr typename span<ElementType, Extent>::iterator
|
||||
begin(const span<ElementType, Extent>& s) noexcept
|
||||
{
|
||||
return s.begin();
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent = dynamic_extent>
|
||||
constexpr typename span<ElementType, Extent>::iterator
|
||||
end(const span<ElementType, Extent>& s) noexcept
|
||||
{
|
||||
return s.end();
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr typename span<ElementType, Extent>::reverse_iterator
|
||||
rbegin(const span<ElementType, Extent>& s) noexcept
|
||||
{
|
||||
return s.rbegin();
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr typename span<ElementType, Extent>::reverse_iterator
|
||||
rend(const span<ElementType, Extent>& s) noexcept
|
||||
{
|
||||
return s.rend();
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr typename span<ElementType, Extent>::iterator
|
||||
cbegin(const span<ElementType, Extent>& s) noexcept
|
||||
{
|
||||
return s.begin();
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent = dynamic_extent>
|
||||
constexpr typename span<ElementType, Extent>::iterator
|
||||
cend(const span<ElementType, Extent>& s) noexcept
|
||||
{
|
||||
return s.end();
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr typename span<ElementType, Extent>::reverse_iterator
|
||||
crbegin(const span<ElementType, Extent>& s) noexcept
|
||||
{
|
||||
return s.rbegin();
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr typename span<ElementType, Extent>::reverse_iterator
|
||||
crend(const span<ElementType, Extent>& s) noexcept
|
||||
{
|
||||
return s.rend();
|
||||
}
|
||||
|
||||
} // namespace gsl
|
||||
|
||||
#endif // GSL_SPAN_EXT_H
|
||||
Vendored
-759
@@ -1,759 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GSL_STRING_SPAN_H
|
||||
#define GSL_STRING_SPAN_H
|
||||
|
||||
#include <gsl/assert> // for Ensures, Expects
|
||||
#include <gsl/span_ext> // for operator!=, operator==, dynamic_extent
|
||||
#include <gsl/util> // for narrow_cast
|
||||
|
||||
#include <algorithm> // for equal, lexicographical_compare
|
||||
#include <array> // for array
|
||||
#include <cstddef> // for size_t, nullptr_t
|
||||
#include <cstdint> // for PTRDIFF_MAX
|
||||
#include <cstring>
|
||||
#include <string> // for basic_string, allocator, char_traits
|
||||
#include <type_traits> // for declval, is_convertible, enable_if_t, add_...
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma warning(push)
|
||||
|
||||
// Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
|
||||
#pragma warning(disable : 26446) // TODO: bug in parser - attributes and templates
|
||||
#pragma warning(disable : 26481) // TODO: suppress does not work inside templates sometimes
|
||||
#pragma warning(disable : 4996) // use of functions & classes marked [[deprecated]]
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
#endif
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
//
|
||||
// czstring and wzstring
|
||||
//
|
||||
// These are "tag" typedefs for C-style strings (i.e. null-terminated character arrays)
|
||||
// that allow static analysis to help find bugs.
|
||||
//
|
||||
// There are no additional features/semantics that we can find a way to add inside the
|
||||
// type system for these types that will not either incur significant runtime costs or
|
||||
// (sometimes needlessly) break existing programs when introduced.
|
||||
//
|
||||
|
||||
template <typename CharT, std::size_t Extent = dynamic_extent>
|
||||
using basic_zstring = CharT*;
|
||||
|
||||
using czstring = basic_zstring<const char, dynamic_extent>;
|
||||
|
||||
using cwzstring = basic_zstring<const wchar_t, dynamic_extent>;
|
||||
|
||||
using cu16zstring = basic_zstring<const char16_t, dynamic_extent>;
|
||||
|
||||
using cu32zstring = basic_zstring<const char32_t, dynamic_extent>;
|
||||
|
||||
using zstring = basic_zstring<char, dynamic_extent>;
|
||||
|
||||
using wzstring = basic_zstring<wchar_t, dynamic_extent>;
|
||||
|
||||
using u16zstring = basic_zstring<char16_t, dynamic_extent>;
|
||||
|
||||
using u32zstring = basic_zstring<char32_t, dynamic_extent>;
|
||||
|
||||
namespace details
|
||||
{
|
||||
template <class CharT>
|
||||
[[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see "
|
||||
"isocpp/CppCoreGuidelines PR#1680")]] constexpr std::size_t
|
||||
string_length(const CharT* str, std::size_t n)
|
||||
{
|
||||
if (str == nullptr || n == dynamic_extent) return 0;
|
||||
|
||||
const span<const CharT> str_span{str, n};
|
||||
|
||||
std::size_t len = 0;
|
||||
while (len < n && str_span[len]) len++;
|
||||
|
||||
return len;
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
//
|
||||
// ensure_sentinel()
|
||||
//
|
||||
// Provides a way to obtain an span from a contiguous sequence
|
||||
// that ends with a (non-inclusive) sentinel value.
|
||||
//
|
||||
// Will fail-fast if sentinel cannot be found before max elements are examined.
|
||||
//
|
||||
template <typename T, const T Sentinel>
|
||||
[[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see "
|
||||
"isocpp/CppCoreGuidelines PR#1680")]] constexpr span<T, dynamic_extent>
|
||||
ensure_sentinel(T* seq, std::size_t max = static_cast<std::size_t>(-1))
|
||||
{
|
||||
Ensures(seq != nullptr);
|
||||
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(f.23) // TODO: false positive // TODO: suppress does not work
|
||||
// clang-format on
|
||||
auto cur = seq;
|
||||
Ensures(cur != nullptr); // workaround for removing the warning
|
||||
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // TODO: suppress does not work
|
||||
// clang-format on
|
||||
while (static_cast<std::size_t>(cur - seq) < max && *cur != Sentinel) ++cur;
|
||||
Ensures(*cur == Sentinel);
|
||||
return {seq, static_cast<std::size_t>(cur - seq)};
|
||||
}
|
||||
|
||||
//
|
||||
// ensure_z - creates a span for a zero terminated strings. The span will not contain the zero
|
||||
// termination. Will fail fast if a null-terminator cannot be found before the limit of size_type.
|
||||
//
|
||||
template <typename CharT>
|
||||
[[deprecated("string_span was removed from the C++ Core Guidelines. For more information, see "
|
||||
"isocpp/CppCoreGuidelines PR#1680")]] constexpr span<CharT, dynamic_extent>
|
||||
ensure_z(CharT* const& sz, std::size_t max = static_cast<std::size_t>(-1))
|
||||
{
|
||||
return ensure_sentinel<CharT, CharT(0)>(sz, max);
|
||||
}
|
||||
|
||||
template <typename CharT, std::size_t N>
|
||||
constexpr span<CharT, dynamic_extent> ensure_z(CharT (&sz)[N])
|
||||
{
|
||||
return ensure_z(&sz[0], N);
|
||||
}
|
||||
|
||||
template <class Cont>
|
||||
[[deprecated(
|
||||
"string_span was removed from the C++ Core Guidelines. For more information, see "
|
||||
"isocpp/CppCoreGuidelines PR#1680")]] constexpr span<typename std::
|
||||
remove_pointer<
|
||||
typename Cont::pointer>::type,
|
||||
dynamic_extent>
|
||||
ensure_z(Cont& cont)
|
||||
{
|
||||
return ensure_z(cont.data(), cont.size());
|
||||
}
|
||||
|
||||
template <typename CharT, std::size_t>
|
||||
class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, "
|
||||
"see isocpp/CppCoreGuidelines PR#1680")]] basic_string_span;
|
||||
|
||||
namespace details
|
||||
{
|
||||
template <typename T>
|
||||
struct [[deprecated(
|
||||
"string_span was removed from the C++ Core Guidelines. For more information, "
|
||||
"see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle : std::false_type{};
|
||||
|
||||
template <typename CharT, std::size_t Extent>
|
||||
struct [[deprecated(
|
||||
"string_span was removed from the C++ Core Guidelines. For more information, see "
|
||||
"isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span_oracle<basic_string_span<CharT,
|
||||
Extent>>
|
||||
: std::true_type{};
|
||||
|
||||
template <typename T>
|
||||
struct [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] is_basic_string_span
|
||||
: is_basic_string_span_oracle<std::remove_cv_t<T>>{};
|
||||
} // namespace details
|
||||
|
||||
//
|
||||
// string_span and relatives
|
||||
//
|
||||
template <typename CharT, std::size_t Extent = dynamic_extent>
|
||||
class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, "
|
||||
"see isocpp/CppCoreGuidelines PR#1680")]] basic_string_span
|
||||
{
|
||||
public:
|
||||
using element_type = CharT;
|
||||
using value_type = std::remove_cv_t<element_type>;
|
||||
using pointer = std::add_pointer_t<element_type>;
|
||||
using reference = std::add_lvalue_reference_t<element_type>;
|
||||
using const_reference = std::add_lvalue_reference_t<std::add_const_t<element_type>>;
|
||||
using impl_type = span<element_type, Extent>;
|
||||
|
||||
using size_type = typename impl_type::size_type;
|
||||
using iterator = typename impl_type::iterator;
|
||||
using reverse_iterator = typename impl_type::reverse_iterator;
|
||||
|
||||
// default (empty)
|
||||
constexpr basic_string_span() noexcept = default;
|
||||
|
||||
// copy
|
||||
constexpr basic_string_span(const basic_string_span& other) noexcept = default;
|
||||
|
||||
// assign
|
||||
constexpr basic_string_span& operator=(const basic_string_span& other) noexcept = default;
|
||||
|
||||
constexpr basic_string_span(pointer ptr, size_type length) : span_(ptr, length) {}
|
||||
constexpr basic_string_span(pointer firstElem, pointer lastElem) : span_(firstElem, lastElem) {}
|
||||
|
||||
// From static arrays - if 0-terminated, remove 0 from the view
|
||||
// All other containers allow 0s within the length, so we do not remove them
|
||||
template <std::size_t N>
|
||||
constexpr basic_string_span(element_type(&arr)[N]) : span_(remove_z(arr))
|
||||
{}
|
||||
|
||||
template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
|
||||
constexpr basic_string_span(std::array<ArrayElementType, N> & arr) noexcept : span_(arr)
|
||||
{}
|
||||
|
||||
template <std::size_t N, class ArrayElementType = std::remove_const_t<element_type>>
|
||||
constexpr basic_string_span(const std::array<ArrayElementType, N>& arr) noexcept : span_(arr)
|
||||
{}
|
||||
|
||||
// Container signature should work for basic_string after C++17 version exists
|
||||
template <class Traits, class Allocator>
|
||||
// GSL_SUPPRESS(bounds.4) // TODO: parser bug
|
||||
constexpr basic_string_span(std::basic_string<element_type, Traits, Allocator> & str)
|
||||
: span_(&str[0], str.length())
|
||||
{}
|
||||
|
||||
template <class Traits, class Allocator>
|
||||
constexpr basic_string_span(const std::basic_string<element_type, Traits, Allocator>& str)
|
||||
: span_(&str[0], str.length())
|
||||
{}
|
||||
|
||||
// from containers. Containers must have a pointer type and data() function signatures
|
||||
template <class Container,
|
||||
class = std::enable_if_t<
|
||||
!details::is_basic_string_span<Container>::value &&
|
||||
std::is_convertible<typename Container::pointer, pointer>::value &&
|
||||
std::is_convertible<typename Container::pointer,
|
||||
decltype(std::declval<Container>().data())>::value>>
|
||||
constexpr basic_string_span(Container & cont) : span_(cont)
|
||||
{}
|
||||
|
||||
template <class Container,
|
||||
class = std::enable_if_t<
|
||||
!details::is_basic_string_span<Container>::value &&
|
||||
std::is_convertible<typename Container::pointer, pointer>::value &&
|
||||
std::is_convertible<typename Container::pointer,
|
||||
decltype(std::declval<Container>().data())>::value>>
|
||||
constexpr basic_string_span(const Container& cont) : span_(cont)
|
||||
{}
|
||||
|
||||
// from string_span
|
||||
template <
|
||||
class OtherValueType, std::size_t OtherExtent,
|
||||
class = std::enable_if_t<std::is_convertible<
|
||||
typename basic_string_span<OtherValueType, OtherExtent>::impl_type, impl_type>::value>>
|
||||
constexpr basic_string_span(basic_string_span<OtherValueType, OtherExtent> other)
|
||||
: span_(other.data(), other.length())
|
||||
{}
|
||||
|
||||
template <size_type Count>
|
||||
constexpr basic_string_span<element_type, Count> first() const
|
||||
{
|
||||
return {span_.template first<Count>()};
|
||||
}
|
||||
|
||||
constexpr basic_string_span<element_type, dynamic_extent> first(size_type count) const
|
||||
{
|
||||
return {span_.first(count)};
|
||||
}
|
||||
|
||||
template <size_type Count>
|
||||
constexpr basic_string_span<element_type, Count> last() const
|
||||
{
|
||||
return {span_.template last<Count>()};
|
||||
}
|
||||
|
||||
constexpr basic_string_span<element_type, dynamic_extent> last(size_type count) const
|
||||
{
|
||||
return {span_.last(count)};
|
||||
}
|
||||
|
||||
template <size_type Offset, size_type Count>
|
||||
constexpr basic_string_span<element_type, Count> subspan() const
|
||||
{
|
||||
return {span_.template subspan<Offset, Count>()};
|
||||
}
|
||||
|
||||
constexpr basic_string_span<element_type, dynamic_extent> subspan(
|
||||
size_type offset, size_type count = dynamic_extent) const
|
||||
{
|
||||
return {span_.subspan(offset, count)};
|
||||
}
|
||||
|
||||
constexpr reference operator[](size_type idx) const { return span_[idx]; }
|
||||
constexpr reference operator()(size_type idx) const { return span_[idx]; }
|
||||
|
||||
constexpr pointer data() const { return span_.data(); }
|
||||
|
||||
constexpr size_type length() const noexcept { return span_.size(); }
|
||||
constexpr size_type size() const noexcept { return span_.size(); }
|
||||
constexpr size_type size_bytes() const noexcept { return span_.size_bytes(); }
|
||||
constexpr size_type length_bytes() const noexcept { return span_.length_bytes(); }
|
||||
constexpr bool empty() const noexcept { return size() == 0; }
|
||||
|
||||
constexpr iterator begin() const noexcept { return span_.begin(); }
|
||||
constexpr iterator end() const noexcept { return span_.end(); }
|
||||
|
||||
constexpr reverse_iterator rbegin() const noexcept { return span_.rbegin(); }
|
||||
constexpr reverse_iterator rend() const noexcept { return span_.rend(); }
|
||||
|
||||
private:
|
||||
static constexpr impl_type remove_z(pointer const& sz, std::size_t max)
|
||||
{
|
||||
return impl_type(sz, details::string_length(sz, max));
|
||||
}
|
||||
|
||||
template <std::size_t N>
|
||||
static constexpr impl_type remove_z(element_type(&sz)[N])
|
||||
{
|
||||
return remove_z(&sz[0], N);
|
||||
}
|
||||
|
||||
impl_type span_;
|
||||
};
|
||||
|
||||
template <std::size_t Extent = dynamic_extent>
|
||||
using string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_string_span<char, Extent>;
|
||||
|
||||
template <std::size_t Extent = dynamic_extent>
|
||||
using cstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_string_span<const char, Extent>;
|
||||
|
||||
template <std::size_t Extent = dynamic_extent>
|
||||
using wstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_string_span<wchar_t, Extent>;
|
||||
|
||||
template <std::size_t Extent = dynamic_extent>
|
||||
using cwstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_string_span<const wchar_t, Extent>;
|
||||
|
||||
template <std::size_t Extent = dynamic_extent>
|
||||
using u16string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_string_span<char16_t, Extent>;
|
||||
|
||||
template <std::size_t Extent = dynamic_extent>
|
||||
using cu16string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_string_span<const char16_t, Extent>;
|
||||
|
||||
template <std::size_t Extent = dynamic_extent>
|
||||
using u32string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_string_span<char32_t, Extent>;
|
||||
|
||||
template <std::size_t Extent = dynamic_extent>
|
||||
using cu32string_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_string_span<const char32_t, Extent>;
|
||||
|
||||
//
|
||||
// to_string() allow (explicit) conversions from string_span to string
|
||||
//
|
||||
|
||||
template <typename CharT, std::size_t Extent>
|
||||
constexpr std::basic_string<typename std::remove_const<CharT>::type>
|
||||
to_string(basic_string_span<CharT, Extent> view)
|
||||
{
|
||||
return {view.data(), narrow_cast<std::size_t>(view.length())};
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits = typename std::char_traits<CharT>,
|
||||
typename Allocator = std::allocator<CharT>, typename gCharT, std::size_t Extent>
|
||||
constexpr std::basic_string<CharT, Traits, Allocator>
|
||||
to_basic_string(basic_string_span<gCharT, Extent> view)
|
||||
{
|
||||
return {view.data(), narrow_cast<std::size_t>(view.length())};
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent>
|
||||
constexpr basic_string_span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
|
||||
as_bytes(basic_string_span<ElementType, Extent> s) noexcept
|
||||
{
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(type.1)
|
||||
// clang-format on
|
||||
return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
|
||||
}
|
||||
|
||||
template <class ElementType, std::size_t Extent,
|
||||
class = std::enable_if_t<!std::is_const<ElementType>::value>>
|
||||
constexpr basic_string_span<byte, details::calculate_byte_size<ElementType, Extent>::value>
|
||||
as_writable_bytes(basic_string_span<ElementType, Extent> s) noexcept
|
||||
{
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(type.1)
|
||||
// clang-format on
|
||||
return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
|
||||
}
|
||||
|
||||
// zero-terminated string span, used to convert
|
||||
// zero-terminated spans to legacy strings
|
||||
template <typename CharT, std::size_t Extent = dynamic_extent>
|
||||
class [[deprecated("string_span was removed from the C++ Core Guidelines. For more information, "
|
||||
"see isocpp/CppCoreGuidelines PR#1680")]] basic_zstring_span
|
||||
{
|
||||
public:
|
||||
using value_type = CharT;
|
||||
using const_value_type = std::add_const_t<CharT>;
|
||||
|
||||
using pointer = std::add_pointer_t<value_type>;
|
||||
using const_pointer = std::add_pointer_t<const_value_type>;
|
||||
|
||||
using zstring_type = basic_zstring<value_type, Extent>;
|
||||
using const_zstring_type = basic_zstring<const_value_type, Extent>;
|
||||
|
||||
using impl_type = span<value_type, Extent>;
|
||||
using string_span_type = basic_string_span<value_type, Extent>;
|
||||
|
||||
constexpr basic_zstring_span(impl_type s) : span_(s)
|
||||
{
|
||||
// expects a zero-terminated span
|
||||
Expects(s.size() > 0);
|
||||
Expects(s[s.size() - 1] == value_type{});
|
||||
}
|
||||
|
||||
// copy
|
||||
constexpr basic_zstring_span(const basic_zstring_span& other) = default;
|
||||
|
||||
// move
|
||||
constexpr basic_zstring_span(basic_zstring_span && other) = default;
|
||||
|
||||
// assign
|
||||
constexpr basic_zstring_span& operator=(const basic_zstring_span& other) = default;
|
||||
|
||||
// move assign
|
||||
constexpr basic_zstring_span& operator=(basic_zstring_span&& other) = default;
|
||||
|
||||
constexpr bool empty() const noexcept { return false; }
|
||||
|
||||
constexpr string_span_type as_string_span() const noexcept
|
||||
{
|
||||
return {span_.data(), span_.size() - 1};
|
||||
}
|
||||
constexpr string_span_type ensure_z() const { return gsl::ensure_z(span_); }
|
||||
|
||||
constexpr const_zstring_type assume_z() const noexcept { return span_.data(); }
|
||||
|
||||
private:
|
||||
impl_type span_;
|
||||
};
|
||||
|
||||
template <std::size_t Max = dynamic_extent>
|
||||
using zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_zstring_span<char, Max>;
|
||||
|
||||
template <std::size_t Max = dynamic_extent>
|
||||
using wzstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_zstring_span<wchar_t, Max>;
|
||||
|
||||
template <std::size_t Max = dynamic_extent>
|
||||
using u16zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_zstring_span<char16_t, Max>;
|
||||
|
||||
template <std::size_t Max = dynamic_extent>
|
||||
using u32zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_zstring_span<char32_t, Max>;
|
||||
|
||||
template <std::size_t Max = dynamic_extent>
|
||||
using czstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_zstring_span<const char, Max>;
|
||||
|
||||
template <std::size_t Max = dynamic_extent>
|
||||
using cwzstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For more "
|
||||
"information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_zstring_span<const wchar_t, Max>;
|
||||
|
||||
template <std::size_t Max = dynamic_extent>
|
||||
using cu16zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For "
|
||||
"more information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_zstring_span<const char16_t, Max>;
|
||||
|
||||
template <std::size_t Max = dynamic_extent>
|
||||
using cu32zstring_span [[deprecated("string_span was removed from the C++ Core Guidelines. For "
|
||||
"more information, see isocpp/CppCoreGuidelines PR#1680")]] =
|
||||
basic_zstring_span<const char32_t, Max>;
|
||||
|
||||
// operator ==
|
||||
template <class CharT, std::size_t Extent, class T,
|
||||
class = std::enable_if_t<
|
||||
details::is_basic_string_span<T>::value ||
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::value>>
|
||||
bool operator==(const gsl::basic_string_span<CharT, Extent>& one, const T& other)
|
||||
{
|
||||
const gsl::basic_string_span<std::add_const_t<CharT>> tmp(other);
|
||||
return std::equal(one.begin(), one.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
template <class CharT, std::size_t Extent, class T,
|
||||
class = std::enable_if_t<
|
||||
!details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>>>::value>>
|
||||
bool operator==(const T& one, const gsl::basic_string_span<CharT, Extent>& other)
|
||||
{
|
||||
const gsl::basic_string_span<std::add_const_t<CharT>> tmp(one);
|
||||
return std::equal(tmp.begin(), tmp.end(), other.begin(), other.end());
|
||||
}
|
||||
|
||||
// operator !=
|
||||
template <typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
|
||||
bool operator!=(gsl::basic_string_span<CharT, Extent> one, const T& other)
|
||||
{
|
||||
return !(one == other);
|
||||
}
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
|
||||
!gsl::details::is_basic_string_span<T>::value>>
|
||||
bool operator!=(const T& one, gsl::basic_string_span<CharT, Extent> other)
|
||||
{
|
||||
return !(one == other);
|
||||
}
|
||||
|
||||
// operator<
|
||||
template <typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
|
||||
bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other)
|
||||
{
|
||||
const gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
|
||||
return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
|
||||
!gsl::details::is_basic_string_span<T>::value>>
|
||||
bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other)
|
||||
{
|
||||
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
|
||||
return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end());
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
|
||||
// VS treats temp and const containers as convertible to basic_string_span,
|
||||
// so the cases below are already covered by the previous operators
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename DataType = typename T::value_type,
|
||||
typename = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator<(gsl::basic_string_span<CharT, Extent> one, const T& other)
|
||||
{
|
||||
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(other);
|
||||
return std::lexicographical_compare(one.begin(), one.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename DataType = typename T::value_type,
|
||||
typename = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator<(const T& one, gsl::basic_string_span<CharT, Extent> other)
|
||||
{
|
||||
gsl::basic_string_span<std::add_const_t<CharT>, Extent> tmp(one);
|
||||
return std::lexicographical_compare(tmp.begin(), tmp.end(), other.begin(), other.end());
|
||||
}
|
||||
#endif
|
||||
|
||||
// operator <=
|
||||
template <typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
|
||||
bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other)
|
||||
{
|
||||
return !(other < one);
|
||||
}
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
|
||||
!gsl::details::is_basic_string_span<T>::value>>
|
||||
bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other)
|
||||
{
|
||||
return !(other < one);
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
|
||||
// VS treats temp and const containers as convertible to basic_string_span,
|
||||
// so the cases below are already covered by the previous operators
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename DataType = typename T::value_type,
|
||||
typename = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator<=(gsl::basic_string_span<CharT, Extent> one, const T& other)
|
||||
{
|
||||
return !(other < one);
|
||||
}
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename DataType = typename T::value_type,
|
||||
typename = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator<=(const T& one, gsl::basic_string_span<CharT, Extent> other)
|
||||
{
|
||||
return !(other < one);
|
||||
}
|
||||
#endif
|
||||
|
||||
// operator>
|
||||
template <typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
|
||||
bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other)
|
||||
{
|
||||
return other < one;
|
||||
}
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
|
||||
!gsl::details::is_basic_string_span<T>::value>>
|
||||
bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other)
|
||||
{
|
||||
return other < one;
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
|
||||
// VS treats temp and const containers as convertible to basic_string_span,
|
||||
// so the cases below are already covered by the previous operators
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename DataType = typename T::value_type,
|
||||
typename = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator>(gsl::basic_string_span<CharT, Extent> one, const T& other)
|
||||
{
|
||||
return other < one;
|
||||
}
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename DataType = typename T::value_type,
|
||||
typename = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator>(const T& one, gsl::basic_string_span<CharT, Extent> other)
|
||||
{
|
||||
return other < one;
|
||||
}
|
||||
#endif
|
||||
|
||||
// operator >=
|
||||
template <typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<std::is_convertible<
|
||||
T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value>>
|
||||
bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other)
|
||||
{
|
||||
return !(one < other);
|
||||
}
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename = std::enable_if_t<
|
||||
std::is_convertible<T, gsl::basic_string_span<std::add_const_t<CharT>, Extent>>::value &&
|
||||
!gsl::details::is_basic_string_span<T>::value>>
|
||||
bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other)
|
||||
{
|
||||
return !(one < other);
|
||||
}
|
||||
|
||||
#ifndef _MSC_VER
|
||||
|
||||
// VS treats temp and const containers as convertible to basic_string_span,
|
||||
// so the cases below are already covered by the previous operators
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename DataType = typename T::value_type,
|
||||
typename = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator>=(gsl::basic_string_span<CharT, Extent> one, const T& other)
|
||||
{
|
||||
return !(one < other);
|
||||
}
|
||||
|
||||
template <
|
||||
typename CharT, std::size_t Extent = dynamic_extent, typename T,
|
||||
typename DataType = typename T::value_type,
|
||||
typename = std::enable_if_t<
|
||||
!gsl::details::is_span<T>::value && !gsl::details::is_basic_string_span<T>::value &&
|
||||
std::is_convertible<DataType*, CharT*>::value &&
|
||||
std::is_same<std::decay_t<decltype(std::declval<T>().size(), *std::declval<T>().data())>,
|
||||
DataType>::value>>
|
||||
bool operator>=(const T& one, gsl::basic_string_span<CharT, Extent> other)
|
||||
{
|
||||
return !(one < other);
|
||||
}
|
||||
#endif
|
||||
} // namespace gsl
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif // GSL_STRING_SPAN_H
|
||||
Vendored
-160
@@ -1,160 +0,0 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef GSL_UTIL_H
|
||||
#define GSL_UTIL_H
|
||||
|
||||
#include <gsl/assert> // for Expects
|
||||
|
||||
#include <array>
|
||||
#include <cstddef> // for ptrdiff_t, size_t
|
||||
#include <initializer_list> // for initializer_list
|
||||
#include <type_traits> // for is_signed, integral_constant
|
||||
#include <utility> // for exchange, forward
|
||||
|
||||
#if defined(__has_include) && __has_include(<version>)
|
||||
#include <version>
|
||||
#if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
|
||||
#include <span>
|
||||
#endif // __cpp_lib_span >= 202002L
|
||||
#endif //__has_include(<version>)
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127) // conditional expression is constant
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#if defined(__cplusplus) && (__cplusplus >= 201703L)
|
||||
#define GSL_NODISCARD [[nodiscard]]
|
||||
#else
|
||||
#define GSL_NODISCARD
|
||||
#endif // defined(__cplusplus) && (__cplusplus >= 201703L)
|
||||
|
||||
namespace gsl
|
||||
{
|
||||
//
|
||||
// GSL.util: utilities
|
||||
//
|
||||
|
||||
// index type for all container indexes/subscripts/sizes
|
||||
using index = std::ptrdiff_t;
|
||||
|
||||
// final_action allows you to ensure something gets run at the end of a scope
|
||||
template <class F>
|
||||
class final_action
|
||||
{
|
||||
public:
|
||||
static_assert(!std::is_reference<F>::value && !std::is_const<F>::value &&
|
||||
!std::is_volatile<F>::value,
|
||||
"Final_action should store its callable by value");
|
||||
|
||||
explicit final_action(F f) noexcept : f_(std::move(f)) {}
|
||||
|
||||
final_action(final_action&& other) noexcept
|
||||
: f_(std::move(other.f_)), invoke_(std::exchange(other.invoke_, false))
|
||||
{}
|
||||
|
||||
final_action(const final_action&) = delete;
|
||||
final_action& operator=(const final_action&) = delete;
|
||||
final_action& operator=(final_action&&) = delete;
|
||||
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // terminate if throws
|
||||
// clang-format on
|
||||
~final_action() noexcept
|
||||
{
|
||||
if (invoke_) f_();
|
||||
}
|
||||
|
||||
private:
|
||||
F f_;
|
||||
bool invoke_{true};
|
||||
};
|
||||
|
||||
// finally() - convenience function to generate a final_action
|
||||
template <class F>
|
||||
GSL_NODISCARD final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>
|
||||
finally(F&& f) noexcept
|
||||
{
|
||||
return final_action<typename std::remove_cv<typename std::remove_reference<F>::type>::type>(
|
||||
std::forward<F>(f));
|
||||
}
|
||||
|
||||
// narrow_cast(): a searchable way to do narrowing casts of values
|
||||
template <class T, class U>
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
constexpr T narrow_cast(U&& u) noexcept
|
||||
{
|
||||
return static_cast<T>(std::forward<U>(u));
|
||||
}
|
||||
|
||||
//
|
||||
// at() - Bounds-checked way of accessing builtin arrays, std::array, std::vector
|
||||
//
|
||||
template <class T, std::size_t N>
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
|
||||
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
constexpr T& at(T (&arr)[N], const index i)
|
||||
{
|
||||
Expects(i >= 0 && i < narrow_cast<index>(N));
|
||||
return arr[narrow_cast<std::size_t>(i)];
|
||||
}
|
||||
|
||||
template <class Cont>
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
|
||||
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
|
||||
{
|
||||
Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
|
||||
using size_type = decltype(cont.size());
|
||||
return cont[narrow_cast<size_type>(i)];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
// clang-format off
|
||||
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
|
||||
// clang-format on
|
||||
constexpr T at(const std::initializer_list<T> cont, const index i)
|
||||
{
|
||||
Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
|
||||
return *(cont.begin() + i);
|
||||
}
|
||||
|
||||
#if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
|
||||
template <class T, size_t extent = std::dynamic_extent>
|
||||
constexpr auto at(std::span<T, extent> sp, const index i) -> decltype(sp[sp.size()])
|
||||
{
|
||||
Expects(i >= 0 && i < narrow_cast<index>(sp.size()));
|
||||
return sp[gsl::narrow_cast<size_t>(i)];
|
||||
}
|
||||
#endif // __cpp_lib_span >= 202002L
|
||||
} // namespace gsl
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
#endif // _MSC_VER
|
||||
|
||||
#endif // GSL_UTIL_H
|
||||
Vendored
+1
-1
Submodule 3rdparty/wil updated: 3018875eaa...ae986e12b2
@@ -22,7 +22,7 @@ Installers and binaries for both stable and development builds are available fro
|
||||
|
||||
| Operating System | CPU | GPU | RAM |
|
||||
| ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||
| - Windows 10 21H2 (1809 or later) (64-bit) <br/> - Ubuntu 20.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 1800<br/> - Two physical cores, with hyperthreading | - Direct3D10 support <br/> - OpenGL 3.x support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750, Radeon RX 560, Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
|
||||
| - Windows 10 Version 1809 or later (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports SSE4.1 <br/> - [PassMark Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 1800<br/> - Two physical cores, with hyperthreading | - Direct3D10 support <br/> - OpenGL 3.x support <br/> - Vulkan 1.1 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 3000 (Geforce GTX 750, Radeon RX 560, Intel Arc A380) <br/> - 2 GB Video Memory | 4 GB |
|
||||
|
||||
_Note: Recommended Single Thread Performance is based on moderately complex games. Games that pushed the PS2 hardware to its limits will struggle on CPUs at this level. Some release titles and 2D games which underutilized the PS2 hardware may run on CPUs rated as low as 1200. A quick reference for CPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:CPU_intensive_games), [Forum](https://forums.pcsx2.net/Thread-LIST-The-Most-CPU-Intensive-Games) and CPU **light** games: [Forum](https://forums.pcsx2.net/Thread-LIST-Games-that-don-t-need-a-strong-CPU-to-emulate)_
|
||||
|
||||
@@ -30,7 +30,7 @@ _Note: Recommended Single Thread Performance is based on moderately complex game
|
||||
|
||||
| Operating System | CPU | GPU | RAM |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||
| - Windows 10 21H2 (1809 or later) (64-bit) <br/> - Ubuntu 22.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 2600<br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650, Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
|
||||
| - Windows 10 22H2 (64-bit) <br/> - Ubuntu 23.04/Debian or newer, Arch Linux, or other distro (64-bit) <br/> - macOS 10.14 | - Supports AVX2 <br/> - [PassMark Single Thread Performance](https://www.cpubenchmark.net/CPU_mega_page.html) rating near or greater than 2600<br/> - Four physical cores, with or without hyperthreading | - Direct3D12 support <br/> - OpenGL 4.6 support <br/> - Vulkan 1.3 support <br/> - Metal support <br/> - [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 6000 (GeForce GTX 1650, Radeon RX 570) <br/> - 4 GB Video Memory | 8 GB |
|
||||
|
||||
_Note: Recommended GPU is based on 3x Internal, ~1080p resolution requirements. Higher resolutions will require stronger cards; 6x Internal, ~4K resolution will require a [PassMark G3D Mark](https://www.videocardbenchmark.net/high_end_gpus.html) rating around 12000 (GeForce RTX 2060 Radeon RX 6600 Intel Arc A750). Just like CPU requirements, this is also highly game dependent. A quick reference for GPU **intensive games**: [Wiki](https://wiki.pcsx2.net/Category:GPU_intensive_games)_
|
||||
|
||||
|
||||
+688
-200
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1067,10 +1067,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000c82d00000851000000010000,8BitDo P30,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:a8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00000660000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00000660000000010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000631000014010000,8BitDo Pro 2 Wired Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c82d00001030000011010000,8BitDo Pro 2 Wired Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000020000000000000,8BitDo Pro 2 Wired Controller for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
06000000c82d00000020000006010000,8BitDo Pro 2 Wired Controller for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c82d00000631000014010000,8BitDo Pro 2,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c82d00001030000011010000,8BitDo Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000020000000000000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
06000000c82d00000020000006010000,8BitDo Pro 2 for Xbox,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
03000000c82d00000131000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000231000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
@@ -1094,7 +1094,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
|
||||
05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001730000011010000,8BitDo Ultimate a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
03000000c82d00001130000011010000,8BitDo Ultimate Wired,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b26,paddle1:b24,paddle2:b25,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
@@ -1252,6 +1252,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000242f00008a00000011010000,JYS Adapter,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b0,y:b3,platform:Linux,
|
||||
030000006f0e00000103000000020000,Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
|
||||
030000006d040000d1ca000000000000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006d040000d1ca000011010000,Logitech Chillstream,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006d04000016c2000010010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000006d04000016c2000011010000,Logitech Dual Action,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(SHADER_MODEL) || defined(FXAA_GLSL_130) || defined(FXAA_GLSL_VK) || defined(__METAL_VERSION__)
|
||||
|
||||
#ifndef SHADER_MODEL
|
||||
|
||||
@@ -56,7 +56,7 @@ void main(uint3 LocalThreadId : SV_GroupThreadID, uint3 WorkGroupId : SV_GroupID
|
||||
#endif
|
||||
|
||||
// Filter.
|
||||
AF3 c;
|
||||
AF3 c = (float4)0.0f;
|
||||
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, sharpenOnly);
|
||||
OutputTexture[ASU2(gxy)] = AF4(c, 1);
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
|
||||
struct VS_INPUT
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
cbuffer vertexBuffer : register(b0)
|
||||
{
|
||||
float4x4 ProjectionMatrix;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
|
||||
Texture2D Texture;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
|
||||
Texture2D Texture;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
|
||||
#ifndef PS_SCALE_FACTOR
|
||||
@@ -395,4 +410,46 @@ PS_OUTPUT ps_filter_lottes(PS_INPUT input)
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_4x_rgss(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
float2 dxy = float2(ddx(input.t.x), ddy(input.t.y));
|
||||
float3 color = 0;
|
||||
|
||||
float s = 1.0/8.0;
|
||||
float l = 3.0/8.0;
|
||||
|
||||
color += sample_c(input.t + float2( s, l) * dxy).rgb;
|
||||
color += sample_c(input.t + float2( l,-s) * dxy).rgb;
|
||||
color += sample_c(input.t + float2(-s,-l) * dxy).rgb;
|
||||
color += sample_c(input.t + float2(-l, s) * dxy).rgb;
|
||||
|
||||
output.c = float4(color * 0.25,1);
|
||||
return output;
|
||||
}
|
||||
|
||||
PS_OUTPUT ps_automagical_supersampling(PS_INPUT input)
|
||||
{
|
||||
PS_OUTPUT output;
|
||||
|
||||
float2 ratio = (u_source_size / u_target_size) * 0.5;
|
||||
float2 steps = floor(ratio);
|
||||
float3 col = sample_c(input.t).rgb;
|
||||
float div = 1;
|
||||
|
||||
for (float y = 0; y < steps.y; y++)
|
||||
{
|
||||
for (float x = 0; x < steps.x; x++)
|
||||
{
|
||||
float2 offset = float2(x,y) - ratio * 0.5;
|
||||
col += sample_c(input.t + offset * u_rcp_source_resolution * 2.0).rgb;
|
||||
div++;
|
||||
}
|
||||
}
|
||||
|
||||
output.c = float4(col / div, 1);
|
||||
return output;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef SHADER_MODEL // make safe to include in resource file to enforce dependency
|
||||
|
||||
Texture2D Texture;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define FMT_32 0
|
||||
#define FMT_24 1
|
||||
#define FMT_16 2
|
||||
|
||||
@@ -46,7 +46,7 @@ void main()
|
||||
AU2 gxy = ARmp8x8(gl_LocalInvocationID.x)+AU2(gl_WorkGroupID.x<<4u,gl_WorkGroupID.y<<4u);
|
||||
|
||||
// Filter.
|
||||
AF4 c;
|
||||
AF4 c = vec4(0.0f);
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, CAS_SHARPEN_ONLY);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x += 8u;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
|
||||
@@ -367,7 +382,7 @@ uniform ivec2 EMOD;
|
||||
void ps_yuv()
|
||||
{
|
||||
vec4 i = sample_c();
|
||||
vec4 o;
|
||||
vec4 o = vec4(0.0f);
|
||||
|
||||
mat3 rgb2yuv; // Value from GS manual
|
||||
rgb2yuv[0] = vec3(0.587, -0.311, -0.419);
|
||||
@@ -380,7 +395,8 @@ void ps_yuv()
|
||||
float Cr = float(0xE0)/255.0f * yuv.y + float(0x80)/255.0f;
|
||||
float Cb = float(0xE0)/255.0f * yuv.z + float(0x80)/255.0f;
|
||||
|
||||
switch(EMOD.x) {
|
||||
switch(EMOD.x)
|
||||
{
|
||||
case 0:
|
||||
o.a = i.a;
|
||||
break;
|
||||
@@ -395,7 +411,8 @@ void ps_yuv()
|
||||
break;
|
||||
}
|
||||
|
||||
switch(EMOD.y) {
|
||||
switch(EMOD.y)
|
||||
{
|
||||
case 0:
|
||||
o.rgb = i.rgb;
|
||||
break;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 Position;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef FRAGMENT_SHADER
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
|
||||
@@ -54,6 +69,11 @@ vec4 sample_c()
|
||||
return texture(TextureSampler, PSin_t);
|
||||
}
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
{
|
||||
return texture(TextureSampler, uv);
|
||||
}
|
||||
|
||||
vec4 ps_crt(uint i)
|
||||
{
|
||||
vec4 mask[4] = vec4[4](
|
||||
@@ -384,4 +404,44 @@ void ps_filter_lottes()
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ps_4x_rgss
|
||||
void ps_4x_rgss()
|
||||
{
|
||||
vec2 dxy = vec2(dFdx(PSin_t.x), dFdy(PSin_t.y));
|
||||
vec3 color = vec3(0);
|
||||
|
||||
float s = 1.0/8.0;
|
||||
float l = 3.0/8.0;
|
||||
|
||||
color += sample_c(PSin_t + vec2( s, l) * dxy).rgb;
|
||||
color += sample_c(PSin_t + vec2( l,-s) * dxy).rgb;
|
||||
color += sample_c(PSin_t + vec2(-s,-l) * dxy).rgb;
|
||||
color += sample_c(PSin_t + vec2(-l, s) * dxy).rgb;
|
||||
|
||||
SV_Target0 = vec4(color * 0.25,1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_automagical_supersampling
|
||||
void ps_automagical_supersampling()
|
||||
{
|
||||
vec2 ratio = (u_source_size / u_target_size) * 0.5;
|
||||
vec2 steps = floor(ratio);
|
||||
vec3 col = sample_c(PSin_t).rgb;
|
||||
float div = 1;
|
||||
|
||||
for (float y = 0; y < steps.y; y++)
|
||||
{
|
||||
for (float x = 0; x < steps.x; x++)
|
||||
{
|
||||
vec2 offset = vec2(x,y) - ratio * 0.5;
|
||||
col += sample_c(PSin_t + offset * u_rcp_source_resolution * 2.0).rgb;
|
||||
div++;
|
||||
}
|
||||
}
|
||||
|
||||
SV_Target0 = vec4(col / div, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for text editor detection
|
||||
|
||||
#define FMT_32 0
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for text editor detection
|
||||
|
||||
layout(std140, binding = 1) uniform cb20
|
||||
|
||||
@@ -53,7 +53,7 @@ void main()
|
||||
AU2 gxy = ARmp8x8(gl_LocalInvocationID.x)+AU2(gl_WorkGroupID.x<<4u,gl_WorkGroupID.y<<4u);
|
||||
|
||||
// Filter.
|
||||
AF4 c;
|
||||
AF4 c = vec4(0.0f);
|
||||
CasFilter(c.r, c.g, c.b, gxy, const0, const1, sharpenOnly != 0);
|
||||
imageStore(imgDst, ASU2(gxy), c);
|
||||
gxy.x += 8u;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
@@ -348,7 +363,7 @@ layout(push_constant) uniform cb10
|
||||
void ps_yuv()
|
||||
{
|
||||
vec4 i = sample_c(v_tex);
|
||||
vec4 o;
|
||||
vec4 o = vec4(0.0f);
|
||||
|
||||
mat3 rgb2yuv;
|
||||
rgb2yuv[0] = vec3(0.587, -0.311, -0.419);
|
||||
@@ -361,7 +376,8 @@ void ps_yuv()
|
||||
float Cr = float(0xE0)/255.0f * yuv.y + float(0x80)/255.0f;
|
||||
float Cb = float(0xE0)/255.0f * yuv.z + float(0x80)/255.0f;
|
||||
|
||||
switch(EMODA) {
|
||||
switch(EMODA)
|
||||
{
|
||||
case 0:
|
||||
o.a = i.a;
|
||||
break;
|
||||
@@ -376,7 +392,8 @@ void ps_yuv()
|
||||
break;
|
||||
}
|
||||
|
||||
switch(EMODC) {
|
||||
switch(EMODC)
|
||||
{
|
||||
case 0:
|
||||
o.rgb = i.rgb;
|
||||
break;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec2 Position;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
layout(location = 0) in vec4 a_pos;
|
||||
@@ -359,4 +374,44 @@ void ps_filter_lottes()
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ps_4x_rgss
|
||||
void ps_4x_rgss()
|
||||
{
|
||||
vec2 dxy = vec2(dFdx(v_tex.x), dFdy(v_tex.y));
|
||||
vec3 color = vec3(0);
|
||||
|
||||
float s = 1.0/8.0;
|
||||
float l = 3.0/8.0;
|
||||
|
||||
color += sample_c(v_tex + vec2( s, l) * dxy).rgb;
|
||||
color += sample_c(v_tex + vec2( l,-s) * dxy).rgb;
|
||||
color += sample_c(v_tex + vec2(-s,-l) * dxy).rgb;
|
||||
color += sample_c(v_tex + vec2(-l, s) * dxy).rgb;
|
||||
|
||||
o_col0 = vec4(color * 0.25,1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_automagical_supersampling
|
||||
void ps_automagical_supersampling()
|
||||
{
|
||||
vec2 ratio = (u_source_size / u_target_size) * 0.5;
|
||||
vec2 steps = floor(ratio);
|
||||
vec3 col = sample_c(v_tex).rgb;
|
||||
float div = 1;
|
||||
|
||||
for (float y = 0; y < steps.y; y++)
|
||||
{
|
||||
for (float x = 0; x < steps.x; x++)
|
||||
{
|
||||
vec2 offset = vec2(x,y) - ratio * 0.5;
|
||||
col += sample_c(v_tex + offset * u_rcp_source_resolution * 2.0).rgb;
|
||||
div++;
|
||||
}
|
||||
}
|
||||
|
||||
o_col0 = vec4(col / div, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//#version 420 // Keep it for editor detection
|
||||
|
||||
#ifdef VERTEX_SHADER
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Vertex Shader
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@@ -336,12 +351,12 @@ layout(set = 1, binding = 1) uniform texture2D Palette;
|
||||
#endif
|
||||
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED
|
||||
#ifndef DISABLE_TEXTURE_BARRIER
|
||||
layout(input_attachment_index = 0, set = 2, binding = 0) uniform subpassInput RtSampler;
|
||||
vec4 sample_from_rt() { return subpassLoad(RtSampler); }
|
||||
#else
|
||||
#if defined(DISABLE_TEXTURE_BARRIER) || defined(HAS_FEEDBACK_LOOP_LAYOUT)
|
||||
layout(set = 2, binding = 0) uniform texture2D RtSampler;
|
||||
vec4 sample_from_rt() { return texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0); }
|
||||
#else
|
||||
layout(input_attachment_index = 0, set = 2, binding = 0) uniform subpassInput RtSampler;
|
||||
vec4 sample_from_rt() { return subpassLoad(RtSampler); }
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1218,7 +1233,7 @@ void main()
|
||||
#endif
|
||||
|
||||
#if (SW_AD_TO_HW)
|
||||
vec4 RT = trunc(subpassLoad(RtSampler) * 255.0f + 0.1f);
|
||||
vec4 RT = trunc(sample_from_rt() * 255.0f + 0.1f);
|
||||
vec4 alpha_blend = vec4(RT.a / 128.0f);
|
||||
#else
|
||||
vec4 alpha_blend = vec4(C.a / 128.0f);
|
||||
|
||||
@@ -36,6 +36,9 @@ if(UNIX AND NOT APPLE)
|
||||
option(X11_API "Enable X11 support" ON)
|
||||
option(WAYLAND_API "Enable Wayland support" ON)
|
||||
option(DBUS_API "Enable DBus support for screensaver inhibiting" ON)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
option(USE_LINKED_FFMPEG "Links with ffmpeg instead of using dynamic loading" OFF)
|
||||
endif()
|
||||
|
||||
@@ -134,6 +137,10 @@ add_compile_options("${ARCH_FLAG_LIST}")
|
||||
option(USE_PGO_GENERATE "Enable PGO optimization (generate profile)")
|
||||
option(USE_PGO_OPTIMIZE "Enable PGO optimization (use profile)")
|
||||
|
||||
# Require C++20.
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
if(MSVC AND NOT USE_CLANG_CL)
|
||||
add_compile_options(
|
||||
"$<$<COMPILE_LANGUAGE:CXX>:/Zc:externConstexpr>"
|
||||
@@ -270,18 +277,7 @@ if(NOT CMAKE_GENERATOR MATCHES "Xcode")
|
||||
# Assume Xcode builds aren't being used for distribution
|
||||
# Helpful because Xcode builds don't build multiple metallibs for different macOS versions
|
||||
# Also helpful because Xcode's interactive shader debugger requires apps be built for the latest macOS
|
||||
if (QT_BUILD)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14)
|
||||
else()
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.13)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (APPLE AND CMAKE_OSX_DEPLOYMENT_TARGET AND "${CMAKE_OSX_DEPLOYMENT_TARGET}" VERSION_LESS 10.14 AND NOT ${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 9)
|
||||
# Older versions of the macOS stdlib don't have operator new(size_t, align_val_t)
|
||||
# Disable use of them with this flag
|
||||
# Not great, but also no worse that what we were getting before we turned on C++17
|
||||
add_compile_options(-fno-aligned-allocation)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.14)
|
||||
endif()
|
||||
|
||||
# CMake defaults the suffix for modules to .so on macOS but wx tells us that the
|
||||
|
||||
@@ -9,11 +9,15 @@ if (WIN32)
|
||||
add_subdirectory(3rdparty/zlib EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/libpng EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/libjpeg EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/wil EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/xz EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(3rdparty/D3D12MemAlloc EXCLUDE_FROM_ALL)
|
||||
set(FFMPEG_INCLUDE_DIRS "${CMAKE_SOURCE_DIR}/3rdparty/ffmpeg/include")
|
||||
find_package(Vtune)
|
||||
|
||||
# Don't try to build tests for WIL, it needs NuGet.
|
||||
set(WIL_BUILD_TESTS OFF CACHE BOOL "")
|
||||
set(WIL_BUILD_PACKAGING OFF CACHE BOOL "")
|
||||
add_subdirectory(3rdparty/wil EXCLUDE_FROM_ALL)
|
||||
else()
|
||||
find_package(PCAP REQUIRED)
|
||||
find_package(LibLZMA REQUIRED)
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// An implementation of bit_cast until we get c++20
|
||||
|
||||
template<class T2, class T1>
|
||||
T2 bit_cast(const T1& src)
|
||||
{
|
||||
static_assert(sizeof(T2) == sizeof(T1), "bit_cast: types must be equal size");
|
||||
static_assert(std::is_pod<T1>::value, "bit_cast: source must be POD");
|
||||
static_assert(std::is_pod<T2>::value, "bit_cast: destination must be POD");
|
||||
T2 dst;
|
||||
memcpy(&dst, &src, sizeof(T2));
|
||||
return dst;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2002-2021 PCSX2 Dev Team
|
||||
* Copyright (C) 2002-2023 PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
@@ -14,8 +14,29 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
#include <bit>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#include <intrin.h>
|
||||
|
||||
#else
|
||||
|
||||
static inline int _BitScanReverse(unsigned long* const Index, const unsigned long Mask)
|
||||
{
|
||||
if (Mask == 0)
|
||||
return 0;
|
||||
|
||||
// For some reason, clang won't emit bsr if we use std::countl_zeros()...
|
||||
*Index = 31 - __builtin_clz(Mask);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace Common
|
||||
{
|
||||
template <typename T>
|
||||
@@ -54,46 +75,24 @@ namespace Common
|
||||
return value & static_cast<T>(~static_cast<T>(alignment - 1));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static constexpr __fi bool IsPow2(T value)
|
||||
{
|
||||
return (value & (value - 1)) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static constexpr __fi T PreviousPow2(T value)
|
||||
{
|
||||
if (value == static_cast<T>(0))
|
||||
return 0;
|
||||
|
||||
value |= (value >> 1);
|
||||
value |= (value >> 2);
|
||||
value |= (value >> 4);
|
||||
value |= (value >> 8);
|
||||
value |= (value >> 16);
|
||||
return value - (value >> 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr __fi T NextPow2(T value)
|
||||
{
|
||||
if (value == static_cast<T>(0))
|
||||
return 0;
|
||||
|
||||
value--;
|
||||
value |= value >> 1;
|
||||
value |= value >> 2;
|
||||
value |= value >> 4;
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
value++;
|
||||
return value;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static constexpr T PageAlign(T size)
|
||||
{
|
||||
static_assert(Common::IsPow2(__pagesize), "Page size is a power of 2");
|
||||
static_assert(std::has_single_bit(__pagesize), "Page size is a power of 2");
|
||||
return Common::AlignUpPow2(size, __pagesize);
|
||||
}
|
||||
|
||||
__fi static u32 CountLeadingSignBits(s32 n)
|
||||
{
|
||||
// If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
|
||||
if (n < 0)
|
||||
n = ~n;
|
||||
|
||||
// If BSR is used directly, it would have an undefined value for 0.
|
||||
if (n == 0)
|
||||
return 32;
|
||||
|
||||
// Perform our count leading zero.
|
||||
return std::countl_zero(static_cast<u32>(n));
|
||||
}
|
||||
} // namespace Common
|
||||
@@ -30,6 +30,7 @@ target_sources(common PRIVATE
|
||||
Semaphore.cpp
|
||||
SettingsWrapper.cpp
|
||||
StringUtil.cpp
|
||||
TextureDecompress.cpp
|
||||
Timer.cpp
|
||||
ThreadPool.cpp
|
||||
WAVWriter.cpp
|
||||
@@ -60,10 +61,10 @@ target_sources(common PRIVATE
|
||||
|
||||
# x86emitter headers
|
||||
target_sources(common PRIVATE
|
||||
Align.h
|
||||
AlignedMalloc.h
|
||||
Assertions.h
|
||||
boost_spsc_queue.hpp
|
||||
BitUtils.h
|
||||
ByteSwap.h
|
||||
Console.h
|
||||
CrashHandler.h
|
||||
@@ -94,6 +95,7 @@ target_sources(common PRIVATE
|
||||
SettingsWrapper.h
|
||||
StringUtil.h
|
||||
Timer.h
|
||||
TextureDecompress.h
|
||||
Threading.h
|
||||
ThreadPool.h
|
||||
TraceLog.h
|
||||
|
||||
+2
-2
@@ -88,7 +88,7 @@ void Error::SetWin32(unsigned long err)
|
||||
if (r > 0)
|
||||
m_description = fmt::format("Win32 Error {}: {}", err, std::string_view(buf, r));
|
||||
else
|
||||
m_description = fmt::format("Win32 Error {}: <Could not resolve system error ID>");
|
||||
m_description = fmt::format("Win32 Error {}: <Could not resolve system error ID>", err);
|
||||
}
|
||||
|
||||
void Error::SetWin32(Error* errptr, unsigned long err)
|
||||
@@ -106,7 +106,7 @@ void Error::SetHResult(long err)
|
||||
if (r > 0)
|
||||
m_description = fmt::format("HRESULT {:08X}: {}", err, std::string_view(buf, r));
|
||||
else
|
||||
m_description = fmt::format("HRESULT {:08X}: <Could not resolve system error ID>");
|
||||
m_description = fmt::format("HRESULT {:08X}: <Could not resolve system error ID>", err);
|
||||
}
|
||||
|
||||
void Error::SetHResult(Error* errptr, long err)
|
||||
|
||||
+15
-8
@@ -38,6 +38,7 @@
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "RedtapeWindows.h"
|
||||
#include <io.h>
|
||||
#include <winioctl.h>
|
||||
#include <share.h>
|
||||
#include <shlobj.h>
|
||||
@@ -672,7 +673,7 @@ int FileSystem::OpenFDFile(const char* filename, int flags, int mode, Error* err
|
||||
|
||||
FileSystem::ManagedCFilePtr FileSystem::OpenManagedCFile(const char* filename, const char* mode, Error* error)
|
||||
{
|
||||
return ManagedCFilePtr(OpenCFile(filename, mode, error), [](std::FILE* fp) { std::fclose(fp); });
|
||||
return ManagedCFilePtr(OpenCFile(filename, mode, error));
|
||||
}
|
||||
|
||||
std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error)
|
||||
@@ -717,7 +718,7 @@ std::FILE* FileSystem::OpenSharedCFile(const char* filename, const char* mode, F
|
||||
|
||||
FileSystem::ManagedCFilePtr FileSystem::OpenManagedSharedCFile(const char* filename, const char* mode, FileShareMode share_mode, Error* error)
|
||||
{
|
||||
return ManagedCFilePtr(OpenSharedCFile(filename, mode, share_mode, error), [](std::FILE* fp) { std::fclose(fp); });
|
||||
return ManagedCFilePtr(OpenSharedCFile(filename, mode, share_mode, error));
|
||||
}
|
||||
|
||||
int FileSystem::FSeek64(std::FILE* fp, s64 offset, int whence)
|
||||
@@ -747,6 +748,13 @@ s64 FileSystem::FTell64(std::FILE* fp)
|
||||
|
||||
s64 FileSystem::FSize64(std::FILE* fp)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const int fd = _fileno(fp);
|
||||
if (fd >= 0)
|
||||
{
|
||||
return _filelengthi64(fd);
|
||||
}
|
||||
#else
|
||||
const s64 pos = FTell64(fp);
|
||||
if (pos >= 0)
|
||||
{
|
||||
@@ -757,6 +765,7 @@ s64 FileSystem::FSize64(std::FILE* fp)
|
||||
return size;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -781,12 +790,11 @@ std::optional<std::vector<u8>> FileSystem::ReadBinaryFile(const char* filename)
|
||||
|
||||
std::optional<std::vector<u8>> FileSystem::ReadBinaryFile(std::FILE* fp)
|
||||
{
|
||||
std::fseek(fp, 0, SEEK_END);
|
||||
const long size = std::ftell(fp);
|
||||
std::fseek(fp, 0, SEEK_SET);
|
||||
const s64 size = FSize64(fp);
|
||||
if (size < 0)
|
||||
return std::nullopt;
|
||||
|
||||
std::fseek(fp, 0, SEEK_SET);
|
||||
std::vector<u8> res(static_cast<size_t>(size));
|
||||
if (size > 0 && std::fread(res.data(), 1u, static_cast<size_t>(size), fp) != static_cast<size_t>(size))
|
||||
return std::nullopt;
|
||||
@@ -805,12 +813,11 @@ std::optional<std::string> FileSystem::ReadFileToString(const char* filename)
|
||||
|
||||
std::optional<std::string> FileSystem::ReadFileToString(std::FILE* fp)
|
||||
{
|
||||
std::fseek(fp, 0, SEEK_END);
|
||||
const long size = std::ftell(fp);
|
||||
std::fseek(fp, 0, SEEK_SET);
|
||||
const s64 size = FSize64(fp);
|
||||
if (size < 0)
|
||||
return std::nullopt;
|
||||
|
||||
std::fseek(fp, 0, SEEK_SET);
|
||||
std::string res;
|
||||
res.resize(static_cast<size_t>(size));
|
||||
// NOTE - assumes mode 'rb', for example, this will fail over missing Windows carriage return bytes
|
||||
|
||||
+10
-1
@@ -102,8 +102,17 @@ namespace FileSystem
|
||||
/// Rename file
|
||||
bool RenamePath(const char* OldPath, const char* NewPath);
|
||||
|
||||
/// Deleter functor for managed file pointers
|
||||
struct FileDeleter
|
||||
{
|
||||
void operator()(std::FILE* fp)
|
||||
{
|
||||
std::fclose(fp);
|
||||
}
|
||||
};
|
||||
|
||||
/// open files
|
||||
using ManagedCFilePtr = std::unique_ptr<std::FILE, void (*)(std::FILE*)>;
|
||||
using ManagedCFilePtr = std::unique_ptr<std::FILE, FileDeleter>;
|
||||
ManagedCFilePtr OpenManagedCFile(const char* filename, const char* mode, Error* error = nullptr);
|
||||
std::FILE* OpenCFile(const char* filename, const char* mode, Error* error = nullptr);
|
||||
int FSeek64(std::FILE* fp, s64 offset, int whence);
|
||||
|
||||
@@ -60,8 +60,6 @@ namespace detail
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
// This requires C++20, so fallback to ugly heap allocations if we don't have it.
|
||||
#if __cplusplus >= 202002L
|
||||
template <typename ValueType>
|
||||
using UnorderedStringMap =
|
||||
std::unordered_map<std::string, ValueType, detail::transparent_string_hash, detail::transparent_string_equal>;
|
||||
@@ -73,84 +71,6 @@ using UnorderedStringSet =
|
||||
using UnorderedStringMultiSet =
|
||||
std::unordered_multiset<std::string, detail::transparent_string_hash, detail::transparent_string_equal>;
|
||||
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMap<ValueType>::const_iterator
|
||||
UnorderedStringMapFind(const UnorderedStringMap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(key);
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMap<ValueType>::iterator
|
||||
UnorderedStringMapFind(UnorderedStringMap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(key);
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMultimap<ValueType>::const_iterator
|
||||
UnorderedStringMultiMapFind(const UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(key);
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi std::pair<typename UnorderedStringMultimap<ValueType>::const_iterator, typename UnorderedStringMultimap<ValueType>::const_iterator>
|
||||
UnorderedStringMultiMapEqualRange(const UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.equal_range(key);
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMultimap<ValueType>::iterator
|
||||
UnorderedStringMultiMapFind(UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(key);
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi std::pair<typename UnorderedStringMultimap<ValueType>::iterator, typename UnorderedStringMultimap<ValueType>::iterator>
|
||||
UnorderedStringMultiMapEqualRange(UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.equal_range(key);
|
||||
}
|
||||
#else
|
||||
template <typename ValueType>
|
||||
using UnorderedStringMap = std::unordered_map<std::string, ValueType>;
|
||||
template <typename ValueType>
|
||||
using UnorderedStringMultimap = std::unordered_multimap<std::string, ValueType>;
|
||||
using UnorderedStringSet = std::unordered_set<std::string>;
|
||||
using UnorderedStringMultiSet = std::unordered_multiset<std::string>;
|
||||
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMap<ValueType>::const_iterator UnorderedStringMapFind(const UnorderedStringMap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(std::string(key));
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMap<ValueType>::iterator UnorderedStringMapFind(UnorderedStringMap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(std::string(key));
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMultimap<ValueType>::const_iterator UnorderedStringMultiMapFind(const UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(std::string(key));
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi std::pair<typename UnorderedStringMultimap<ValueType>::const_iterator, typename UnorderedStringMultimap<ValueType>::const_iterator>
|
||||
UnorderedStringMultiMapEqualRange(const UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.equal_range(std::string(key));
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi typename UnorderedStringMultimap<ValueType>::iterator UnorderedStringMultiMapFind(UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.find(std::string(key));
|
||||
}
|
||||
template <typename KeyType, typename ValueType>
|
||||
__fi std::pair<typename UnorderedStringMultimap<ValueType>::iterator, typename UnorderedStringMultimap<ValueType>::iterator>
|
||||
UnorderedStringMultiMapEqualRange(UnorderedStringMultimap<ValueType>& map, const KeyType& key)
|
||||
{
|
||||
return map.equal_range(std::string(key));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename ValueType>
|
||||
using StringMap = std::map<std::string, ValueType, detail::transparent_string_less>;
|
||||
template <typename ValueType>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#include "fmt/core.h"
|
||||
|
||||
#include "common/Align.h"
|
||||
#include "common/BitUtils.h"
|
||||
#include "common/Assertions.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/General.h"
|
||||
@@ -108,7 +108,8 @@ static void SysPageFaultSignalFilter(int signal, siginfo_t* siginfo, void* ctx)
|
||||
void* const exception_pc = nullptr;
|
||||
#endif
|
||||
|
||||
const PageFaultInfo pfi{(uptr)exception_pc, (uptr)siginfo->si_addr & ~__pagemask};
|
||||
const PageFaultInfo pfi{
|
||||
reinterpret_cast<uptr>(exception_pc), reinterpret_cast<uptr>(siginfo->si_addr) & ~static_cast<uptr>(__pagemask)};
|
||||
|
||||
s_in_exception_handler = true;
|
||||
|
||||
|
||||
+42
-36
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "common/Pcsx2Types.h"
|
||||
#include "common/General.h"
|
||||
#include "common/ScopedGuard.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "common/Threading.h"
|
||||
#include "common/WindowInfo.h"
|
||||
@@ -70,66 +71,72 @@ std::string GetOSVersionString()
|
||||
|
||||
#ifdef DBUS_API
|
||||
|
||||
bool ChangeScreenSaverStateDBus(const bool inhibit_requested, const char* program_name, const char* reason)
|
||||
static bool SetScreensaverInhibitDBus(const bool inhibit_requested, const char* program_name, const char* reason)
|
||||
{
|
||||
static dbus_uint32_t s_cookie;
|
||||
// "error_dbus" doesn't need to be cleared in the end with "dbus_message_unref" at least if there is
|
||||
// no error set, since calling "dbus_error_free" reinitializes it like "dbus_error_init" after freeing.
|
||||
const char* bus_method = (inhibit_requested) ? "Inhibit" : "UnInhibit";
|
||||
DBusError error_dbus;
|
||||
dbus_error_init(&error_dbus);
|
||||
DBusConnection* connection = nullptr;
|
||||
static DBusConnection* s_comparison_connection;
|
||||
DBusMessage* message = nullptr;
|
||||
DBusMessage* response = nullptr;
|
||||
// Initialized here because initializations should be before "goto" statements.
|
||||
const char* bus_method = (inhibit_requested) ? "Inhibit" : "UnInhibit";
|
||||
// "dbus_bus_get" gets a pointer to the same connection in libdbus, if exists, without creating a new connection.
|
||||
// this doesn't need to be deleted, except if there's an error then calling "dbus_connection_unref", to free it,
|
||||
// might be better so a new connection is established on the next try.
|
||||
if (!(connection = dbus_bus_get(DBUS_BUS_SESSION, &error_dbus)) || (dbus_error_is_set(&error_dbus)))
|
||||
goto cleanup;
|
||||
if (!(message = dbus_message_new_method_call("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", bus_method)))
|
||||
goto cleanup;
|
||||
// Initialize an append iterator for the message, gets freed with the message.
|
||||
DBusMessageIter message_itr;
|
||||
|
||||
ScopedGuard cleanup = [&]() {
|
||||
if (dbus_error_is_set(&error_dbus))
|
||||
dbus_error_free(&error_dbus);
|
||||
if (message)
|
||||
dbus_message_unref(message);
|
||||
if (response)
|
||||
dbus_message_unref(response);
|
||||
};
|
||||
|
||||
dbus_error_init(&error_dbus);
|
||||
// Calling dbus_bus_get() after the first time returns a pointer to the existing connection.
|
||||
connection = dbus_bus_get(DBUS_BUS_SESSION, &error_dbus);
|
||||
if (!connection || (dbus_error_is_set(&error_dbus)))
|
||||
return false;
|
||||
if (s_comparison_connection != connection)
|
||||
{
|
||||
dbus_connection_set_exit_on_disconnect(connection, false);
|
||||
s_cookie = 0;
|
||||
s_comparison_connection = connection;
|
||||
}
|
||||
message = dbus_message_new_method_call("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", bus_method);
|
||||
if (!message)
|
||||
return false;
|
||||
// Initialize an append iterator for the message, gets freed with the message.
|
||||
dbus_message_iter_init_append(message, &message_itr);
|
||||
if (inhibit_requested)
|
||||
{
|
||||
// Guard against repeat inhibitions which would add extra inhibitors each generating a different cookie.
|
||||
if (s_cookie)
|
||||
return false;
|
||||
// Append process/window name.
|
||||
if (!dbus_message_iter_append_basic(&message_itr, DBUS_TYPE_STRING, &program_name))
|
||||
goto cleanup;
|
||||
return false;
|
||||
// Append reason for inhibiting the screensaver.
|
||||
if (!dbus_message_iter_append_basic(&message_itr, DBUS_TYPE_STRING, &reason))
|
||||
goto cleanup;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only Append the cookie.
|
||||
if (!dbus_message_iter_append_basic(&message_itr, DBUS_TYPE_UINT32, &s_cookie))
|
||||
goto cleanup;
|
||||
return false;
|
||||
}
|
||||
// Send message and get response.
|
||||
if (!(response = dbus_connection_send_with_reply_and_block(connection, message, DBUS_TIMEOUT_USE_DEFAULT, &error_dbus))
|
||||
|| dbus_error_is_set(&error_dbus))
|
||||
goto cleanup;
|
||||
response = dbus_connection_send_with_reply_and_block(connection, message, DBUS_TIMEOUT_USE_DEFAULT, &error_dbus);
|
||||
if (!response || dbus_error_is_set(&error_dbus))
|
||||
return false;
|
||||
s_cookie = 0;
|
||||
if (inhibit_requested)
|
||||
{
|
||||
// Get the cookie from the response message.
|
||||
if (!dbus_message_get_args(response, &error_dbus, DBUS_TYPE_UINT32, &s_cookie, DBUS_TYPE_INVALID))
|
||||
goto cleanup;
|
||||
if (!dbus_message_get_args(response, &error_dbus, DBUS_TYPE_UINT32, &s_cookie, DBUS_TYPE_INVALID) || dbus_error_is_set(&error_dbus))
|
||||
return false;
|
||||
}
|
||||
dbus_message_unref(message);
|
||||
dbus_message_unref(response);
|
||||
return true;
|
||||
cleanup:
|
||||
if (dbus_error_is_set(&error_dbus))
|
||||
dbus_error_free(&error_dbus);
|
||||
if (connection)
|
||||
dbus_connection_unref(connection);
|
||||
if (message)
|
||||
dbus_message_unref(message);
|
||||
if (response)
|
||||
dbus_message_unref(response);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -176,11 +183,10 @@ bool WindowInfo::InhibitScreensaver(const WindowInfo& wi, bool inhibit)
|
||||
|
||||
#ifdef DBUS_API
|
||||
|
||||
return ChangeScreenSaverStateDBus(inhibit, "PCSX2", "PCSX2 VM is running.");
|
||||
return SetScreensaverInhibitDBus(inhibit, "PCSX2", "PCSX2 VM is running.");
|
||||
|
||||
#else
|
||||
|
||||
//ChangeScreenSaverStateDBus
|
||||
if (s_inhibit_window_info.has_value())
|
||||
{
|
||||
// Bit of extra logic here, because wx spams it and we don't want to
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/* PCSX2 - PS2 Emulator for PCs
|
||||
* Copyright (C) 2014- PCSX2 Dev Team
|
||||
*
|
||||
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU Lesser General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with PCSX2.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
// Hopefully this file will be used for cross-source math utilities.
|
||||
// Currently these are strewn across the code base. Please collect them all!
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
// On GCC >= 4.7, this is equivalent to __builtin_clrsb(n);
|
||||
inline u32 count_leading_sign_bits(s32 n)
|
||||
{
|
||||
// If the sign bit is 1, we invert the bits to 0 for count-leading-zero.
|
||||
if (n < 0)
|
||||
n = ~n;
|
||||
|
||||
// If BSR is used directly, it would have an undefined value for 0.
|
||||
if (n == 0)
|
||||
return 32;
|
||||
|
||||
// Perform our count leading zero.
|
||||
#ifdef _MSC_VER
|
||||
unsigned long ret;
|
||||
_BitScanReverse(&ret, n);
|
||||
return 31 - (u32)ret;
|
||||
#else
|
||||
return __builtin_clz(n);
|
||||
#endif
|
||||
}
|
||||
@@ -32,7 +32,7 @@ void MemorySettingsInterface::Clear()
|
||||
|
||||
bool MemorySettingsInterface::GetIntValue(const char* section, const char* key, s32* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
@@ -50,11 +50,11 @@ bool MemorySettingsInterface::GetIntValue(const char* section, const char* key,
|
||||
|
||||
bool MemorySettingsInterface::GetUIntValue(const char* section, const char* key, u32* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
|
||||
const auto iter = sit->second.find(key);
|
||||
if (iter == sit->second.end())
|
||||
return false;
|
||||
|
||||
@@ -68,11 +68,11 @@ bool MemorySettingsInterface::GetUIntValue(const char* section, const char* key,
|
||||
|
||||
bool MemorySettingsInterface::GetFloatValue(const char* section, const char* key, float* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
|
||||
const auto iter = sit->second.find(key);
|
||||
if (iter == sit->second.end())
|
||||
return false;
|
||||
|
||||
@@ -86,11 +86,11 @@ bool MemorySettingsInterface::GetFloatValue(const char* section, const char* key
|
||||
|
||||
bool MemorySettingsInterface::GetDoubleValue(const char* section, const char* key, double* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
|
||||
const auto iter = sit->second.find(key);
|
||||
if (iter == sit->second.end())
|
||||
return false;
|
||||
|
||||
@@ -104,11 +104,11 @@ bool MemorySettingsInterface::GetDoubleValue(const char* section, const char* ke
|
||||
|
||||
bool MemorySettingsInterface::GetBoolValue(const char* section, const char* key, bool* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
|
||||
const auto iter = sit->second.find(key);
|
||||
if (iter == sit->second.end())
|
||||
return false;
|
||||
|
||||
@@ -122,11 +122,11 @@ bool MemorySettingsInterface::GetBoolValue(const char* section, const char* key,
|
||||
|
||||
bool MemorySettingsInterface::GetStringValue(const char* section, const char* key, std::string* value) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
const auto iter = UnorderedStringMultiMapFind(sit->second, key);
|
||||
const auto iter = sit->second.find(key);
|
||||
if (iter == sit->second.end())
|
||||
return false;
|
||||
|
||||
@@ -167,7 +167,7 @@ void MemorySettingsInterface::SetStringValue(const char* section, const char* ke
|
||||
std::vector<std::pair<std::string, std::string>> MemorySettingsInterface::GetKeyValueList(const char* section) const
|
||||
{
|
||||
std::vector<std::pair<std::string, std::string>> output;
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit != m_sections.end())
|
||||
{
|
||||
for (const auto& it : sit->second)
|
||||
@@ -178,7 +178,7 @@ std::vector<std::pair<std::string, std::string>> MemorySettingsInterface::GetKey
|
||||
|
||||
void MemorySettingsInterface::SetKeyValueList(const char* section, const std::vector<std::pair<std::string, std::string>>& items)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
sit->second.clear();
|
||||
for (const auto& [key, value] : items)
|
||||
sit->second.emplace(key, value);
|
||||
@@ -186,11 +186,11 @@ void MemorySettingsInterface::SetKeyValueList(const char* section, const std::ve
|
||||
|
||||
void MemorySettingsInterface::SetValue(const char* section, const char* key, std::string value)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
||||
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
if (range.first == sit->second.end())
|
||||
{
|
||||
sit->second.emplace(std::string(key), std::move(value));
|
||||
@@ -213,10 +213,10 @@ std::vector<std::string> MemorySettingsInterface::GetStringList(const char* sect
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit != m_sections.end())
|
||||
{
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
for (auto iter = range.first; iter != range.second; ++iter)
|
||||
ret.emplace_back(iter->second);
|
||||
}
|
||||
@@ -226,11 +226,11 @@ std::vector<std::string> MemorySettingsInterface::GetStringList(const char* sect
|
||||
|
||||
void MemorySettingsInterface::SetStringList(const char* section, const char* key, const std::vector<std::string>& items)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
||||
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
for (auto iter = range.first; iter != range.second;)
|
||||
sit->second.erase(iter++);
|
||||
|
||||
@@ -241,11 +241,11 @@ void MemorySettingsInterface::SetStringList(const char* section, const char* key
|
||||
|
||||
bool MemorySettingsInterface::RemoveFromStringList(const char* section, const char* key, const char* item)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
||||
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
bool result = false;
|
||||
for (auto iter = range.first; iter != range.second;)
|
||||
{
|
||||
@@ -265,11 +265,11 @@ bool MemorySettingsInterface::RemoveFromStringList(const char* section, const ch
|
||||
|
||||
bool MemorySettingsInterface::AddToStringList(const char* section, const char* key, const char* item)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
sit = m_sections.emplace(std::make_pair(std::string(section), KeyMap())).first;
|
||||
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
for (auto iter = range.first; iter != range.second; ++iter)
|
||||
{
|
||||
if (iter->second == item)
|
||||
@@ -282,7 +282,7 @@ bool MemorySettingsInterface::AddToStringList(const char* section, const char* k
|
||||
|
||||
bool MemorySettingsInterface::ContainsValue(const char* section, const char* key) const
|
||||
{
|
||||
const auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
const auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return false;
|
||||
|
||||
@@ -291,18 +291,18 @@ bool MemorySettingsInterface::ContainsValue(const char* section, const char* key
|
||||
|
||||
void MemorySettingsInterface::DeleteValue(const char* section, const char* key)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return;
|
||||
|
||||
const auto range = UnorderedStringMultiMapEqualRange(sit->second, key);
|
||||
const auto range = sit->second.equal_range(key);
|
||||
for (auto iter = range.first; iter != range.second;)
|
||||
sit->second.erase(iter++);
|
||||
}
|
||||
|
||||
void MemorySettingsInterface::ClearSection(const char* section)
|
||||
{
|
||||
auto sit = UnorderedStringMapFind(m_sections, section);
|
||||
auto sit = m_sections.find(section);
|
||||
if (sit == m_sections.end())
|
||||
return;
|
||||
|
||||
|
||||
+3
-4
@@ -81,10 +81,9 @@
|
||||
|
||||
// Defines the memory page size for the target platform at compilation. All supported platforms
|
||||
// (which means Intel only right now) have a 4k granularity.
|
||||
#define PCSX2_PAGESIZE 0x1000
|
||||
static constexpr int __pagesize = PCSX2_PAGESIZE;
|
||||
static constexpr int __pageshift = 12;
|
||||
static constexpr size_t __pagemask = PCSX2_PAGESIZE - 1;
|
||||
static constexpr unsigned int __pagesize = 0x1000;
|
||||
static constexpr unsigned int __pageshift = 12;
|
||||
static constexpr unsigned int __pagemask = __pagesize - 1;
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// Microsoft Visual Studio
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#pragma once
|
||||
#include "Pcsx2Types.h"
|
||||
#include <algorithm>
|
||||
#include <charconv>
|
||||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
@@ -340,4 +341,15 @@ namespace StringUtil
|
||||
/// Converts unsigned 128-bit data to string.
|
||||
std::string U128ToString(const u128& u);
|
||||
std::string& AppendU128ToString(const u128& u, std::string& s);
|
||||
|
||||
template <typename ContainerType>
|
||||
static inline bool ContainsSubString(const ContainerType& haystack, const std::string_view& needle)
|
||||
{
|
||||
using ValueType = typename ContainerType::value_type;
|
||||
if (needle.empty())
|
||||
return std::empty(haystack);
|
||||
|
||||
return std::search(std::begin(haystack), std::end(haystack), reinterpret_cast<const ValueType*>(needle.data()),
|
||||
reinterpret_cast<const ValueType*>(needle.data() + needle.length())) != std::end(haystack);
|
||||
}
|
||||
} // namespace StringUtil
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,199 @@
|
||||
// See TextureDecompress.cpp for license info.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4201) // nonstandard extension used: nameless struct/union
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
enum BC4Mode
|
||||
{
|
||||
BC4_UNORM = 0,
|
||||
BC4_SNORM = 1
|
||||
};
|
||||
|
||||
enum BC5Mode
|
||||
{
|
||||
BC5_UNORM = 0,
|
||||
BC5_SNORM = 1
|
||||
};
|
||||
|
||||
void DecompressBlockBC1(uint32_t x, uint32_t y, uint32_t stride,
|
||||
const uint8_t* blockStorage, unsigned char* image);
|
||||
void DecompressBlockBC2(uint32_t x, uint32_t y, uint32_t stride,
|
||||
const uint8_t* blockStorage, unsigned char* image);
|
||||
void DecompressBlockBC3(uint32_t x, uint32_t y, uint32_t stride,
|
||||
const uint8_t* blockStorage, unsigned char* image);
|
||||
void DecompressBlockBC4(uint32_t x, uint32_t y, uint32_t stride,
|
||||
enum BC4Mode mode, const uint8_t* blockStorage, unsigned char* image);
|
||||
void DecompressBlockBC5(uint32_t x, uint32_t y, uint32_t stride,
|
||||
enum BC5Mode mode, const uint8_t* blockStorage, unsigned char* image);
|
||||
|
||||
namespace bc7decomp
|
||||
{
|
||||
|
||||
enum eNoClamp { cNoClamp };
|
||||
|
||||
template <typename S> inline S clamp(S value, S low, S high) { return (value < low) ? low : ((value > high) ? high : value); }
|
||||
|
||||
class color_rgba
|
||||
{
|
||||
public:
|
||||
union
|
||||
{
|
||||
uint8_t m_comps[4];
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t r;
|
||||
uint8_t g;
|
||||
uint8_t b;
|
||||
uint8_t a;
|
||||
};
|
||||
};
|
||||
|
||||
inline color_rgba()
|
||||
{
|
||||
static_assert(sizeof(*this) == 4, "sizeof(*this) != 4");
|
||||
}
|
||||
|
||||
inline color_rgba(int y)
|
||||
{
|
||||
set(y);
|
||||
}
|
||||
|
||||
inline color_rgba(int y, int na)
|
||||
{
|
||||
set(y, na);
|
||||
}
|
||||
|
||||
inline color_rgba(int sr, int sg, int sb, int sa)
|
||||
{
|
||||
set(sr, sg, sb, sa);
|
||||
}
|
||||
|
||||
inline color_rgba(eNoClamp, int sr, int sg, int sb, int sa)
|
||||
{
|
||||
set_noclamp_rgba((uint8_t)sr, (uint8_t)sg, (uint8_t)sb, (uint8_t)sa);
|
||||
}
|
||||
|
||||
inline color_rgba& set_noclamp_y(int y)
|
||||
{
|
||||
m_comps[0] = (uint8_t)y;
|
||||
m_comps[1] = (uint8_t)y;
|
||||
m_comps[2] = (uint8_t)y;
|
||||
m_comps[3] = (uint8_t)255;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline color_rgba &set_noclamp_rgba(int sr, int sg, int sb, int sa)
|
||||
{
|
||||
m_comps[0] = (uint8_t)sr;
|
||||
m_comps[1] = (uint8_t)sg;
|
||||
m_comps[2] = (uint8_t)sb;
|
||||
m_comps[3] = (uint8_t)sa;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline color_rgba &set(int y)
|
||||
{
|
||||
m_comps[0] = static_cast<uint8_t>(clamp<int>(y, 0, 255));
|
||||
m_comps[1] = m_comps[0];
|
||||
m_comps[2] = m_comps[0];
|
||||
m_comps[3] = 255;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline color_rgba &set(int y, int na)
|
||||
{
|
||||
m_comps[0] = static_cast<uint8_t>(clamp<int>(y, 0, 255));
|
||||
m_comps[1] = m_comps[0];
|
||||
m_comps[2] = m_comps[0];
|
||||
m_comps[3] = static_cast<uint8_t>(clamp<int>(na, 0, 255));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline color_rgba &set(int sr, int sg, int sb, int sa)
|
||||
{
|
||||
m_comps[0] = static_cast<uint8_t>(clamp<int>(sr, 0, 255));
|
||||
m_comps[1] = static_cast<uint8_t>(clamp<int>(sg, 0, 255));
|
||||
m_comps[2] = static_cast<uint8_t>(clamp<int>(sb, 0, 255));
|
||||
m_comps[3] = static_cast<uint8_t>(clamp<int>(sa, 0, 255));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline color_rgba &set_rgb(int sr, int sg, int sb)
|
||||
{
|
||||
m_comps[0] = static_cast<uint8_t>(clamp<int>(sr, 0, 255));
|
||||
m_comps[1] = static_cast<uint8_t>(clamp<int>(sg, 0, 255));
|
||||
m_comps[2] = static_cast<uint8_t>(clamp<int>(sb, 0, 255));
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline color_rgba &set_rgb(const color_rgba &other)
|
||||
{
|
||||
r = other.r;
|
||||
g = other.g;
|
||||
b = other.b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const uint8_t &operator[] (uint32_t index) const { assert(index < 4); return m_comps[index]; }
|
||||
inline uint8_t &operator[] (uint32_t index) { assert(index < 4); return m_comps[index]; }
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
m_comps[0] = 0;
|
||||
m_comps[1] = 0;
|
||||
m_comps[2] = 0;
|
||||
m_comps[3] = 0;
|
||||
}
|
||||
|
||||
inline bool operator== (const color_rgba &rhs) const
|
||||
{
|
||||
if (m_comps[0] != rhs.m_comps[0]) return false;
|
||||
if (m_comps[1] != rhs.m_comps[1]) return false;
|
||||
if (m_comps[2] != rhs.m_comps[2]) return false;
|
||||
if (m_comps[3] != rhs.m_comps[3]) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool operator!= (const color_rgba &rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
inline bool operator<(const color_rgba &rhs) const
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
if (m_comps[i] < rhs.m_comps[i])
|
||||
return true;
|
||||
else if (m_comps[i] != rhs.m_comps[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline int get_601_luma() const { return (19595U * m_comps[0] + 38470U * m_comps[1] + 7471U * m_comps[2] + 32768U) >> 16U; }
|
||||
inline int get_709_luma() const { return (13938U * m_comps[0] + 46869U * m_comps[1] + 4729U * m_comps[2] + 32768U) >> 16U; }
|
||||
inline int get_luma(bool luma_601) const { return luma_601 ? get_601_luma() : get_709_luma(); }
|
||||
|
||||
static color_rgba comp_min(const color_rgba& a, const color_rgba& b) { return color_rgba(std::min(a[0], b[0]), std::min(a[1], b[1]), std::min(a[2], b[2]), std::min(a[3], b[3])); }
|
||||
static color_rgba comp_max(const color_rgba& a, const color_rgba& b) { return color_rgba(std::max(a[0], b[0]), std::max(a[1], b[1]), std::max(a[2], b[2]), std::max(a[3], b[3])); }
|
||||
};
|
||||
|
||||
bool unpack_bc7(const void *pBlock, color_rgba *pPixels);
|
||||
|
||||
} // namespace bc7decomp
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include "common/Align.h"
|
||||
#include "common/BitUtils.h"
|
||||
#include "common/RedtapeWindows.h"
|
||||
#include "common/Console.h"
|
||||
#include "common/General.h"
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
<ClCompile Include="StackWalker.cpp" />
|
||||
<ClCompile Include="StringUtil.cpp" />
|
||||
<ClCompile Include="SettingsWrapper.cpp" />
|
||||
<ClCompile Include="TextureDecompress.cpp" />
|
||||
<ClCompile Include="Timer.cpp" />
|
||||
<ClCompile Include="WAVWriter.cpp" />
|
||||
<ClCompile Include="WindowInfo.cpp" />
|
||||
@@ -102,9 +103,8 @@
|
||||
<MASM Include="FastJmp.asm" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Align.h" />
|
||||
<ClInclude Include="BitUtils.h" />
|
||||
<ClInclude Include="AlignedMalloc.h" />
|
||||
<ClInclude Include="BitCast.h" />
|
||||
<ClInclude Include="ByteSwap.h" />
|
||||
<ClInclude Include="CrashHandler.h" />
|
||||
<ClInclude Include="DynamicLibrary.h" />
|
||||
@@ -134,13 +134,13 @@
|
||||
<ClInclude Include="Assertions.h" />
|
||||
<ClInclude Include="Console.h" />
|
||||
<ClInclude Include="General.h" />
|
||||
<ClInclude Include="MathUtils.h" />
|
||||
<ClInclude Include="Path.h" />
|
||||
<ClInclude Include="PrecompiledHeader.h" />
|
||||
<ClInclude Include="ReadbackSpinManager.h" />
|
||||
<ClInclude Include="RedtapeWindows.h" />
|
||||
<ClInclude Include="SafeArray.h" />
|
||||
<ClInclude Include="ThreadPool.h" />
|
||||
<ClInclude Include="TextureDecompress.h" />
|
||||
<ClInclude Include="Timer.h" />
|
||||
<ClInclude Include="WAVWriter.h" />
|
||||
<ClInclude Include="WindowInfo.h" />
|
||||
|
||||
@@ -142,6 +142,9 @@
|
||||
<ClCompile Include="Assertions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TextureDecompress.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AlignedMalloc.h">
|
||||
@@ -198,9 +201,6 @@
|
||||
<ClInclude Include="emitter\legacy_types.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MathUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Path.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -267,15 +267,12 @@
|
||||
<ClInclude Include="SettingsWrapper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Align.h">
|
||||
<ClInclude Include="BitUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WindowInfo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BitCast.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StringUtil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -354,6 +351,9 @@
|
||||
<ClInclude Include="Error.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TextureDecompress.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<CompileAs>Default</CompileAs>
|
||||
<DisableSpecificWarnings>4063;4100;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<LanguageStandard>stdcpp20</LanguageStandard>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
pull_request_title: "[ci skip] Syncing Crowdin translations"
|
||||
pull_request_title: "translations: Syncing Crowdin translations"
|
||||
commit_message: "[ci skip]"
|
||||
files:
|
||||
- source: pcsx2-qt/Translations/pcsx2-qt_en.ts
|
||||
|
||||
+70
-1
@@ -13,6 +13,7 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
#include <cstdlib>
|
||||
@@ -39,6 +40,7 @@
|
||||
#include "pcsx2/Achievements.h"
|
||||
#include "pcsx2/CDVD/CDVD.h"
|
||||
#include "pcsx2/GS.h"
|
||||
#include "pcsx2/GS/GSPerfMon.h"
|
||||
#include "pcsx2/GSDumpReplayer.h"
|
||||
#include "pcsx2/Host.h"
|
||||
#include "pcsx2/INISettingsInterface.h"
|
||||
@@ -57,6 +59,7 @@ namespace GSRunner
|
||||
static void InitializeConsole();
|
||||
static bool InitializeConfig();
|
||||
static bool ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& params);
|
||||
static void DumpStats();
|
||||
|
||||
static bool CreatePlatformWindow();
|
||||
static void DestroyPlatformWindow();
|
||||
@@ -77,6 +80,19 @@ static bool s_no_console = 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_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 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 u32 s_total_frames = 0;
|
||||
|
||||
bool GSRunner::InitializeConfig()
|
||||
{
|
||||
@@ -241,7 +257,7 @@ void Host::OnInputDeviceDisconnected(const std::string_view& identifier)
|
||||
{
|
||||
}
|
||||
|
||||
void Host::SetRelativeMouseMode(bool enabled)
|
||||
void Host::SetMouseMode(bool relative_mode, bool hide_cursor)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -265,6 +281,24 @@ void Host::BeginPresentFrame()
|
||||
std::string dump_path(fmt::format("{}_frame{}.png", s_output_prefix, s_dump_frame_number));
|
||||
GSQueueSnapshot(dump_path);
|
||||
}
|
||||
|
||||
if (GSConfig.UseHardwareRenderer())
|
||||
{
|
||||
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::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);
|
||||
s_total_frames++;
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
void Host::RequestResizeHostDisplay(s32 width, s32 height)
|
||||
@@ -601,6 +635,24 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSRunner::DumpStats()
|
||||
{
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
Console.WriteLn(fmt::format("======= HW STATISTICS FOR {} FRAMES ========", s_total_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_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_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Barriers: {} (avg {})", s_total_barriers, static_cast<u64>(std::ceil(s_total_barriers / static_cast<double>(s_total_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Copies: {} (avg {})", s_total_copies, static_cast<u64>(std::ceil(s_total_copies / static_cast<double>(s_total_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Uploads: {} (avg {})", s_total_uploads, static_cast<u64>(std::ceil(s_total_uploads / static_cast<double>(s_total_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Readbacks: {} (avg {})", s_total_readbacks, static_cast<u64>(std::ceil(s_total_readbacks / static_cast<double>(s_total_frames)))));
|
||||
Console.WriteLn("============================================");
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// We can't handle unicode in filenames if we don't use wmain on Win32.
|
||||
#define main real_main
|
||||
#endif
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
GSRunner::InitializeConsole();
|
||||
@@ -636,6 +688,7 @@ int main(int argc, char* argv[])
|
||||
while (VMManager::GetState() == VMState::Running)
|
||||
VMManager::Execute();
|
||||
VMManager::Shutdown(false);
|
||||
GSRunner::DumpStats();
|
||||
}
|
||||
|
||||
VMManager::Internal::CPUThreadShutdown();
|
||||
@@ -764,4 +817,20 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
return DefWindowProcW(hwnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
int wmain(int argc, wchar_t** argv)
|
||||
{
|
||||
std::vector<std::string> u8_args;
|
||||
u8_args.reserve(static_cast<size_t>(argc));
|
||||
for (int i = 0; i < argc; i++)
|
||||
u8_args.push_back(StringUtil::WideStringToUTF8String(argv[i]));
|
||||
|
||||
std::vector<char*> u8_argptrs;
|
||||
u8_argptrs.reserve(u8_args.size());
|
||||
for (int i = 0; i < argc; i++)
|
||||
u8_argptrs.push_back(u8_args[i].data());
|
||||
u8_argptrs.push_back(nullptr);
|
||||
|
||||
return real_main(argc, u8_argptrs.data());
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
z-index: 1;
|
||||
padding-top: 100px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
position: relative;
|
||||
margin: auto;
|
||||
padding: 0;
|
||||
width: 90%;
|
||||
max-width: 1200px;
|
||||
}
|
||||
|
||||
.close {
|
||||
color: white;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 25px;
|
||||
font-size: 35px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.close:hover,
|
||||
.close:focus {
|
||||
color: #999;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.prev,
|
||||
.next {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: auto;
|
||||
padding: 16px;
|
||||
margin-top: -50px;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
transition: 0.6s ease;
|
||||
border-radius: 0 3px 3px 0;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.next {
|
||||
right: 0;
|
||||
border-radius: 3px 0 0 3px;
|
||||
}
|
||||
|
||||
.prev:hover,
|
||||
.next:hover {
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
.item img {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#compareTitle {
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
font-family: sans-serif;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#compareCaption {
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#compareState {
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
color: red;
|
||||
font-family: sans-serif;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#compareImage {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/* Worst script known to man */
|
||||
/* Sources:
|
||||
https://www.w3schools.com/howto/howto_js_lightbox.asp
|
||||
https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/
|
||||
*/
|
||||
|
||||
function openModal() {
|
||||
document.body.style.position = 'fixed';
|
||||
document.body.style.top = `-${window.scrollY}px`;
|
||||
document.getElementById("myModal").style.display = "block";
|
||||
document.getElementById("myModal").focus();
|
||||
setImageIndex(0);
|
||||
}
|
||||
|
||||
function closeModal() {
|
||||
document.getElementById("myModal").style.display = "none";
|
||||
const scrollY = document.body.style.top;
|
||||
document.body.style.position = '';
|
||||
document.body.style.top = '';
|
||||
window.scrollTo(0, parseInt(scrollY || '0') * -1);
|
||||
}
|
||||
|
||||
function isModalOpen() {
|
||||
return (document.getElementById("myModal").style.display == "block");
|
||||
}
|
||||
|
||||
function formatLines(str) {
|
||||
let lines = str.split("\n")
|
||||
lines = lines.filter(line => !line.startsWith("Difference in frames"))
|
||||
return lines.join("<br>")
|
||||
}
|
||||
|
||||
function extractItem(elem) {
|
||||
return {
|
||||
name: elem.querySelector("h1").innerText,
|
||||
beforeImg: elem.querySelector(".before").getAttribute("src"),
|
||||
afterImg: elem.querySelector(".after").getAttribute("src"),
|
||||
details: formatLines(elem.querySelector("pre").innerText)
|
||||
};
|
||||
}
|
||||
|
||||
const items = [...document.querySelectorAll(".item")].map(extractItem)
|
||||
let currentImage = 0;
|
||||
let currentState = 0;
|
||||
|
||||
function getImageIndexForUri(uri) {
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (items[i].beforeImg == uri || items[i].afterImg == uri)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function setImageState(state) {
|
||||
const item = items[currentImage]
|
||||
const uri = (state === 0) ? item.beforeImg : item.afterImg;
|
||||
const stateText = (state === 0) ? "BEFORE" : "AFTER";
|
||||
const posText = "(" + (currentImage + 1).toString() + "/" + (items.length).toString() + ") ";
|
||||
document.getElementById("compareImage").setAttribute("src", uri);
|
||||
document.getElementById("compareState").innerText = stateText;
|
||||
document.getElementById("compareTitle").innerText = posText + item.name;
|
||||
document.getElementById("compareCaption").innerHTML = item.details;
|
||||
currentState = state;
|
||||
}
|
||||
|
||||
function setImageIndex(index) {
|
||||
if (index < 0 || index > items.length)
|
||||
return;
|
||||
|
||||
currentImage = index;
|
||||
setImageState(0);
|
||||
}
|
||||
|
||||
function handleKey(key) {
|
||||
if (key == " ") {
|
||||
setImageState((currentState === 0) ? 1 : 0);
|
||||
return true;
|
||||
} else if (key == "ArrowLeft") {
|
||||
setImageIndex(currentImage - 1);
|
||||
return true;
|
||||
} else if (key == "ArrowRight") {
|
||||
setImageIndex(currentImage + 1);
|
||||
return true;
|
||||
} else if (key == "Escape") {
|
||||
closeModal();
|
||||
return true;
|
||||
} else {
|
||||
console.log(key);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("myModal").addEventListener("keydown", function(ev) {
|
||||
if (ev.defaultPrevented)
|
||||
return;
|
||||
|
||||
if (handleKey(ev.key))
|
||||
ev.preventDefault();
|
||||
});
|
||||
|
||||
document.querySelector("#myModal .prev").addEventListener("click", function() {
|
||||
setImageIndex(currentImage - 1);
|
||||
});
|
||||
document.querySelector("#myModal .next").addEventListener("click", function() {
|
||||
setImageIndex(currentImage + 1);
|
||||
});
|
||||
document.querySelectorAll(".item img").forEach(elem => elem.addEventListener("click", function() {
|
||||
if (!isModalOpen())
|
||||
openModal();
|
||||
setImageIndex(getImageIndexForUri(this.getAttribute("src")));
|
||||
}));
|
||||
@@ -7,17 +7,35 @@ import hashlib
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
MAX_DIFF_FRAMES = 9999
|
||||
|
||||
SCRIPTDIR = os.path.abspath(os.path.dirname(__file__))
|
||||
CSS_PATH = Path(os.path.join(SCRIPTDIR, "comparer.css")).as_uri()
|
||||
JS_PATH = Path(os.path.join(SCRIPTDIR, "comparer.js")).as_uri()
|
||||
|
||||
FILE_HEADER = """
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Comparison</title>
|
||||
""" + f"<link rel=\"stylesheet\" href=\"{CSS_PATH}\" />" + """
|
||||
</head>
|
||||
<body>
|
||||
"""
|
||||
|
||||
FILE_FOOTER = """
|
||||
<div id="myModal" class="modal" tabindex="0">
|
||||
<span class="close cursor" onclick="closeModal()">×</span>
|
||||
<div class="modal-content">
|
||||
<div id="compareTitle"></div>
|
||||
<img id="compareImage" />
|
||||
<div id="compareState"></div>
|
||||
<a class="prev">❮</a>
|
||||
<a class="next">❯</a>
|
||||
<div id="compareCaption"></div>
|
||||
</div>
|
||||
</div>
|
||||
""" + f"<script src=\"{JS_PATH}\"></script>\n" + """
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
@@ -39,6 +57,36 @@ def compare_frames(path1, path2):
|
||||
return False
|
||||
|
||||
|
||||
def extract_stats(file):
|
||||
stats = {}
|
||||
try:
|
||||
with open(file, "r") as f:
|
||||
for line in f.readlines():
|
||||
m = re.match(".*@HWSTAT@ ([^:]+): (.*) \(avg ([^)]+)\)$", line)
|
||||
if m is None:
|
||||
continue
|
||||
stats[m[1]] = int(m[3])
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
except IOError:
|
||||
pass
|
||||
return stats
|
||||
|
||||
|
||||
def compare_stats(baselinedir, testdir):
|
||||
stats1 = extract_stats(os.path.join(baselinedir, "emulog.txt"))
|
||||
stats2 = extract_stats(os.path.join(testdir, "emulog.txt"))
|
||||
res = []
|
||||
for statname in stats1.keys():
|
||||
if statname not in stats2 or stats1[statname] == stats2[statname]:
|
||||
continue
|
||||
v2 = stats2[statname]
|
||||
v1 = stats1[statname]
|
||||
delta = v2 - v1
|
||||
res.append("%s: %s%d [%d=>%d]" % (statname, "+" if delta > 0 else "", delta, v1, v2))
|
||||
return res
|
||||
|
||||
|
||||
def check_regression_test(baselinedir, testdir, name):
|
||||
#print("Checking '%s'..." % name)
|
||||
|
||||
@@ -51,6 +99,7 @@ def check_regression_test(baselinedir, testdir, name):
|
||||
images = glob.glob(os.path.join(dir1, "*_frame*.png"))
|
||||
diff_frames = []
|
||||
first_fail = True
|
||||
stats = compare_stats(dir1, dir2)
|
||||
|
||||
for imagepath in images:
|
||||
imagename = Path(imagepath).name
|
||||
@@ -72,6 +121,7 @@ def check_regression_test(baselinedir, testdir, name):
|
||||
diff_frames.append(framenum)
|
||||
|
||||
if first_fail:
|
||||
write("<div class=\"item\">")
|
||||
write("<h1>{}</h1>".format(name))
|
||||
write("<table width=\"100%\">")
|
||||
first_fail = False
|
||||
@@ -79,15 +129,24 @@ def check_regression_test(baselinedir, testdir, name):
|
||||
imguri1 = Path(path1).as_uri()
|
||||
imguri2 = Path(path2).as_uri()
|
||||
write("<tr><td colspan=\"2\">Frame %d</td></tr>" % (framenum))
|
||||
write("<tr><td><img src=\"%s\" /></td><td><img src=\"%s\" /></td></tr>" % (imguri1, imguri2))
|
||||
write("<tr><td><img class=\"before\" src=\"%s\" /></td><td><img class=\"after\" src=\"%s\" /></td></tr>" % (imguri1, imguri2))
|
||||
|
||||
if len(diff_frames) == MAX_DIFF_FRAMES:
|
||||
break
|
||||
|
||||
if len(diff_frames) > 0:
|
||||
write("</table>")
|
||||
write("<pre>Difference in frames [%s] for %s</pre>" % (",".join(map(str, diff_frames)), name))
|
||||
write("<pre>Difference in frames [%s] for %s%s%s</pre>" % (",".join(map(str, diff_frames)), name, "\n" if len(stats) > 0 else "", "\n".join(stats)))
|
||||
write("</div>")
|
||||
print("*** Difference in frames [%s] for %s" % (",".join(map(str, diff_frames)), name))
|
||||
return False
|
||||
if len(stats) > 0:
|
||||
print(stats)
|
||||
elif len(stats) > 0:
|
||||
write("<h1>{}</h1>".format(name))
|
||||
write("<pre>%s</pre>" % "\n".join(stats))
|
||||
print(name, stats)
|
||||
|
||||
return True
|
||||
return len(diff_frames) == 0
|
||||
|
||||
|
||||
def check_regression_tests(baselinedir, testdir):
|
||||
@@ -103,6 +162,8 @@ def check_regression_tests(baselinedir, testdir):
|
||||
else:
|
||||
failure += 1
|
||||
|
||||
print("%d dumps unchanged" % success)
|
||||
print("%d dumps changed" % failure)
|
||||
return (failure == 0)
|
||||
|
||||
|
||||
@@ -110,9 +171,11 @@ if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(description="Check frame dump images for regression tests")
|
||||
parser.add_argument("-baselinedir", action="store", required=True, help="Directory containing baseline frames to check against")
|
||||
parser.add_argument("-testdir", action="store", required=True, help="Directory containing frames to check")
|
||||
parser.add_argument("-maxframes", type=int, action="store", required=False, default=9999, help="Max frames to compare")
|
||||
parser.add_argument("outfile", action="store", help="The file to write the output to")
|
||||
|
||||
args = parser.parse_args()
|
||||
MAX_DIFF_FRAMES = args.maxframes
|
||||
|
||||
outfile = open(args.outfile, "w")
|
||||
write(FILE_HEADER)
|
||||
|
||||
@@ -24,6 +24,8 @@ def run_regression_test(runner, dumpdir, renderer, upscale, renderhacks, paralle
|
||||
real_dumpdir = os.path.join(dumpdir, gsname).strip()
|
||||
if not os.path.exists(real_dumpdir):
|
||||
os.mkdir(real_dumpdir)
|
||||
else:
|
||||
return
|
||||
|
||||
if renderer is not None:
|
||||
args.extend(["-renderer", renderer])
|
||||
|
||||
@@ -224,7 +224,6 @@ void AutoUpdaterDialog::getLatestReleaseComplete(QNetworkReply* reply)
|
||||
bool is_symbols = false;
|
||||
bool is_avx2 = false;
|
||||
bool is_sse4 = false;
|
||||
bool is_qt_asset = false;
|
||||
bool is_perfect_match = false;
|
||||
for (const QJsonValue& additional_tag : additional_tags_array)
|
||||
{
|
||||
@@ -235,12 +234,6 @@ void AutoUpdaterDialog::getLatestReleaseComplete(QNetworkReply* reply)
|
||||
is_symbols = true;
|
||||
break;
|
||||
}
|
||||
else if (additional_tag_str.startsWith(QStringLiteral("Qt")))
|
||||
{
|
||||
// found a qt build
|
||||
// Note: The website improperly parses macOS file names, and gives them the tag "Qt.tar" instead of "Qt"
|
||||
is_qt_asset = true;
|
||||
}
|
||||
else if (additional_tag_str == QStringLiteral("SSE4"))
|
||||
{
|
||||
is_sse4 = true;
|
||||
@@ -258,7 +251,7 @@ void AutoUpdaterDialog::getLatestReleaseComplete(QNetworkReply* reply)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!is_qt_asset || is_symbols || (!x86caps.hasAVX2 && is_avx2))
|
||||
if (is_symbols || (!x86caps.hasAVX2 && is_avx2))
|
||||
{
|
||||
// skip this asset
|
||||
continue;
|
||||
@@ -387,6 +380,8 @@ void AutoUpdaterDialog::getChangesComplete(QNetworkReply* reply)
|
||||
changes_html.prepend(tr("<h2>Save State Warning</h2><p>Installing this update will make your save states "
|
||||
"<b>incompatible</b>. Please ensure you have saved your games to a Memory Card "
|
||||
"before installing this update or you will lose progress.</p>"));
|
||||
|
||||
m_update_will_break_save_states = true;
|
||||
}
|
||||
|
||||
if (update_increases_settings_version)
|
||||
@@ -414,6 +409,23 @@ void AutoUpdaterDialog::getChangesComplete(QNetworkReply* reply)
|
||||
|
||||
void AutoUpdaterDialog::downloadUpdateClicked()
|
||||
{
|
||||
if (m_update_will_break_save_states)
|
||||
{
|
||||
QMessageBox msgbox;
|
||||
msgbox.setIcon(QMessageBox::Critical);
|
||||
msgbox.setWindowTitle(tr("Savestate Warning"));
|
||||
msgbox.setText(tr("<h1>WARNING</h1><p style='font-size:12pt;'>Installing this update will make your <b>save states incompatible</b>.</p><p>Do you wish to continue?</p>"));
|
||||
msgbox.addButton(QMessageBox::Yes);
|
||||
msgbox.addButton(QMessageBox::No);
|
||||
msgbox.setDefaultButton(QMessageBox::No);
|
||||
// This makes the box wider, for some reason sizing boxes in Qt is hard - Source: The internet.
|
||||
QSpacerItem* horizontalSpacer = new QSpacerItem(500, 0, QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
QGridLayout* layout = (QGridLayout*)msgbox.layout();
|
||||
layout->addItem(horizontalSpacer, layout->rowCount(), 0, 1, layout->columnCount());
|
||||
if (msgbox.exec() != QMessageBox::Yes)
|
||||
return;
|
||||
}
|
||||
|
||||
m_display_messages = true;
|
||||
QUrl url(m_download_url);
|
||||
QNetworkRequest request(url);
|
||||
|
||||
+19
-2
@@ -55,6 +55,7 @@ target_sources(pcsx2-qt PRIVATE
|
||||
Settings/BIOSSettingsWidget.ui
|
||||
Settings/ControllerBindingWidget.ui
|
||||
Settings/ControllerBindingWidget_DualShock2.ui
|
||||
Settings/ControllerBindingWidget_Guitar.ui
|
||||
Settings/ControllerBindingWidgets.cpp
|
||||
Settings/ControllerBindingWidgets.h
|
||||
Settings/ControllerLEDSettingsDialog.ui
|
||||
@@ -133,6 +134,7 @@ target_sources(pcsx2-qt PRIVATE
|
||||
Settings/SettingsDialog.ui
|
||||
Settings/USBBindingWidget_DrivingForce.ui
|
||||
Settings/USBBindingWidget_GTForce.ui
|
||||
Settings/USBBindingWidget_GunCon2.ui
|
||||
Debugger/CpuWidget.cpp
|
||||
Debugger/CpuWidget.h
|
||||
Debugger/CpuWidget.ui
|
||||
@@ -204,8 +206,23 @@ if(WIN32)
|
||||
set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION "${CMAKE_SOURCE_DIR}/bin/translations")
|
||||
qt_add_lrelease(pcsx2-qt TS_FILES ${TS_FILES})
|
||||
elseif(APPLE)
|
||||
# Hopefully macdeployqt will pick these up.
|
||||
qt_add_lrelease(pcsx2-qt TS_FILES ${TS_FILES})
|
||||
qt_add_lrelease(pcsx2-qt TS_FILES ${TS_FILES} QM_FILES_OUTPUT_VARIABLE QM_FILES)
|
||||
set(PCSX2_MACOS_LOCALIZATIONS)
|
||||
foreach (TS_FILE IN LISTS TS_FILES)
|
||||
get_filename_component(TS_FILE_NAME ${TS_FILE} NAME)
|
||||
set(regex "^pcsx2-qt_([a-zA-Z0-9\\-]+)\\.ts$")
|
||||
if (TS_FILE_NAME MATCHES ${regex})
|
||||
string(REGEX REPLACE ${regex} "\\1" language ${TS_FILE_NAME})
|
||||
string(REPLACE "-" "_" language ${language})
|
||||
set(PCSX2_MACOS_LOCALIZATIONS "${PCSX2_MACOS_LOCALIZATIONS}\n\t\t<string>${language}</string>")
|
||||
else()
|
||||
message(WARNING "Unrecognized ts file ${TS_FILE_NAME}")
|
||||
endif()
|
||||
endforeach()
|
||||
foreach (QM_FILE IN LISTS QM_FILES)
|
||||
target_sources(pcsx2-qt PRIVATE ${QM_FILE})
|
||||
set_source_files_properties(${QM_FILE} PROPERTIES MACOSX_PACKAGE_LOCATION Resources/translations/)
|
||||
endforeach()
|
||||
else()
|
||||
# TODO: Copy base translations.
|
||||
qt_add_lrelease(pcsx2-qt TS_FILES ${TS_FILES} QM_FILES_OUTPUT_VARIABLE QM_FILES)
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "DebugTools/Breakpoints.h"
|
||||
#include "DebugTools/BiosDebugData.h"
|
||||
#include "DebugTools/MipsStackWalk.h"
|
||||
#include "common/BitCast.h"
|
||||
|
||||
#include "QtUtils.h"
|
||||
#include <QtGui/QClipboard>
|
||||
@@ -539,7 +538,7 @@ static std::vector<u32> searchWorker(DebugInterface* cpu, u32 start, u32 end, T
|
||||
{
|
||||
const float fTop = value + 0.00001f;
|
||||
const float fBottom = value - 0.00001f;
|
||||
const float memValue = bit_cast<float, u32>(cpu->read32(addr));
|
||||
const float memValue = std::bit_cast<float, u32>(cpu->read32(addr));
|
||||
if (fBottom < memValue && memValue < fTop)
|
||||
{
|
||||
hitAddresses.emplace_back(addr);
|
||||
@@ -556,7 +555,7 @@ static std::vector<u32> searchWorker(DebugInterface* cpu, u32 start, u32 end, T
|
||||
{
|
||||
const double dTop = value + 0.00001f;
|
||||
const double dBottom = value - 0.00001f;
|
||||
const double memValue = bit_cast<double, u64>(cpu->read64(addr));
|
||||
const double memValue = std::bit_cast<double, u64>(cpu->read64(addr));
|
||||
if (dBottom < memValue && memValue < dTop)
|
||||
{
|
||||
hitAddresses.emplace_back(addr);
|
||||
@@ -582,15 +581,15 @@ static std::vector<u32> searchWorker(DebugInterface* cpu, u32 start, u32 end, T
|
||||
return hitAddresses;
|
||||
}
|
||||
|
||||
static std::vector<u32> searchWorkerString(DebugInterface* cpu, u32 start, u32 end, std::string value)
|
||||
static std::vector<u32> searchWorkerByteArray(DebugInterface* cpu, u32 start, u32 end, QByteArray value)
|
||||
{
|
||||
std::vector<u32> hitAddresses;
|
||||
for (u32 addr = start; addr < end; addr += 1)
|
||||
{
|
||||
bool hit = true;
|
||||
for (size_t i = 0; i < value.length(); i++)
|
||||
for (qsizetype i = 0; i < value.length(); i++)
|
||||
{
|
||||
if (static_cast<char>(cpu->read8(addr + i)) != value[i])
|
||||
if (cpu->read8(addr + i) != value[i])
|
||||
{
|
||||
hit = false;
|
||||
break;
|
||||
@@ -624,7 +623,9 @@ std::vector<u32> startWorker(DebugInterface* cpu, int type, u32 start, u32 end,
|
||||
case 5:
|
||||
return searchWorker<double>(cpu, start, end, value.toDouble());
|
||||
case 6:
|
||||
return searchWorkerString(cpu, start, end, value.toStdString());
|
||||
return searchWorkerByteArray(cpu, start, end, value.toUtf8());
|
||||
case 7:
|
||||
return searchWorkerByteArray(cpu, start, end, QByteArray::fromHex(value.toUtf8()));
|
||||
default:
|
||||
Console.Error("Debugger: Unknown type when doing memory search!");
|
||||
break;
|
||||
@@ -667,13 +668,24 @@ void CpuWidget::onSearchButtonClicked()
|
||||
|
||||
unsigned long long value;
|
||||
|
||||
if (searchType < 4)
|
||||
switch (searchType)
|
||||
{
|
||||
value = searchValue.toULongLong(&ok, searchHex ? 16 : 10);
|
||||
}
|
||||
else if (searchType != 6)
|
||||
{
|
||||
searchValue.toDouble(&ok);
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
value = searchValue.toULongLong(&ok, searchHex ? 16 : 10);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
searchValue.toDouble(&ok);
|
||||
break;
|
||||
case 6:
|
||||
ok = !searchValue.isEmpty();
|
||||
break;
|
||||
case 7:
|
||||
ok = !searchValue.trimmed().isEmpty();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
@@ -684,6 +696,7 @@ void CpuWidget::onSearchButtonClicked()
|
||||
|
||||
switch (searchType)
|
||||
{
|
||||
case 7:
|
||||
case 6:
|
||||
case 5:
|
||||
case 4:
|
||||
|
||||
@@ -231,6 +231,11 @@
|
||||
<string>String</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Array of byte</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user