mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-11 09:44:17 +02:00
Compare commits
101 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| faf6c04dee | |||
| 6aadbc18a9 | |||
| 2be34a6938 | |||
| daa0d2d3c4 | |||
| 1b4af9deef | |||
| db6cb43336 | |||
| 012d352fa7 | |||
| 904096cd6e | |||
| b3bb67b43a | |||
| deba43640e | |||
| d665efdc3a | |||
| 66493c8dd1 | |||
| 9ff85a620e | |||
| ae1ee7cc3d | |||
| 2392cf7014 | |||
| 08fe525a3b | |||
| 1cd30601ed | |||
| 07713e97d7 | |||
| be307f3eb9 | |||
| d9bfdc3fcd | |||
| 064a96dfd2 | |||
| 428e035032 | |||
| 2db9cd0437 | |||
| bd78c33f11 | |||
| f16774357a | |||
| 00868a1b29 | |||
| 93212882d0 | |||
| 7f1ab4043c | |||
| 65822ecf86 | |||
| 9dff4f2005 | |||
| ec8f3b0414 | |||
| dde3c73af7 | |||
| bc80ea92a3 | |||
| 497dc14d11 | |||
| c80866ab5c | |||
| d856f3f5bd | |||
| 5d811f03f4 | |||
| 600a8b468b | |||
| e0c5e861be | |||
| d049c395fc | |||
| 6aed46c603 | |||
| f0723a6ec9 | |||
| bc624524cf | |||
| d1a44cdae8 | |||
| 8a46f9e6ca | |||
| eba66a2bb3 | |||
| 7ea5234049 | |||
| 0b5c37e1c5 | |||
| 2f7be602c8 | |||
| 05289e80a0 | |||
| 1ddc283ea2 | |||
| f969b0d4c7 | |||
| 1bd475cfab | |||
| f678788b6c | |||
| 379371f0b5 | |||
| 247511fd38 | |||
| 8de55a1937 | |||
| 73010de3b5 | |||
| b29496eb8e | |||
| dc88ed97ab | |||
| 10d2e5dd40 | |||
| f357fad0ff | |||
| 1ae55e8615 | |||
| 012120c344 | |||
| e3565eb924 | |||
| cd9fe1630b | |||
| f5524bab1b | |||
| 471a7203a5 | |||
| 456c062246 | |||
| 2c0bb98cac | |||
| bf4670c855 | |||
| 6113f9bcb4 | |||
| fe919d18b2 | |||
| d0687dd631 | |||
| 1bf53e6432 | |||
| 58a4f1e5e9 | |||
| ea304becf6 | |||
| b0a7d6994b | |||
| bd522e2385 | |||
| 27e9accffa | |||
| 4f41366600 | |||
| d26701c004 | |||
| d7983d81e3 | |||
| 2e122c3255 | |||
| eef1f837a2 | |||
| e52d8f70ba | |||
| d4cf5a998c | |||
| 608922dc41 | |||
| 438937ace3 | |||
| 50605bd0e9 | |||
| c1d46b1866 | |||
| e47b32b2e6 | |||
| f0dc40ac15 | |||
| 15a502cf36 | |||
| a1152f5313 | |||
| 68150c7448 | |||
| 71fe1b809c | |||
| ec6901b93d | |||
| 3c7eb2ac88 | |||
| baecf73f4b | |||
| 9a2561d9cf |
@@ -0,0 +1,21 @@
|
||||
name: 🧹 Clean Up Old Caches
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 0 * * *" # Every day at 12am UTC.
|
||||
workflow_dispatch: # As well as manually.
|
||||
|
||||
jobs:
|
||||
clean:
|
||||
name: "Clean Up Caches"
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
actions: write
|
||||
steps:
|
||||
- name: Clean Caches
|
||||
uses: PCSX2/cache-clean-action@v1.1.0
|
||||
with:
|
||||
items: '[{"key": " deps", "count": 4}, {"key": " ccache", "count": 1}, {"key": " flatpak", "count": 1}]'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: all
|
||||
on_failure: error
|
||||
@@ -27,10 +27,6 @@ on:
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
detail:
|
||||
required: false
|
||||
type: string
|
||||
default: ""
|
||||
patchesUrl:
|
||||
required: false
|
||||
type: string
|
||||
@@ -95,8 +91,8 @@ jobs:
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: .ccache
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} ${{ inputs.detail }} ccache ${{ steps.ccache_cache_timestamp.outputs.timestamp }}
|
||||
restore-keys: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} ${{ inputs.detail }} ccache
|
||||
key: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} ccache ${{ steps.ccache_cache_timestamp.outputs.timestamp }}
|
||||
restore-keys: ${{ inputs.os }} ${{ inputs.platform }} ${{ inputs.compiler }} ccache
|
||||
|
||||
- name: Install Packages
|
||||
run: |
|
||||
|
||||
@@ -62,11 +62,15 @@ jobs:
|
||||
echo "#define DEFAULT_UPDATER_CHANNEL \"stable\"" > ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
cat ./pcsx2-qt/DefaultUpdaterChannel.h
|
||||
|
||||
- name: Use Xcode 26.0.1
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.0.1.app
|
||||
- name: Use Xcode 26.2
|
||||
run: sudo xcode-select -s /Applications/Xcode_26.2.app
|
||||
|
||||
- name: Install Metal Toolchain
|
||||
run: xcodebuild -downloadComponent MetalToolchain
|
||||
run: |
|
||||
for i in {1..5}; do
|
||||
if xcrun metal -v; then break; fi
|
||||
xcodebuild -downloadComponent MetalToolchain
|
||||
done
|
||||
|
||||
- name: Prepare Artifact Metadata
|
||||
id: artifact-metadata
|
||||
|
||||
@@ -68,7 +68,7 @@ jobs:
|
||||
mv ./release-notes.md ${GITHUB_WORKSPACE}/release-notes.md
|
||||
|
||||
- name: Create a GitHub Release (Manual)
|
||||
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name == 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
tag_name: ${{ steps.tag_version.outputs.new_tag }}
|
||||
|
||||
- name: Create a GitHub Release (Push)
|
||||
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b
|
||||
uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe
|
||||
if: steps.tag_version.outputs.new_tag && github.event_name != 'workflow_dispatch'
|
||||
with:
|
||||
body_path: ./release-notes.md
|
||||
|
||||
@@ -1,16 +1,3 @@
|
||||
diff --git a/CHANGES b/CHANGES
|
||||
index 5d3dd16..587b612 100644
|
||||
--- a/CHANGES
|
||||
+++ b/CHANGES
|
||||
@@ -4,7 +4,7 @@ v2024.1
|
||||
- Update dependencies
|
||||
- Propagate test/install options to Glslang
|
||||
|
||||
-v2024.0
|
||||
+v2024.0 2024-03-09
|
||||
- Update dependencies
|
||||
- Utilities:
|
||||
- Use Python3 explicitly in utility scripts
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index ffcb54b..7c1a6d8 100644
|
||||
--- a/CMakeLists.txt
|
||||
|
||||
@@ -23,10 +23,10 @@ QTAPNG=1.3.0
|
||||
|
||||
FFMPEG=8.0
|
||||
FREETYPE=2.14.1
|
||||
HARFBUZZ=12.2.0
|
||||
HARFBUZZ=13.0.0
|
||||
LIBBACKTRACE=ad106d5fdd5d960bd33fae1c48a351af567fd075
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBPNG=1.6.53
|
||||
LIBJPEGTURBO=3.1.3
|
||||
LIBPNG=1.6.55
|
||||
LIBWEBP=1.6.0
|
||||
NVENC=13.0.19.0
|
||||
SDL=SDL3-3.4.2
|
||||
@@ -37,10 +37,10 @@ KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.2
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
SHADERC=2025.4
|
||||
SHADERC_GLSLANG=7a47e2531cb334982b2a2dd8513dca0a3de4373d
|
||||
SHADERC_SPIRVHEADERS=b824a462d4256d720bebb40e78b9eb8f78bbb305
|
||||
SHADERC_SPIRVTOOLS=971a7b6e8d7740035bbff089bbbf9f42951ecfd5
|
||||
SHADERC=2026.1
|
||||
SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
|
||||
SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
|
||||
SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
@@ -58,13 +58,13 @@ f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG
|
||||
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
|
||||
f63fc519f150465bd0bdafcdf3d0e9c23474f4c474171cd515ea1b3a72c081fb harfbuzz-$HARFBUZZ.tar.gz
|
||||
207f96964dc9475b13c1f66565bf145d2658089d65b4cf786d351da2857fc269 harfbuzz-$HARFBUZZ.tar.gz
|
||||
fd6f417fe9e3a071cf1424a5152d926a34c4a3c5070745470be6cf12a404ed79 $LIBBACKTRACE.zip
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
1d3fb8ccc2932d04aa3663e22ef5ef490244370f4e568d7850165068778d98d4 libpng-$LIBPNG.tar.xz
|
||||
075920b826834ac4ddf97661cc73491047855859affd671d52079c6867c1c6c0 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
d925722864837ad5ae2a82070d4b2e0603dc72af44bd457c3962298258b8e82d libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
ef39a2e3f9a8a78296c40da701967dd1b0d0d6e267e483863ce70f8a03b4050c $SDL.tar.gz
|
||||
452a1a290bd0cf18737fad0057dc17b7fdf10a73eda2d6d4f31ba04fda25ef2c libpng-$LIBPNG-apng.patch.gz
|
||||
017c06f75ffed25f6cda9b5369ec6da0ac35a6616adf7abe4222516a0237f37a libpng-$LIBPNG-apng.patch.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
13da39edb3a40ed9713ae390ca89faa2f1202c9dda869ef306a8d4383e242bee nv-codec-headers-$NVENC.tar.gz
|
||||
c465aa56757e7746ac707f582b6e2d51546569a4a2488c1172fb543aa5fdfc2c vulkan-sdk-$VULKAN.tar.gz
|
||||
@@ -73,10 +73,10 @@ eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar
|
||||
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
|
||||
8a89fb6612ace8954470aae004623374a8fc8b7a34a4277bee5527173b064faf shaderc-$SHADERC.tar.gz
|
||||
272d2725b140e09e85b96eecdc59c2e00c1a14cda2301767e1bf3c363a44b931 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
c693867f10a7760ef1bcf85419d51783586768cc2c601d03841bc6a8b2554b9c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
06b0a042f2e121e954badb4fd78c9e2d4bc7ed6087eceb26ab559c23cf94334f shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
245002feccbe7f8361b223545a5654cea69780745886872d7efff50a38d96c66 shaderc-$SHADERC.tar.gz
|
||||
bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
@@ -145,7 +145,7 @@ echo "Building libbacktrace..."
|
||||
rm -fr "libbacktrace-$LIBBACKTRACE"
|
||||
unzip "$LIBBACKTRACE.zip"
|
||||
cd "libbacktrace-$LIBBACKTRACE"
|
||||
./configure --prefix="$INSTALLDIR"
|
||||
./configure --prefix="$INSTALLDIR" --with-pic
|
||||
make
|
||||
make install
|
||||
cd ..
|
||||
|
||||
@@ -15,24 +15,24 @@
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/google/shaderc.git",
|
||||
"commit": "73743588fe9c39f2f1c780a087d94afac691a189"
|
||||
"commit": "301b4ede53d59b68bf55f95bb26412d9233c8187"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/KhronosGroup/glslang/archive/7a47e2531cb334982b2a2dd8513dca0a3de4373d.tar.gz",
|
||||
"sha256": "272d2725b140e09e85b96eecdc59c2e00c1a14cda2301767e1bf3c363a44b931",
|
||||
"url": "https://github.com/KhronosGroup/glslang/archive/f0bd0257c308b9a26562c1a30c4748a0219cc951.tar.gz",
|
||||
"sha256": "bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647",
|
||||
"dest": "third_party/glslang"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Headers/archive/b824a462d4256d720bebb40e78b9eb8f78bbb305.tar.gz",
|
||||
"sha256": "c693867f10a7760ef1bcf85419d51783586768cc2c601d03841bc6a8b2554b9c",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Headers/archive/04f10f650d514df88b76d25e83db360142c7b174.tar.gz",
|
||||
"sha256": "1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded",
|
||||
"dest": "third_party/spirv-headers"
|
||||
},
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Tools/archive/971a7b6e8d7740035bbff089bbbf9f42951ecfd5.tar.gz",
|
||||
"sha256": "06b0a042f2e121e954badb4fd78c9e2d4bc7ed6087eceb26ab559c23cf94334f",
|
||||
"url": "https://github.com/KhronosGroup/SPIRV-Tools/archive/fbe4f3ad913c44fe8700545f8ffe35d1382b7093.tar.gz",
|
||||
"sha256": "cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59",
|
||||
"dest": "third_party/spirv-tools"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -14,21 +14,21 @@
|
||||
"sources": [
|
||||
{
|
||||
"type": "archive",
|
||||
"url": "https://downloads.sourceforge.net/project/libpng/libpng16/1.6.53/libpng-1.6.53.tar.xz",
|
||||
"sha256": "1d3fb8ccc2932d04aa3663e22ef5ef490244370f4e568d7850165068778d98d4"
|
||||
"url": "https://downloads.sourceforge.net/project/libpng/libpng16/1.6.55/libpng-1.6.55.tar.xz",
|
||||
"sha256": "d925722864837ad5ae2a82070d4b2e0603dc72af44bd457c3962298258b8e82d"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"url": "https://download.sourceforge.net/libpng-apng/libpng-1.6.53-apng.patch.gz",
|
||||
"dest-filename": "libpng-1.6.53-apng.patch.gz",
|
||||
"sha256": "452a1a290bd0cf18737fad0057dc17b7fdf10a73eda2d6d4f31ba04fda25ef2c"
|
||||
"url": "https://download.sourceforge.net/libpng-apng/libpng-1.6.55-apng.patch.gz",
|
||||
"dest-filename": "libpng-1.6.55-apng.patch.gz",
|
||||
"sha256": "017c06f75ffed25f6cda9b5369ec6da0ac35a6616adf7abe4222516a0237f37a"
|
||||
},
|
||||
{
|
||||
"type": "shell",
|
||||
"commands":
|
||||
[
|
||||
"gunzip -f libpng-1.6.53-apng.patch.gz",
|
||||
"patch -p1 < \"libpng-1.6.53-apng.patch\""
|
||||
"gunzip -f libpng-1.6.55-apng.patch.gz",
|
||||
"patch -p1 < \"libpng-1.6.55-apng.patch\""
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
@@ -42,12 +42,12 @@ QT=6.10.1
|
||||
QTAPNG=1.3.0
|
||||
|
||||
FREETYPE=2.14.1
|
||||
HARFBUZZ=12.2.0
|
||||
HARFBUZZ=13.0.0
|
||||
SDL=SDL3-3.4.2
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.53
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBPNG=1.6.55
|
||||
LIBJPEGTURBO=3.1.3
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.0
|
||||
MOLTENVK=1.4.1
|
||||
@@ -55,10 +55,10 @@ KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.2
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
SHADERC=2025.4
|
||||
SHADERC_GLSLANG=7a47e2531cb334982b2a2dd8513dca0a3de4373d
|
||||
SHADERC_SPIRVHEADERS=b824a462d4256d720bebb40e78b9eb8f78bbb305
|
||||
SHADERC_SPIRVTOOLS=971a7b6e8d7740035bbff089bbbf9f42951ecfd5
|
||||
SHADERC=2026.1
|
||||
SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
|
||||
SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
|
||||
SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
@@ -87,24 +87,24 @@ b3b3813bc9d76b545716dc8b6e659fa71b6e2bc14569e9fab6dab8b30650a644 qttranslations
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
|
||||
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
|
||||
f63fc519f150465bd0bdafcdf3d0e9c23474f4c474171cd515ea1b3a72c081fb harfbuzz-$HARFBUZZ.tar.gz
|
||||
207f96964dc9475b13c1f66565bf145d2658089d65b4cf786d351da2857fc269 harfbuzz-$HARFBUZZ.tar.gz
|
||||
ef39a2e3f9a8a78296c40da701967dd1b0d0d6e267e483863ce70f8a03b4050c $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
1d3fb8ccc2932d04aa3663e22ef5ef490244370f4e568d7850165068778d98d4 libpng-$LIBPNG.tar.xz
|
||||
d925722864837ad5ae2a82070d4b2e0603dc72af44bd457c3962298258b8e82d libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
452a1a290bd0cf18737fad0057dc17b7fdf10a73eda2d6d4f31ba04fda25ef2c libpng-$LIBPNG-apng.patch.gz
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
017c06f75ffed25f6cda9b5369ec6da0ac35a6616adf7abe4222516a0237f37a libpng-$LIBPNG-apng.patch.gz
|
||||
075920b826834ac4ddf97661cc73491047855859affd671d52079c6867c1c6c0 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
|
||||
8a89fb6612ace8954470aae004623374a8fc8b7a34a4277bee5527173b064faf shaderc-$SHADERC.tar.gz
|
||||
272d2725b140e09e85b96eecdc59c2e00c1a14cda2301767e1bf3c363a44b931 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
c693867f10a7760ef1bcf85419d51783586768cc2c601d03841bc6a8b2554b9c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
06b0a042f2e121e954badb4fd78c9e2d4bc7ed6087eceb26ab559c23cf94334f shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
245002feccbe7f8361b223545a5654cea69780745886872d7efff50a38d96c66 shaderc-$SHADERC.tar.gz
|
||||
bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
EOF
|
||||
|
||||
curl -C - -L \
|
||||
|
||||
@@ -24,12 +24,12 @@ QT=6.10.2
|
||||
QTAPNG=1.3.0
|
||||
|
||||
FREETYPE=2.14.1
|
||||
HARFBUZZ=12.2.0
|
||||
HARFBUZZ=13.0.0
|
||||
SDL=SDL3-3.4.2
|
||||
ZSTD=1.5.7
|
||||
LZ4=1.10.0
|
||||
LIBPNG=1.6.53
|
||||
LIBJPEGTURBO=3.1.2
|
||||
LIBPNG=1.6.55
|
||||
LIBJPEGTURBO=3.1.3
|
||||
LIBWEBP=1.6.0
|
||||
FFMPEG=8.0
|
||||
MOLTENVK=1.4.1
|
||||
@@ -37,10 +37,10 @@ KDDOCKWIDGETS=2.4.0
|
||||
PLUTOVG=1.3.2
|
||||
PLUTOSVG=0.0.7
|
||||
|
||||
SHADERC=2025.4
|
||||
SHADERC_GLSLANG=7a47e2531cb334982b2a2dd8513dca0a3de4373d
|
||||
SHADERC_SPIRVHEADERS=b824a462d4256d720bebb40e78b9eb8f78bbb305
|
||||
SHADERC_SPIRVTOOLS=971a7b6e8d7740035bbff089bbbf9f42951ecfd5
|
||||
SHADERC=2026.1
|
||||
SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
|
||||
SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
|
||||
SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
|
||||
|
||||
mkdir -p deps-build
|
||||
cd deps-build
|
||||
@@ -68,24 +68,24 @@ b3b3813bc9d76b545716dc8b6e659fa71b6e2bc14569e9fab6dab8b30650a644 qttranslations
|
||||
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
|
||||
|
||||
32427e8c471ac095853212a37aef816c60b42052d4d9e48230bab3bdf2936ccc freetype-$FREETYPE.tar.xz
|
||||
f63fc519f150465bd0bdafcdf3d0e9c23474f4c474171cd515ea1b3a72c081fb harfbuzz-$HARFBUZZ.tar.gz
|
||||
207f96964dc9475b13c1f66565bf145d2658089d65b4cf786d351da2857fc269 harfbuzz-$HARFBUZZ.tar.gz
|
||||
ef39a2e3f9a8a78296c40da701967dd1b0d0d6e267e483863ce70f8a03b4050c $SDL.tar.gz
|
||||
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
|
||||
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
|
||||
1d3fb8ccc2932d04aa3663e22ef5ef490244370f4e568d7850165068778d98d4 libpng-$LIBPNG.tar.xz
|
||||
d925722864837ad5ae2a82070d4b2e0603dc72af44bd457c3962298258b8e82d libpng-$LIBPNG.tar.xz
|
||||
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
|
||||
452a1a290bd0cf18737fad0057dc17b7fdf10a73eda2d6d4f31ba04fda25ef2c libpng-$LIBPNG-apng.patch.gz
|
||||
8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
017c06f75ffed25f6cda9b5369ec6da0ac35a6616adf7abe4222516a0237f37a libpng-$LIBPNG-apng.patch.gz
|
||||
075920b826834ac4ddf97661cc73491047855859affd671d52079c6867c1c6c0 libjpeg-turbo-$LIBJPEGTURBO.tar.gz
|
||||
b2751fccb6cc4c77708113cd78b561059b6fa904b24162fa0be2d60273d27b8e ffmpeg-$FFMPEG.tar.xz
|
||||
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz
|
||||
51dbf24fe72e43dd7cb9a289d3cab47112010f1a2ed69b6fc8ac0dff31991ed2 KDDockWidgets-$KDDOCKWIDGETS.tar.gz
|
||||
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
|
||||
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
|
||||
|
||||
8a89fb6612ace8954470aae004623374a8fc8b7a34a4277bee5527173b064faf shaderc-$SHADERC.tar.gz
|
||||
272d2725b140e09e85b96eecdc59c2e00c1a14cda2301767e1bf3c363a44b931 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
c693867f10a7760ef1bcf85419d51783586768cc2c601d03841bc6a8b2554b9c shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
06b0a042f2e121e954badb4fd78c9e2d4bc7ed6087eceb26ab559c23cf94334f shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
245002feccbe7f8361b223545a5654cea69780745886872d7efff50a38d96c66 shaderc-$SHADERC.tar.gz
|
||||
bd58dca4dac67dcf7640292d7d63e0416274d40ee2200f7301878cec11ac6647 shaderc-glslang-$SHADERC_GLSLANG.tar.gz
|
||||
1b220e3eec1714f0451b0e3652979bd280edf10893f617837b88e6359a804ded shaderc-spirv-headers-$SHADERC_SPIRVHEADERS.tar.gz
|
||||
cabb35f4eef0da3ef72ad9edd596af4191d7507a8f35c05df526d2d5ff889f59 shaderc-spirv-tools-$SHADERC_SPIRVTOOLS.tar.gz
|
||||
EOF
|
||||
|
||||
curl -L \
|
||||
|
||||
@@ -52,24 +52,24 @@ set QTMINOR=6.10
|
||||
set QTAPNG=1.3.0
|
||||
|
||||
set FREETYPE=2.14.1
|
||||
set HARFBUZZ=12.2.0
|
||||
set LIBJPEGTURBO=3.1.2
|
||||
set LIBPNG=1653
|
||||
set LIBPNGLONG=1.6.53
|
||||
set HARFBUZZ=13.0.0
|
||||
set LIBJPEGTURBO=3.1.3
|
||||
set LIBPNG=1655
|
||||
set LIBPNGLONG=1.6.55
|
||||
set SDL=SDL3-3.4.2
|
||||
set LZ4=1.10.0
|
||||
set WEBP=1.6.0
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZLIB=1.3.2
|
||||
set ZLIBSHORT=132
|
||||
set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.4.0
|
||||
set PLUTOVG=1.3.2
|
||||
set PLUTOSVG=0.0.7
|
||||
|
||||
set SHADERC=2025.4
|
||||
set SHADERC_GLSLANG=7a47e2531cb334982b2a2dd8513dca0a3de4373d
|
||||
set SHADERC_SPIRVHEADERS=b824a462d4256d720bebb40e78b9eb8f78bbb305
|
||||
set SHADERC_SPIRVTOOLS=971a7b6e8d7740035bbff089bbbf9f42951ecfd5
|
||||
set SHADERC=2026.1
|
||||
set SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
|
||||
set SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
|
||||
set SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
|
||||
|
||||
set AGILITYSDK=1.618.5
|
||||
|
||||
@@ -81,24 +81,24 @@ call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 174d9e53402e1bf9ec7277e22ec199ba3e55a6be2c0740cb18c0ee9850fc8c34 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 31490c781bacd2ce56862555b11c51c964977c39f14f51b817dfaecf0be089fe || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1653.zip 140566abc64bb2320cb35f1d154d1cb3eb7174a12234d33bfdffb446bdc0a1d2 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip a448a8abc3f9ae8eef19ef3ce247370957c1fada5d58a01b5e281e792f40fa61 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1655.zip aa45ef52ff7a4e61f34af866b3254b0b243ddc42fe2adb823b0843d2a57c2e86 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 452a1a290bd0cf18737fad0057dc17b7fdf10a73eda2d6d4f31ba04fda25ef2c || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 075920b826834ac4ddf97661cc73491047855859affd671d52079c6867c1c6c0 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 4954d436c95c42aa258d4eb3fb95f8ecc5d7a3dc411f0f41ac2692d34b9b9e9c || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://github.com/madler/zlib/releases/download/v%ZLIB%/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://github.com/madler/zlib/releases/download/v%ZLIB%/zlib%ZLIBSHORT%.zip" e8bf55f3017aa181690990cb58a994e77885da140609fc8f94abe9b65d2cae28 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 4fe4e48f28aa80171b2166d45c0976ab0f21eecedb52cd4c3ef73b5afb48fac9 || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
|
||||
call :downloadfile: "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" 0027fc24f947c48dbded13ada7d280be221eb651644e23a8a476f0f1f0a079dd || goto error
|
||||
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" fab72d1a38eacea52710d18edb95dfd75db894ad869675d07a1eb26827da9b15 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 4a118247386ffba9160113f146f2189ba5abe3995db357114d7112ede6bd3cd1 || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" 9a38cb3b14484f5038d78cd5df89404f2f5b389a6ad91f9f1df4ae71bb9490dc || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" a26383c836a84fab5b03aed5d98e8e27d6c0a9cdbc3b0f462ccfe0a11a3d91ea || goto error
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 3ac59c8216d367ab7858684d39c8faf872a64150aeb139335f4e083c5f79dde0 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 42a30acca4a35955370ed8ff6e54b823b4d4a5a86571baec1203d3fce87da447 || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" 00ecd73dcaaa956cf2221ce899ce096e9535ba20695483c5277adede462d1bde || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 65b23ace0ff0c64daf51f7741ebb6448899fa4aceefc72403e56f5b95607ca8e || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
echo Building debug and release libraries...
|
||||
|
||||
@@ -50,24 +50,24 @@ set QTMINOR=6.10
|
||||
set QTAPNG=1.3.0
|
||||
|
||||
set FREETYPE=2.14.1
|
||||
set HARFBUZZ=12.2.0
|
||||
set LIBJPEGTURBO=3.1.2
|
||||
set LIBPNG=1653
|
||||
set LIBPNGLONG=1.6.53
|
||||
set HARFBUZZ=13.0.0
|
||||
set LIBJPEGTURBO=3.1.3
|
||||
set LIBPNG=1655
|
||||
set LIBPNGLONG=1.6.55
|
||||
set SDL=SDL3-3.4.2
|
||||
set LZ4=1.10.0
|
||||
set WEBP=1.6.0
|
||||
set ZLIB=1.3.1
|
||||
set ZLIBSHORT=131
|
||||
set ZLIB=1.3.2
|
||||
set ZLIBSHORT=132
|
||||
set ZSTD=1.5.7
|
||||
set KDDOCKWIDGETS=2.4.0
|
||||
set PLUTOVG=1.3.2
|
||||
set PLUTOSVG=0.0.7
|
||||
|
||||
set SHADERC=2025.4
|
||||
set SHADERC_GLSLANG=7a47e2531cb334982b2a2dd8513dca0a3de4373d
|
||||
set SHADERC_SPIRVHEADERS=b824a462d4256d720bebb40e78b9eb8f78bbb305
|
||||
set SHADERC_SPIRVTOOLS=971a7b6e8d7740035bbff089bbbf9f42951ecfd5
|
||||
set SHADERC=2026.1
|
||||
set SHADERC_GLSLANG=f0bd0257c308b9a26562c1a30c4748a0219cc951
|
||||
set SHADERC_SPIRVHEADERS=04f10f650d514df88b76d25e83db360142c7b174
|
||||
set SHADERC_SPIRVTOOLS=fbe4f3ad913c44fe8700545f8ffe35d1382b7093
|
||||
|
||||
set AGILITYSDK=1.619.0
|
||||
|
||||
@@ -79,24 +79,24 @@ call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt
|
||||
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
|
||||
|
||||
call :downloadfile "freetype-%FREETYPE%.tar.gz" https://sourceforge.net/projects/freetype/files/freetype2/%FREETYPE%/freetype-%FREETYPE%.tar.gz/download 174d9e53402e1bf9ec7277e22ec199ba3e55a6be2c0740cb18c0ee9850fc8c34 || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip 31490c781bacd2ce56862555b11c51c964977c39f14f51b817dfaecf0be089fe || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1653.zip 140566abc64bb2320cb35f1d154d1cb3eb7174a12234d33bfdffb446bdc0a1d2 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 452a1a290bd0cf18737fad0057dc17b7fdf10a73eda2d6d4f31ba04fda25ef2c || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 8f0012234b464ce50890c490f18194f913a7b1f4e6a03d6644179fa0f867d0cf || goto error
|
||||
call :downloadfile "harfbuzz-%HARFBUZZ%.zip" https://github.com/harfbuzz/harfbuzz/archive/refs/tags/%HARFBUZZ%.zip a448a8abc3f9ae8eef19ef3ce247370957c1fada5d58a01b5e281e792f40fa61 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lpng1655.zip aa45ef52ff7a4e61f34af866b3254b0b243ddc42fe2adb823b0843d2a57c2e86 || goto error
|
||||
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz 017c06f75ffed25f6cda9b5369ec6da0ac35a6616adf7abe4222516a0237f37a || goto error
|
||||
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 075920b826834ac4ddf97661cc73491047855859affd671d52079c6867c1c6c0 || goto error
|
||||
call :downloadfile "libwebp-%WEBP%.tar.gz" "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-%WEBP%.tar.gz" e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 || goto error
|
||||
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 4954d436c95c42aa258d4eb3fb95f8ecc5d7a3dc411f0f41ac2692d34b9b9e9c || goto error
|
||||
call :downloadfile "lz4-%LZ4%.zip" "https://github.com/lz4/lz4/archive/refs/tags/v%LZ4%.zip" 3224b4c80f351f194984526ef396f6079bd6332dd9825c72ac0d7a37b3cdc565 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://github.com/madler/zlib/releases/download/v%ZLIB%/zlib%ZLIBSHORT%.zip" 72af66d44fcc14c22013b46b814d5d2514673dda3d115e64b690c1ad636e7b17 || goto error
|
||||
call :downloadfile "zlib%ZLIBSHORT%.zip" "https://github.com/madler/zlib/releases/download/v%ZLIB%/zlib%ZLIBSHORT%.zip" e8bf55f3017aa181690990cb58a994e77885da140609fc8f94abe9b65d2cae28 || goto error
|
||||
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
|
||||
call :downloadfile "KDDockWidgets-%KDDOCKWIDGETS%.zip" "https://github.com/KDAB/KDDockWidgets/archive/v%KDDOCKWIDGETS%.zip" 47ddb48197872055f0adf8e90a7235f8a3b795ca1ee3a28ac2c504c673ae3806 || goto error
|
||||
call :downloadfile "plutovg-%PLUTOVG%.zip" "https://github.com/sammycage/plutovg/archive/v%PLUTOVG%.zip" 4fe4e48f28aa80171b2166d45c0976ab0f21eecedb52cd4c3ef73b5afb48fac9 || goto error
|
||||
call :downloadfile "plutosvg-%PLUTOSVG%.zip" "https://github.com/sammycage/plutosvg/archive/v%PLUTOSVG%.zip" 82dee2c57ad712bdd6d6d81d3e76249d89caa4b5a4214353660fd5adff12201a || goto error
|
||||
call :downloadfile "agility-sdk-%AGILITYSDK%.nupkg" "https://www.nuget.org/api/v2/package/Microsoft.Direct3D.D3D12/%AGILITYSDK%" d5edab9a0c4d1b78ba6fe55b425eeef9fefba7d2a101e889d70fd21d481e6cb1 || goto error
|
||||
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" fab72d1a38eacea52710d18edb95dfd75db894ad869675d07a1eb26827da9b15 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 4a118247386ffba9160113f146f2189ba5abe3995db357114d7112ede6bd3cd1 || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" 9a38cb3b14484f5038d78cd5df89404f2f5b389a6ad91f9f1df4ae71bb9490dc || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" a26383c836a84fab5b03aed5d98e8e27d6c0a9cdbc3b0f462ccfe0a11a3d91ea || goto error
|
||||
call :downloadfile "shaderc-%SHADERC%.zip" "https://github.com/google/shaderc/archive/refs/tags/v%SHADERC%.zip" 3ac59c8216d367ab7858684d39c8faf872a64150aeb139335f4e083c5f79dde0 || goto error
|
||||
call :downloadfile "shaderc-glslang-%SHADERC_GLSLANG%.zip" "https://github.com/KhronosGroup/glslang/archive/%SHADERC_GLSLANG%.zip" 42a30acca4a35955370ed8ff6e54b823b4d4a5a86571baec1203d3fce87da447 || goto error
|
||||
call :downloadfile "shaderc-spirv-headers-%SHADERC_SPIRVHEADERS%.zip" "https://github.com/KhronosGroup/SPIRV-Headers/archive/%SHADERC_SPIRVHEADERS%.zip" 00ecd73dcaaa956cf2221ce899ce096e9535ba20695483c5277adede462d1bde || goto error
|
||||
call :downloadfile "shaderc-spirv-tools-%SHADERC_SPIRVTOOLS%.zip" "https://github.com/KhronosGroup/SPIRV-Tools/archive/%SHADERC_SPIRVTOOLS%.zip" 65b23ace0ff0c64daf51f7741ebb6448899fa4aceefc72403e56f5b95607ca8e || goto error
|
||||
|
||||
if %DEBUG%==1 (
|
||||
echo Building debug and release libraries...
|
||||
|
||||
Vendored
+9
-7
@@ -155,15 +155,17 @@ executable(
|
||||
|
||||
This project can be built using [Bazel](https://bazel.build/install).
|
||||
|
||||
You can also use this library as a dependency to your Bazel project. Add to the `WORKSPACE` file:
|
||||
You can also use this library as a dependency to your Bazel project. Add to your `MODULE.bazel` file:
|
||||
|
||||
```python
|
||||
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
|
||||
# fetch cpuinfo from Bazel Central Registry: https://registry.bazel.build/modules/cpuinfo
|
||||
bazel_dep(name = "cpuinfo", version = "0.0.0-20250925-877328f")
|
||||
|
||||
git_repository(
|
||||
name = "org_pytorch_cpuinfo",
|
||||
branch = "master",
|
||||
remote = "https://github.com/Vertexwahn/cpuinfo.git",
|
||||
# Optional: Override it with some specific commit hash
|
||||
git_override(
|
||||
module_name = "cpuinfo",
|
||||
commit = "<replace_with_commit_hash>"
|
||||
remote = "https://github.com/pytorch/cpuinfo.git",
|
||||
)
|
||||
```
|
||||
|
||||
@@ -176,7 +178,7 @@ cc_binary(
|
||||
# ...
|
||||
],
|
||||
deps = [
|
||||
"@org_pytorch_cpuinfo//:cpuinfo",
|
||||
"@cpuinfo",
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.18 FATAL_ERROR)
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12 FATAL_ERROR)
|
||||
|
||||
PROJECT(googletest-download NONE)
|
||||
|
||||
INCLUDE(ExternalProject)
|
||||
ExternalProject_Add(googletest
|
||||
URL https://github.com/google/googletest/archive/refs/tags/v1.17.0.zip
|
||||
URL_HASH SHA256=40d4ec942217dcc84a9ebe2a68584ada7d4a33a8ee958755763278ea1c5e18ff
|
||||
URL https://github.com/google/googletest/archive/release-1.8.0.zip
|
||||
URL_HASH SHA256=f3ed3b58511efd272eb074a3a6d6fb79d7c2e6a0e374323d1e6bcbcc1ef141bf
|
||||
SOURCE_DIR "${CONFU_DEPENDENCIES_SOURCE_DIR}/googletest"
|
||||
BINARY_DIR "${CONFU_DEPENDENCIES_BINARY_DIR}/googletest"
|
||||
CONFIGURE_COMMAND ""
|
||||
|
||||
Vendored
+23
@@ -431,6 +431,8 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_zen4 = 0x0020010C,
|
||||
/** AMD Zen 5 microarchitecture. */
|
||||
cpuinfo_uarch_zen5 = 0x0020010D,
|
||||
/** AMD Zen 6 microarchitecture. */
|
||||
cpuinfo_uarch_zen6 = 0x0020010E,
|
||||
|
||||
/** NSC Geode and AMD Geode GX and LX. */
|
||||
cpuinfo_uarch_geode = 0x00200200,
|
||||
@@ -526,6 +528,15 @@ enum cpuinfo_uarch {
|
||||
/** ARM Cortex-A725. */
|
||||
cpuinfo_uarch_cortex_a725 = 0x00300574,
|
||||
|
||||
/** ARM Lumex-C1-Ultra. */
|
||||
cpuinfo_uarch_lumex_c1_ultra = 0x00300600,
|
||||
/** ARM Lumex-C1-Premium. */
|
||||
cpuinfo_uarch_lumex_c1_premium = 0x00300601,
|
||||
/** ARM Lumex-C1-Pro. */
|
||||
cpuinfo_uarch_lumex_c1_pro = 0x00300602,
|
||||
/** ARM Lumex-C1-Nano. */
|
||||
cpuinfo_uarch_lumex_c1_nano = 0x00300603,
|
||||
|
||||
/** Qualcomm Scorpion. */
|
||||
cpuinfo_uarch_scorpion = 0x00400100,
|
||||
/** Qualcomm Krait. */
|
||||
@@ -538,6 +549,8 @@ enum cpuinfo_uarch {
|
||||
cpuinfo_uarch_saphira = 0x00400104,
|
||||
/** Qualcomm Oryon. */
|
||||
cpuinfo_uarch_oryon = 0x00400105,
|
||||
/** Qualcomm Oryon V3. */
|
||||
cpuinfo_uarch_oryon_v3 = 0x00400106,
|
||||
|
||||
/** Nvidia Denver. */
|
||||
cpuinfo_uarch_denver = 0x00500100,
|
||||
@@ -612,6 +625,16 @@ enum cpuinfo_uarch {
|
||||
/** Apple A18 pro processor (little cores). */
|
||||
cpuinfo_uarch_tahiti_sawtooth = 0x00700207,
|
||||
|
||||
/** Apple A19 processor (big cores). */
|
||||
cpuinfo_uarch_tilos_everest = 0x00700208,
|
||||
/** Apple A19 processor (little cores). */
|
||||
cpuinfo_uarch_tilos_sawtooth = 0x00700209,
|
||||
|
||||
/** Apple M4 processor (big cores). */
|
||||
cpuinfo_uarch_donan_everest = 0x00700308,
|
||||
/** Apple M4 processor (little cores). */
|
||||
cpuinfo_uarch_donan_sawtooth = 0x00700309,
|
||||
|
||||
/** Cavium ThunderX. */
|
||||
cpuinfo_uarch_thunderx = 0x00800100,
|
||||
/** Cavium ThunderX2 (originally Broadcom Vulkan). */
|
||||
|
||||
@@ -69,6 +69,7 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
|
||||
* - Processors with Cortex-A77 cores
|
||||
* - Processors with Cortex-A78 cores
|
||||
* - Processors with Cortex-A510 cores
|
||||
* - Processors with Cortex-A520 cores
|
||||
* - Processors with Cortex-A710 cores
|
||||
* - Processors with Cortex-A715 cores
|
||||
* - Processors with Cortex-X1 cores
|
||||
@@ -101,6 +102,7 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
|
||||
case UINT32_C(0x4100D470): /* Cortex-A710 */
|
||||
case UINT32_C(0x4100D480): /* Cortex-X2 */
|
||||
case UINT32_C(0x4100D490): /* Neoverse N2 */
|
||||
case UINT32_C(0x4100D4B0): /* Cortex-A78C */
|
||||
case UINT32_C(0x4100D4D0): /* Cortex-A715 */
|
||||
case UINT32_C(0x4100D4E0): /* Cortex-X3 */
|
||||
case UINT32_C(0x4100D4F0): /* Neoverse V2 */
|
||||
@@ -162,6 +164,7 @@ void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
|
||||
case UINT32_C(0x4100D470): /* Cortex-A710 */
|
||||
case UINT32_C(0x4100D480): /* Cortex-X2 */
|
||||
case UINT32_C(0x4100D490): /* Neoverse N2 */
|
||||
case UINT32_C(0x4100D4B0): /* Cortex-A78C */
|
||||
case UINT32_C(0x4100D4D0): /* Cortex-A715 */
|
||||
case UINT32_C(0x4100D4E0): /* Cortex-X3 */
|
||||
case UINT32_C(0x4100D4F0): /* Neoverse V2 */
|
||||
|
||||
+8
-8
@@ -1314,7 +1314,7 @@ static bool match_omap(const char* start, const char* end, struct cpuinfo_arm_ch
|
||||
* ro.board.platform) to match.
|
||||
* @param cores - number of cores in the chipset.
|
||||
* @param max_cpu_freq_max - maximum of
|
||||
* /sys/devices/system/cpu/cpu<number>/cpofreq/cpu_freq_max values.
|
||||
* /sys/devices/system/cpu/cpu<number>/cpufreq/cpu_freq_max values.
|
||||
* @param[out] chipset - location where chipset information will be stored upon
|
||||
* a successful match and decoding.
|
||||
*
|
||||
@@ -1607,7 +1607,7 @@ static bool match_and_parse_sunxi(
|
||||
* @param end - end of the /proc/cpuinfo Hardware string to match.
|
||||
* @param cores - number of cores in the chipset.
|
||||
* @param max_cpu_freq_max - maximum of
|
||||
* /sys/devices/system/cpu/cpu<number>/cpofreq/cpu_freq_max values.
|
||||
* /sys/devices/system/cpu/cpu<number>/cpufreq/cpu_freq_max values.
|
||||
* @param[out] chipset - location where chipset information will be stored upon
|
||||
* a successful match and decoding.
|
||||
*
|
||||
@@ -2456,7 +2456,7 @@ static const struct special_map_entry tegra_hardware_map_entries[] = {
|
||||
* @param[in] platform - /proc/cpuinfo Hardware string.
|
||||
* @param cores - number of cores in the chipset.
|
||||
* @param max_cpu_freq_max - maximum of
|
||||
* /sys/devices/system/cpu/cpu<number>/cpofreq/cpu_freq_max values.
|
||||
* /sys/devices/system/cpu/cpu<number>/cpufreq/cpu_freq_max values.
|
||||
*
|
||||
* @returns Decoded chipset name. If chipset could not be decoded, the resulting
|
||||
* structure would use `unknown` vendor and series identifiers.
|
||||
@@ -2857,7 +2857,7 @@ static const struct special_map_entry special_board_map_entries[] = {
|
||||
* @param[in] platform - ro.product.board value.
|
||||
* @param cores - number of cores in the chipset.
|
||||
* @param max_cpu_freq_max - maximum of
|
||||
* /sys/devices/system/cpu/cpu<number>/cpofreq/cpu_freq_max values.
|
||||
* /sys/devices/system/cpu/cpu<number>/cpufreq/cpu_freq_max values.
|
||||
*
|
||||
* @returns Decoded chipset name. If chipset could not be decoded, the resulting
|
||||
* structure would use `unknown` vendor and series identifiers.
|
||||
@@ -3162,7 +3162,7 @@ static const struct special_map_entry special_platform_map_entries[] = {
|
||||
* @param[in] platform - ro.board.platform value.
|
||||
* @param cores - number of cores in the chipset.
|
||||
* @param max_cpu_freq_max - maximum of
|
||||
* /sys/devices/system/cpu/cpu<number>/cpofreq/cpu_freq_max values.
|
||||
* /sys/devices/system/cpu/cpu<number>/cpufreq/cpu_freq_max values.
|
||||
*
|
||||
* @returns Decoded chipset name. If chipset could not be decoded, the resulting
|
||||
* structure would use `unknown` vendor and series identifiers.
|
||||
@@ -3499,7 +3499,7 @@ struct cpuinfo_arm_chipset cpuinfo_arm_android_decode_chipset_from_ro_chipname(
|
||||
* @param[in,out] chipset - chipset name to fix.
|
||||
* @param cores - number of cores in the chipset.
|
||||
* @param max_cpu_freq_max - maximum of
|
||||
* /sys/devices/system/cpu/cpu<number>/cpofreq/cpu_freq_max values.
|
||||
* /sys/devices/system/cpu/cpu<number>/cpufreq/cpu_freq_max values.
|
||||
*/
|
||||
void cpuinfo_arm_fixup_chipset(
|
||||
struct cpuinfo_arm_chipset chipset[restrict static 1],
|
||||
@@ -4038,7 +4038,7 @@ static enum cpuinfo_arm_chipset_vendor disambiguate_chipset_vendor(
|
||||
* described above.
|
||||
* @param cores - number of cores in the chipset.
|
||||
* @param max_cpu_freq_max - maximum of
|
||||
* /sys/devices/system/cpu/cpu<number>/cpofreq/cpu_freq_max values.
|
||||
* /sys/devices/system/cpu/cpu<number>/cpufreq/cpu_freq_max values.
|
||||
*
|
||||
* @returns Decoded chipset name. If chipset could not be decoded, the resulting
|
||||
* structure would use `unknown` vendor and series identifiers.
|
||||
@@ -4291,7 +4291,7 @@ void cpuinfo_arm_fixup_raspberry_pi_chipset(
|
||||
* @param[in] hardware - /proc/cpuinfo Hardware string.
|
||||
* @param cores - number of cores in the chipset.
|
||||
* @param max_cpu_freq_max - maximum of
|
||||
* /sys/devices/system/cpu/cpu<number>/cpofreq/cpu_freq_max values.
|
||||
* /sys/devices/system/cpu/cpu<number>/cpufreq/cpu_freq_max values.
|
||||
*
|
||||
* @returns Decoded chipset name. If chipset could not be decoded, the resulting
|
||||
* structure would use `unknown` vendor and series identifiers.
|
||||
|
||||
Vendored
+76
-67
@@ -21,9 +21,11 @@
|
||||
#ifndef CPUFAMILY_ARM_LIGHTNING_THUNDER
|
||||
#define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504D2
|
||||
#endif
|
||||
// A14 / M1
|
||||
#ifndef CPUFAMILY_ARM_FIRESTORM_ICESTORM
|
||||
#define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1B588BB3
|
||||
#endif
|
||||
// A15 / M2
|
||||
#ifndef CPUFAMILY_ARM_AVALANCHE_BLIZZARD
|
||||
#define CPUFAMILY_ARM_AVALANCHE_BLIZZARD 0xDA33D83D
|
||||
#endif
|
||||
@@ -66,6 +68,18 @@
|
||||
#ifndef CPUFAMILY_ARM_BRAVA
|
||||
#define CPUFAMILY_ARM_BRAVA 0x17d5b93a
|
||||
#endif
|
||||
// M5
|
||||
#ifndef CPUFAMILY_ARM_HIDRA
|
||||
#define CPUFAMILY_ARM_HIDRA 0x1d5a87e8
|
||||
#endif
|
||||
// A19
|
||||
#ifndef CPUFAMILY_ARM_TILOS
|
||||
#define CPUFAMILY_ARM_TILOS 0x01d7a72b
|
||||
#endif
|
||||
// A19 Pro
|
||||
#ifndef CPUFAMILY_ARM_THERA
|
||||
#define CPUFAMILY_ARM_THERA 0xab345f09
|
||||
#endif
|
||||
|
||||
struct cpuinfo_arm_isa cpuinfo_isa = {
|
||||
.aes = true,
|
||||
@@ -118,37 +132,59 @@ static enum cpuinfo_uarch decode_uarch(uint32_t cpu_family, uint32_t core_index,
|
||||
/* 2x Monsoon + 4x Mistral cores */
|
||||
return core_index < 2 ? cpuinfo_uarch_monsoon : cpuinfo_uarch_mistral;
|
||||
case CPUFAMILY_ARM_VORTEX_TEMPEST:
|
||||
/* Hexa-core: 2x Vortex + 4x Tempest; Octa-core: 4x
|
||||
* Cortex + 4x Tempest */
|
||||
/* Hexa-core: 2x Vortex + 4x Tempest; */
|
||||
/* Octa-core: 4x Cortex + 4x Tempest */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_vortex : cpuinfo_uarch_tempest;
|
||||
case CPUFAMILY_ARM_LIGHTNING_THUNDER:
|
||||
/* Hexa-core: 2x Lightning + 4x Thunder; Octa-core
|
||||
* (presumed): 4x Lightning + 4x Thunder */
|
||||
/* Hexa-core: 2x Lightning + 4x Thunder; */
|
||||
/* Octa-core: 4x Lightning + 4x Thunder */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_lightning : cpuinfo_uarch_thunder;
|
||||
case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
|
||||
/* Hexa-core: 2x Firestorm + 4x Icestorm; Octa-core: 4x
|
||||
* Firestorm + 4x Icestorm */
|
||||
/* Hexa-core: 2x Firestorm + 4x Icestorm; */
|
||||
/* Octa-core: 4x Firestorm + 4x Icestorm */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_firestorm : cpuinfo_uarch_icestorm;
|
||||
case CPUFAMILY_ARM_AVALANCHE_BLIZZARD:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_avalanche : cpuinfo_uarch_blizzard;
|
||||
case CPUFAMILY_ARM_EVEREST_SAWTOOTH:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
/* Hexa-core: 2x Everest + 4x Sawtooth */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_everest : cpuinfo_uarch_sawtooth;
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_avalanche : cpuinfo_uarch_blizzard;
|
||||
|
||||
case CPUFAMILY_ARM_IBIZA: /* M3 */
|
||||
/* 8-core: 4x Coll Everest v2 + 4x Coll Sawtooth v2*/
|
||||
case CPUFAMILY_ARM_PALMA: /* M3 Max */
|
||||
/* 14-core: 10x Coll Everest v2 + 4x Coll Sawtooth v2*/
|
||||
case CPUFAMILY_ARM_COLL:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
/* Hexa-core: 2x Coll Everest v2 + 4x Coll Sawtooth v2 */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_coll_everest : cpuinfo_uarch_coll_sawtooth;
|
||||
case CPUFAMILY_ARM_LOBOS: /* M3 Pro */
|
||||
/* 12-core: 6x Coll Everest v2 + 6x Coll Sawtooth v2v2 */
|
||||
return core_index + 6 < core_count ? cpuinfo_uarch_coll_everest : cpuinfo_uarch_coll_sawtooth;
|
||||
|
||||
case CPUFAMILY_ARM_TUPAI:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
/* Hexa-core: 2x Tupai Everest v3 + 4x Tupai Sawtooth v3 */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_tupai_everest : cpuinfo_uarch_tupai_sawtooth;
|
||||
|
||||
case CPUFAMILY_ARM_TAHITI:
|
||||
/* Hexa-core: 2x Avalanche + 4x Blizzard */
|
||||
/* Hexa-core: 2x Tahiti Everest + 4x Tahiti Sawtooth */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_tahiti_everest
|
||||
: cpuinfo_uarch_tahiti_sawtooth;
|
||||
|
||||
case CPUFAMILY_ARM_DONAN: /* M4 */
|
||||
/* 10-core: 4x Donan Everest v3 + 6x Donan Sawtooth v3 */
|
||||
return core_index + 6 < core_count ? cpuinfo_uarch_donan_everest : cpuinfo_uarch_donan_sawtooth;
|
||||
case CPUFAMILY_ARM_BRAVA: /* M4 Pro */
|
||||
/* 14-core: 10x Donan Everest v3 + 4x Donan Sawtooth v3 */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_donan_everest : cpuinfo_uarch_donan_sawtooth;
|
||||
|
||||
case CPUFAMILY_ARM_TILOS: /* A19 */
|
||||
case CPUFAMILY_ARM_THERA: /* A19 Pro */
|
||||
/* Hexa-core: 2x Tilos Everest v4 + 4x Tilos Sawtooth v4 */
|
||||
return core_index + 4 < core_count ? cpuinfo_uarch_tilos_everest : cpuinfo_uarch_tilos_sawtooth;
|
||||
case CPUFAMILY_ARM_HIDRA: /* M5 */
|
||||
/* 10-core: 4x Tilos Everest v4 + 6x Tilos Sawtooth v4 */
|
||||
return core_index + 6 < core_count ? cpuinfo_uarch_tilos_everest : cpuinfo_uarch_tilos_sawtooth;
|
||||
|
||||
default:
|
||||
/* Use hw.cpusubtype for detection */
|
||||
break;
|
||||
@@ -361,10 +397,8 @@ void cpuinfo_arm_mach_init(void) {
|
||||
* possible. Otherwise, fallback to hardcoded set of CPUs with known
|
||||
* support.
|
||||
*/
|
||||
const uint32_t has_feat_lse = get_sys_info_by_name("hw.optional.arm.FEAT_LSE");
|
||||
if (has_feat_lse != 0) {
|
||||
cpuinfo_isa.atomics = true;
|
||||
} else {
|
||||
cpuinfo_isa.atomics = get_sys_info_by_name("hw.optional.arm.FEAT_LSE") != 0;
|
||||
if (!cpuinfo_isa.atomics) {
|
||||
// Mandatory in ARMv8.1-A, list only cores released before iOS
|
||||
// 15 / macOS 12
|
||||
switch (cpu_family) {
|
||||
@@ -376,10 +410,8 @@ void cpuinfo_arm_mach_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t has_feat_rdm = get_sys_info_by_name("hw.optional.arm.FEAT_RDM");
|
||||
if (has_feat_rdm != 0) {
|
||||
cpuinfo_isa.rdm = true;
|
||||
} else {
|
||||
cpuinfo_isa.rdm = get_sys_info_by_name("hw.optional.arm.FEAT_RDM") != 0;
|
||||
if (!cpuinfo_isa.rdm) {
|
||||
// Optional in ARMv8.2-A (implemented in Apple cores),
|
||||
// list only cores released before iOS 15 / macOS 12
|
||||
switch (cpu_family) {
|
||||
@@ -391,10 +423,8 @@ void cpuinfo_arm_mach_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t has_feat_fp16 = get_sys_info_by_name("hw.optional.arm.FEAT_FP16");
|
||||
if (has_feat_fp16 != 0) {
|
||||
cpuinfo_isa.fp16arith = true;
|
||||
} else {
|
||||
cpuinfo_isa.fp16arith = get_sys_info_by_name("hw.optional.arm.FEAT_FP16") != 0;
|
||||
if (!cpuinfo_isa.fp16arith) {
|
||||
// Optional in ARMv8.2-A (implemented in Apple cores),
|
||||
// list only cores released before iOS 15 / macOS 12
|
||||
switch (cpu_family) {
|
||||
@@ -406,15 +436,11 @@ void cpuinfo_arm_mach_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t has_feat_fhm = get_sys_info_by_name("hw.optional.arm.FEAT_FHM");
|
||||
if (has_feat_fhm != 0) {
|
||||
cpuinfo_isa.fhm = true;
|
||||
} else {
|
||||
cpuinfo_isa.fhm = get_sys_info_by_name("hw.optional.arm.FEAT_FHM") != 0;
|
||||
if (!cpuinfo_isa.fhm) {
|
||||
// Prior to iOS 15, use 'hw.optional.armv8_2_fhm'
|
||||
const uint32_t has_feat_fhm_legacy = get_sys_info_by_name("hw.optional.armv8_2_fhm");
|
||||
if (has_feat_fhm_legacy != 0) {
|
||||
cpuinfo_isa.fhm = true;
|
||||
} else {
|
||||
cpuinfo_isa.fhm = get_sys_info_by_name("hw.optional.armv8_2_fhm") != 0;
|
||||
if (!cpuinfo_isa.fhm) {
|
||||
// Mandatory in ARMv8.4-A when FP16 arithmetics is
|
||||
// implemented, list only cores released before iOS 15 /
|
||||
// macOS 12
|
||||
@@ -426,17 +452,10 @@ void cpuinfo_arm_mach_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t has_feat_bf16 = get_sys_info_by_name("hw.optional.arm.FEAT_BF16");
|
||||
if (has_feat_bf16 != 0) {
|
||||
cpuinfo_isa.bf16 = true;
|
||||
}
|
||||
|
||||
const uint32_t has_feat_fcma = get_sys_info_by_name("hw.optional.arm.FEAT_FCMA");
|
||||
if (has_feat_fcma != 0) {
|
||||
cpuinfo_isa.fcma = true;
|
||||
} else {
|
||||
// Mandatory in ARMv8.3-A, list only cores released before iOS
|
||||
// 15 / macOS 12
|
||||
cpuinfo_isa.bf16 = get_sys_info_by_name("hw.optional.arm.FEAT_BF16") != 0;
|
||||
cpuinfo_isa.fcma = get_sys_info_by_name("hw.optional.arm.FEAT_FCMA") != 0;
|
||||
if (!cpuinfo_isa.fcma) {
|
||||
// Mandatory in ARMv8.3-A, list only cores released before iOS 15 / macOS 12
|
||||
switch (cpu_family) {
|
||||
case CPUFAMILY_ARM_LIGHTNING_THUNDER:
|
||||
case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
|
||||
@@ -444,12 +463,9 @@ void cpuinfo_arm_mach_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t has_feat_jscvt = get_sys_info_by_name("hw.optional.arm.FEAT_JSCVT");
|
||||
if (has_feat_jscvt != 0) {
|
||||
cpuinfo_isa.jscvt = true;
|
||||
} else {
|
||||
// Mandatory in ARMv8.3-A, list only cores released before iOS
|
||||
// 15 / macOS 12
|
||||
cpuinfo_isa.jscvt = get_sys_info_by_name("hw.optional.arm.FEAT_JSCVT") != 0;
|
||||
if (!cpuinfo_isa.jscvt) {
|
||||
// Mandatory in ARMv8.3-A, list only cores released before iOS 15 / macOS 12
|
||||
switch (cpu_family) {
|
||||
case CPUFAMILY_ARM_LIGHTNING_THUNDER:
|
||||
case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
|
||||
@@ -457,12 +473,9 @@ void cpuinfo_arm_mach_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t has_feat_dotprod = get_sys_info_by_name("hw.optional.arm.FEAT_DotProd");
|
||||
if (has_feat_dotprod != 0) {
|
||||
cpuinfo_isa.dot = true;
|
||||
} else {
|
||||
// Mandatory in ARMv8.4-A, list only cores released before iOS
|
||||
// 15 / macOS 12
|
||||
cpuinfo_isa.dot = get_sys_info_by_name("hw.optional.arm.FEAT_DotProd") != 0;
|
||||
if (!cpuinfo_isa.dot) {
|
||||
// Mandatory in ARMv8.4-A, list only cores released before iOS 15 / macOS 12
|
||||
switch (cpu_family) {
|
||||
case CPUFAMILY_ARM_LIGHTNING_THUNDER:
|
||||
case CPUFAMILY_ARM_FIRESTORM_ICESTORM:
|
||||
@@ -470,20 +483,16 @@ void cpuinfo_arm_mach_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
const uint32_t has_feat_i8mm = get_sys_info_by_name("hw.optional.arm.FEAT_I8MM");
|
||||
if (has_feat_i8mm != 0) {
|
||||
cpuinfo_isa.i8mm = true;
|
||||
}
|
||||
cpuinfo_isa.i8mm = get_sys_info_by_name("hw.optional.arm.FEAT_I8MM") != 0;
|
||||
cpuinfo_isa.sme = get_sys_info_by_name("hw.optional.arm.FEAT_SME") != 0;
|
||||
cpuinfo_isa.sme2 = get_sys_info_by_name("hw.optional.arm.FEAT_SME2") != 0;
|
||||
cpuinfo_isa.sme2p1 = get_sys_info_by_name("hw.optional.arm.FEAT_SME2p1") != 0;
|
||||
cpuinfo_isa.sme_i16i32 = get_sys_info_by_name("hw.optional.arm.SME_I16I32") != 0;
|
||||
cpuinfo_isa.sme_bi32i32 = get_sys_info_by_name("hw.optional.arm.SME_BI32I32") != 0;
|
||||
cpuinfo_isa.sme_b16b16 = get_sys_info_by_name("hw.optional.arm.FEAT_SME_B16B16") != 0;
|
||||
cpuinfo_isa.sme_f16f16 = get_sys_info_by_name("hw.optional.arm.FEAT_SME_F16F16") != 0;
|
||||
|
||||
const uint32_t has_feat_sme = get_sys_info_by_name("hw.optional.arm.FEAT_SME");
|
||||
if (has_feat_sme != 0) {
|
||||
cpuinfo_isa.sme = true;
|
||||
}
|
||||
|
||||
const uint32_t has_feat_sme2 = get_sys_info_by_name("hw.optional.arm.FEAT_SME2");
|
||||
if (has_feat_sme2 != 0) {
|
||||
cpuinfo_isa.sme2 = true;
|
||||
}
|
||||
cpuinfo_isa.smelen = get_sys_info_by_name("hw.optional.arm.sme_max_svl_b");
|
||||
|
||||
uint32_t num_clusters = 1;
|
||||
for (uint32_t i = 0; i < mach_topology.cores; i++) {
|
||||
|
||||
Vendored
+4
@@ -192,6 +192,7 @@ inline static uint32_t midr_score_core(uint32_t midr) {
|
||||
case UINT32_C(0x4100D0D0): /* Cortex-A77 */
|
||||
case UINT32_C(0x4100D0E0): /* Cortex-A76AE */
|
||||
case UINT32_C(0x4100D410): /* Cortex-A78 */
|
||||
case UINT32_C(0x4100D4B0): /* Cortex-A78C */
|
||||
case UINT32_C(0x4100D470): /* Cortex-A710 */
|
||||
case UINT32_C(0x4100D4D0): /* Cortex-A715 */
|
||||
case UINT32_C(0x4800D400): /* Cortex-A76 (HiSilicon) */
|
||||
@@ -220,6 +221,9 @@ inline static uint32_t midr_score_core(uint32_t midr) {
|
||||
case UINT32_C(0x4100D030): /* Cortex-A53 */
|
||||
case UINT32_C(0x4100D050): /* Cortex-A55 */
|
||||
case UINT32_C(0x4100D460): /* Cortex-A510 */
|
||||
#if CPUINFO_ARCH_ARM64
|
||||
case UINT32_C(0x4100D800): /* Cortex-A520 */
|
||||
#endif /* CPUINFO_ARCH_ARM64 */
|
||||
/* Cortex-A53 is usually in LITTLE role, but can be in
|
||||
* big role w.r.t. Cortex-A35 */
|
||||
return 2;
|
||||
|
||||
Vendored
+19
@@ -94,6 +94,7 @@ void cpuinfo_arm_decode_vendor_uarch(
|
||||
*uarch = cpuinfo_uarch_neoverse_v1;
|
||||
break;
|
||||
case 0xD41: /* Cortex-A78 */
|
||||
case 0xD4B: /* Cortex-A78C */
|
||||
*uarch = cpuinfo_uarch_cortex_a78;
|
||||
break;
|
||||
case 0xD44: /* Cortex-X1 */
|
||||
@@ -125,6 +126,9 @@ void cpuinfo_arm_decode_vendor_uarch(
|
||||
case 0xD4F: /* Neoverse V2 */
|
||||
*uarch = cpuinfo_uarch_neoverse_v2;
|
||||
break;
|
||||
case 0xD80: /* Cortex-A520 */
|
||||
*uarch = cpuinfo_uarch_cortex_a520;
|
||||
break;
|
||||
case 0xD81: /* Cortex-A720 */
|
||||
*uarch = cpuinfo_uarch_cortex_a720;
|
||||
break;
|
||||
@@ -137,6 +141,18 @@ void cpuinfo_arm_decode_vendor_uarch(
|
||||
case 0xD87: /* Cortex-A725 */
|
||||
*uarch = cpuinfo_uarch_cortex_a725;
|
||||
break;
|
||||
case 0xD8C:
|
||||
*uarch = cpuinfo_uarch_lumex_c1_ultra;
|
||||
break;
|
||||
case 0xD90:
|
||||
*uarch = cpuinfo_uarch_lumex_c1_premium;
|
||||
break;
|
||||
case 0xD8B:
|
||||
*uarch = cpuinfo_uarch_lumex_c1_pro;
|
||||
break;
|
||||
case 0xD8A:
|
||||
*uarch = cpuinfo_uarch_lumex_c1_nano;
|
||||
break;
|
||||
default:
|
||||
switch (midr_get_part(midr) >> 8) {
|
||||
#if CPUINFO_ARCH_ARM
|
||||
@@ -347,6 +363,9 @@ void cpuinfo_arm_decode_vendor_uarch(
|
||||
case 0x001:
|
||||
*uarch = cpuinfo_uarch_oryon;
|
||||
break;
|
||||
case 0x002:
|
||||
*uarch = cpuinfo_uarch_oryon_v3;
|
||||
break;
|
||||
case 0xC00:
|
||||
*uarch = cpuinfo_uarch_falkor;
|
||||
break;
|
||||
|
||||
+8
@@ -249,6 +249,14 @@ static void set_cpuinfo_isa_fields(void) {
|
||||
// guarantee that, but it holds in practice.
|
||||
cpuinfo_isa.rdm = dotprod;
|
||||
|
||||
// PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE may not be available in older
|
||||
// Windows versions. If fp16arith was not detected with
|
||||
// IsProcessorFeaturePresent(PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE), fall
|
||||
// back to using the value of dotprod.
|
||||
if (!cpuinfo_isa.fp16arith) {
|
||||
cpuinfo_isa.fp16arith = dotprod;
|
||||
}
|
||||
|
||||
/* Windows API reports all or nothing for cryptographic instructions. */
|
||||
const bool crypto = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0;
|
||||
cpuinfo_isa.aes = crypto;
|
||||
|
||||
+1
-1
@@ -231,7 +231,7 @@ uint32_t cpuinfo_linux_get_processor_min_frequency(uint32_t processor) {
|
||||
}
|
||||
|
||||
bool cpuinfo_linux_get_processor_core_id(uint32_t processor, uint32_t core_id_ptr[restrict static 1]) {
|
||||
char core_id_filename[PACKAGE_ID_FILENAME_SIZE];
|
||||
char core_id_filename[CORE_ID_FILENAME_SIZE];
|
||||
const int chars_formatted =
|
||||
snprintf(core_id_filename, CORE_ID_FILENAME_SIZE, CORE_ID_FILENAME_FORMAT, processor);
|
||||
if ((unsigned int)chars_formatted >= CORE_ID_FILENAME_SIZE) {
|
||||
|
||||
Vendored
+2
@@ -612,6 +612,8 @@ uint32_t cpuinfo_x86_normalize_brand_string(const char raw_name[48], char normal
|
||||
break;
|
||||
case '@':
|
||||
parser_state.frequency_separator = char_ptr;
|
||||
*char_ptr = ' ';
|
||||
break;
|
||||
case '\0':
|
||||
case '\t':
|
||||
*char_ptr = ' ';
|
||||
|
||||
Vendored
+15
-1
@@ -402,7 +402,21 @@ enum cpuinfo_uarch cpuinfo_x86_decode_uarch(
|
||||
}
|
||||
break;
|
||||
case 0x1a:
|
||||
return cpuinfo_uarch_zen5;
|
||||
switch (model_info->extended_model) {
|
||||
case 0x0: // model 00h..2Fh
|
||||
case 0x1:
|
||||
case 0x2:
|
||||
case 0x4: // model 40h..4Fh
|
||||
return cpuinfo_uarch_zen5;
|
||||
|
||||
case 0x5: // model 50h..5Fh
|
||||
case 0x8: // model 80h..AFh
|
||||
case 0x9:
|
||||
case 0xA:
|
||||
case 0xC: // model C0h..CFh
|
||||
return cpuinfo_uarch_zen6;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case cpuinfo_vendor_hygon:
|
||||
|
||||
Vendored
+8
-27
@@ -1,38 +1,19 @@
|
||||
# We need to use a custom CMakeLists for GoogleTest, because we can't compile with exceptions on.
|
||||
|
||||
add_library(gtest
|
||||
googletest/src/gtest.cc
|
||||
googletest/src/gtest-assertion-result.cc
|
||||
googletest/src/gtest-death-test.cc
|
||||
googletest/src/gtest-filepath.cc
|
||||
googletest/src/gtest-matchers.cc
|
||||
googletest/src/gtest-port.cc
|
||||
googletest/src/gtest-printers.cc
|
||||
googletest/src/gtest-test-part.cc
|
||||
googletest/src/gtest-typed-test.cc
|
||||
googletest/src/gtest-all.cc
|
||||
googlemock/src/gmock-all.cc
|
||||
googlemock/src/gmock_main.cc
|
||||
)
|
||||
target_include_directories(gtest PUBLIC
|
||||
googletest/include
|
||||
googlemock/include
|
||||
)
|
||||
target_include_directories(gtest PRIVATE
|
||||
googletest
|
||||
googletest/include
|
||||
)
|
||||
target_include_directories(gtest INTERFACE
|
||||
googletest/include
|
||||
googlemock
|
||||
)
|
||||
target_link_libraries(gtest Threads::Threads)
|
||||
set_property(TARGET gtest PROPERTY CXX_STANDARD 17)
|
||||
set_property(TARGET gtest PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_library(gtest_main
|
||||
googletest/src/gtest_main.cc
|
||||
)
|
||||
target_include_directories(gtest_main PRIVATE
|
||||
googletest
|
||||
googletest/include
|
||||
)
|
||||
target_include_directories(gtest_main INTERFACE
|
||||
googletest/include
|
||||
)
|
||||
target_link_libraries(gtest_main Threads::Threads)
|
||||
set_property(TARGET gtest_main PROPERTY CXX_STANDARD 17)
|
||||
set_property(TARGET gtest_main PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
|
||||
Vendored
+66
-59
@@ -50,7 +50,6 @@
|
||||
#include <libchdr/huffman.h>
|
||||
#include <zstd.h>
|
||||
|
||||
#include "LzmaEnc.h"
|
||||
#include "LzmaDec.h"
|
||||
#if defined(__PS3__) || defined(__PSL1GHT__)
|
||||
#define __MACTYPES__
|
||||
@@ -466,28 +465,6 @@ static void lzma_allocator_free(void* p )
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
* lzma_allocator_free_unused
|
||||
* free unused buffers only
|
||||
*-------------------------------------------------
|
||||
*/
|
||||
|
||||
static void lzma_allocator_free_unused(lzma_allocator *codec)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MAX_LZMA_ALLOCS; i++)
|
||||
{
|
||||
uint32_t *ptr = codec->allocptr[i];
|
||||
if (ptr && (*ptr & 1) == 0)
|
||||
{
|
||||
free(codec->allocptr[i]);
|
||||
codec->allocptr[i] = NULL;
|
||||
codec->allocptr2[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
* lzma_fast_alloc - fast malloc for lzma, which
|
||||
* allocates and frees memory frequently
|
||||
@@ -583,6 +560,61 @@ static void lzma_fast_free(void *p, void *address)
|
||||
***************************************************************************
|
||||
*/
|
||||
|
||||
/*-------------------------------------------------
|
||||
* lzma_compute_aligned_dictionary_size
|
||||
* Based on LzmaEncProps_Normalize, LzmaEnc_SetProps, LzmaEnc_WriteProperties.
|
||||
*-------------------------------------------------
|
||||
*/
|
||||
|
||||
static uint32_t lzma_compute_aligned_dictionary_size(uint32_t hunkbytes)
|
||||
{
|
||||
const unsigned int level = 9;
|
||||
const uint32_t reduceSize = hunkbytes;
|
||||
|
||||
uint32_t dictSize, alignedDictSize;
|
||||
|
||||
/* LzmaEncProps_Normalize */
|
||||
dictSize = level <= 4 ?
|
||||
(uint32_t)1 << (level * 2 + 16) :
|
||||
level <= sizeof(size_t) / 2 + 4 ?
|
||||
(uint32_t)1 << (level + 20) :
|
||||
(uint32_t)1 << (sizeof(size_t) / 2 + 24);
|
||||
|
||||
if (dictSize > reduceSize)
|
||||
{
|
||||
const uint32_t kReduceMin = (uint32_t)1 << 12;
|
||||
const uint32_t max = MIN(kReduceMin, reduceSize);
|
||||
|
||||
dictSize = MAX(max, dictSize);
|
||||
}
|
||||
|
||||
/* LzmaEnc_SetProps */
|
||||
dictSize = MIN((uint32_t)15 << 28, dictSize); /* kLzmaMaxHistorySize */
|
||||
|
||||
/* LzmaEnc_WriteProperties */
|
||||
/* we write aligned dictionary value to properties for lzma decoder */
|
||||
if (dictSize >= ((uint32_t)1 << 21))
|
||||
{
|
||||
const uint32_t kDictMask = ((uint32_t)1 << 20) - 1;
|
||||
|
||||
alignedDictSize = (dictSize + kDictMask) & ~kDictMask;
|
||||
alignedDictSize = MIN(dictSize, alignedDictSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int i = 11 * 2;
|
||||
|
||||
do
|
||||
{
|
||||
alignedDictSize = (uint32_t)(2 + (i & 1)) << (i >> 1);
|
||||
i++;
|
||||
}
|
||||
while (alignedDictSize < dictSize);
|
||||
}
|
||||
|
||||
return alignedDictSize;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------
|
||||
* lzma_codec_init - constructor
|
||||
*-------------------------------------------------
|
||||
@@ -590,47 +622,22 @@ static void lzma_fast_free(void *p, void *address)
|
||||
|
||||
static chd_error lzma_codec_init(void* codec, uint32_t hunkbytes)
|
||||
{
|
||||
CLzmaEncHandle enc;
|
||||
CLzmaEncProps encoder_props;
|
||||
Byte decoder_props[LZMA_PROPS_SIZE];
|
||||
SizeT props_size;
|
||||
lzma_allocator* alloc;
|
||||
lzma_codec_data* lzma_codec = (lzma_codec_data*) codec;
|
||||
lzma_allocator* alloc = &lzma_codec->allocator;
|
||||
const uint32_t alignedDictSize = lzma_compute_aligned_dictionary_size(hunkbytes);
|
||||
|
||||
unsigned int i;
|
||||
Byte decoder_props[LZMA_PROPS_SIZE];
|
||||
|
||||
decoder_props[0] = 93;
|
||||
for (i = 0; i < LZMA_PROPS_SIZE - 1; ++i)
|
||||
decoder_props[1 + i] = (alignedDictSize >> (8 * i)) & 0xFF;
|
||||
|
||||
lzma_allocator_init(alloc);
|
||||
|
||||
/* construct the decoder */
|
||||
LzmaDec_Construct(&lzma_codec->decoder);
|
||||
|
||||
/* FIXME: this code is written in a way that makes it impossible to safely upgrade the LZMA SDK
|
||||
* This code assumes that the current version of the encoder imposes the same requirements on the
|
||||
* decoder as the encoder used to produce the file. This is not necessarily true. The format
|
||||
* needs to be changed so the encoder properties are written to the file.
|
||||
|
||||
* configure the properties like the compressor did */
|
||||
LzmaEncProps_Init(&encoder_props);
|
||||
encoder_props.level = 9;
|
||||
encoder_props.reduceSize = hunkbytes;
|
||||
LzmaEncProps_Normalize(&encoder_props);
|
||||
|
||||
/* convert to decoder properties */
|
||||
alloc = &lzma_codec->allocator;
|
||||
lzma_allocator_init(alloc);
|
||||
enc = LzmaEnc_Create((ISzAlloc*)alloc);
|
||||
if (!enc)
|
||||
return CHDERR_DECOMPRESSION_ERROR;
|
||||
if (LzmaEnc_SetProps(enc, &encoder_props) != SZ_OK)
|
||||
{
|
||||
LzmaEnc_Destroy(enc, (ISzAlloc*)&alloc, (ISzAlloc*)&alloc);
|
||||
return CHDERR_DECOMPRESSION_ERROR;
|
||||
}
|
||||
props_size = sizeof(decoder_props);
|
||||
if (LzmaEnc_WriteProperties(enc, decoder_props, &props_size) != SZ_OK)
|
||||
{
|
||||
LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
|
||||
return CHDERR_DECOMPRESSION_ERROR;
|
||||
}
|
||||
LzmaEnc_Destroy(enc, (ISzAlloc*)alloc, (ISzAlloc*)alloc);
|
||||
lzma_allocator_free_unused(alloc);
|
||||
|
||||
/* do memory allocations */
|
||||
if (LzmaDec_Allocate(&lzma_codec->decoder, decoder_props, LZMA_PROPS_SIZE, (ISzAlloc*)alloc) != SZ_OK)
|
||||
return CHDERR_DECOMPRESSION_ERROR;
|
||||
|
||||
Vendored
+14
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef RA_CONSOLES_H
|
||||
#define RA_CONSOLES_H
|
||||
|
||||
/* this list should match the list in rcheevos/include/rconsoles.h */
|
||||
/* this list should match the list in rcheevos/include/rc_consoles.h */
|
||||
enum ConsoleID
|
||||
{
|
||||
UnknownConsoleID = 0,
|
||||
@@ -77,6 +77,19 @@ enum ConsoleID
|
||||
Zeebo = 70,
|
||||
Arduboy = 71,
|
||||
WASM4 = 72,
|
||||
Arcadia2001 = 73,
|
||||
IntertonVC4000 = 74,
|
||||
ElektorTVGamesComputer = 75,
|
||||
PCEngineCD = 76,
|
||||
JaguarCD = 77,
|
||||
DSi = 78,
|
||||
TI83 = 79,
|
||||
Uzebox = 80,
|
||||
FamicomDiskSystem = 81,
|
||||
|
||||
Hubs = 100,
|
||||
Events = 101,
|
||||
Standalone = 102,
|
||||
|
||||
NumConsoleIDs
|
||||
};
|
||||
|
||||
+213
-61
@@ -5,10 +5,23 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#ifndef RA_NOPROGRESS
|
||||
#include <ShlObj.h>
|
||||
#else
|
||||
#define IProgressDialog void
|
||||
#endif
|
||||
|
||||
#ifndef CCONV
|
||||
#define CCONV __cdecl
|
||||
#endif
|
||||
|
||||
#if defined(_M_X64) || defined(__amd64__)
|
||||
#define RA_X64
|
||||
#define RA_INT_DLL L"RA_Integration-x64.dll"
|
||||
#else
|
||||
#define RA_INT_DLL L"RA_Integration.dll"
|
||||
#endif
|
||||
|
||||
// Initialization
|
||||
static const char* (CCONV* _RA_IntegrationVersion)() = nullptr;
|
||||
static const char* (CCONV* _RA_HostName)() = nullptr;
|
||||
@@ -270,10 +283,58 @@ void RA_DisableHardcore()
|
||||
_RA_WarnDisableHardcore(nullptr);
|
||||
}
|
||||
|
||||
static size_t DownloadToFile(char* pData, size_t nDataSize, void* pUserData)
|
||||
#ifndef RA_NOPROGRESS
|
||||
|
||||
static void FormatByteSize(DWORD nSize, wchar_t* sBuffer, size_t nBufferSize)
|
||||
{
|
||||
if (nSize < 1024)
|
||||
{
|
||||
swprintf_s(sBuffer, nBufferSize, L"%u bytes", nSize);
|
||||
return;
|
||||
}
|
||||
|
||||
float fSize = nSize;
|
||||
fSize /= 1024.0;
|
||||
if (fSize < 1024.0)
|
||||
{
|
||||
swprintf_s(sBuffer, nBufferSize, L"%.2f KB", fSize);
|
||||
return;
|
||||
}
|
||||
|
||||
fSize /= 1024.0;
|
||||
swprintf_s(sBuffer, nBufferSize, L"%.2f MB", fSize);
|
||||
}
|
||||
|
||||
static void SetProgressMessage(IProgressDialog* pProgressDialog, DWORD nProgress, DWORD nMax)
|
||||
{
|
||||
wchar_t sNum[32];
|
||||
std::wstring sMessage;
|
||||
|
||||
FormatByteSize(nProgress, sNum, sizeof(sNum) / sizeof(sNum[0]));
|
||||
sMessage.append(sNum);
|
||||
sMessage.append(L" of ");
|
||||
|
||||
FormatByteSize(nMax, sNum, sizeof(sNum) / sizeof(sNum[0]));
|
||||
sMessage.append(sNum);
|
||||
|
||||
pProgressDialog->SetLine(2, sMessage.c_str(), FALSE, NULL);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static size_t DownloadToFile(char* pData, size_t nDataSize, void* pUserData, DWORD* pStatusCode)
|
||||
{
|
||||
FILE* file = (FILE*)pUserData;
|
||||
return fwrite(pData, 1, nDataSize, file);
|
||||
size_t nBytesWritten = fwrite(pData, 1, nDataSize, file);
|
||||
if (nBytesWritten != nDataSize)
|
||||
{
|
||||
std::string sMessage;
|
||||
sMessage = "Error " + std::to_string(errno) + " writing file: " + strerror(errno);
|
||||
MessageBoxA(nullptr, sMessage.c_str(), "Error", MB_OK | MB_ICONERROR);
|
||||
*pStatusCode = 0;
|
||||
}
|
||||
|
||||
return nBytesWritten;
|
||||
}
|
||||
|
||||
typedef struct DownloadBuffer
|
||||
@@ -283,7 +344,7 @@ typedef struct DownloadBuffer
|
||||
size_t nOffset;
|
||||
} DownloadBuffer;
|
||||
|
||||
static size_t DownloadToBuffer(char* pData, size_t nDataSize, void* pUserData)
|
||||
static size_t DownloadToBuffer(char* pData, size_t nDataSize, void* pUserData, DWORD* pStatusCode)
|
||||
{
|
||||
DownloadBuffer* pBuffer = (DownloadBuffer*)pUserData;
|
||||
const size_t nRemaining = pBuffer->nBufferSize - pBuffer->nOffset;
|
||||
@@ -299,10 +360,10 @@ static size_t DownloadToBuffer(char* pData, size_t nDataSize, void* pUserData)
|
||||
return nDataSize;
|
||||
}
|
||||
|
||||
typedef size_t (DownloadFunc)(char* pData, size_t nDataSize, void* pUserData);
|
||||
typedef size_t (DownloadFunc)(char* pData, size_t nDataSize, void* pUserData, DWORD* pStatusCode);
|
||||
|
||||
static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage, const char* sPostData,
|
||||
DownloadFunc fnDownload, void* pDownloadUserData, DWORD* pBytesRead, DWORD* pStatusCode)
|
||||
DownloadFunc fnDownload, void* pDownloadUserData, DWORD* pBytesRead, DWORD* pStatusCode, IProgressDialog* pProgressDialog)
|
||||
{
|
||||
BOOL bResults = FALSE, bSuccess = FALSE;
|
||||
HINTERNET hSession = nullptr, hConnect = nullptr, hRequest = nullptr;
|
||||
@@ -355,6 +416,8 @@ static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage,
|
||||
mbstowcs_s(&nTemp, wBuffer, sizeof(wBuffer) / sizeof(wBuffer[0]), sHostName, nHostnameLen);
|
||||
#else
|
||||
nTemp = mbstowcs(wBuffer, sHostName, nHostnameLen);
|
||||
if (nTemp > 0)
|
||||
wBuffer[nTemp] = '\0';
|
||||
#endif
|
||||
|
||||
if (nTemp > 0)
|
||||
@@ -373,6 +436,8 @@ static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage,
|
||||
mbstowcs_s(&nTemp, wBuffer, sizeof(wBuffer) / sizeof(wBuffer[0]), sRequestedPage, strlen(sRequestedPage) + 1);
|
||||
#else
|
||||
nTemp = mbstowcs(wBuffer, sRequestedPage, strlen(sRequestedPage) + 1);
|
||||
if (nTemp > 0)
|
||||
wBuffer[nTemp] = '\0';
|
||||
#endif
|
||||
|
||||
hRequest = WinHttpOpenRequest(hConnect,
|
||||
@@ -410,12 +475,28 @@ static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage,
|
||||
}
|
||||
else
|
||||
{
|
||||
char buffer[16384];
|
||||
const DWORD nBufferSize = 16384;
|
||||
char* pBuffer = (char*)malloc(nBufferSize);
|
||||
DWORD dwSize = sizeof(DWORD);
|
||||
WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, pStatusCode, &dwSize, WINHTTP_NO_HEADER_INDEX);
|
||||
bSuccess = (*pStatusCode == 200);
|
||||
const DWORD nDefaultTotalBytes = 3 * 1024 * 1024;
|
||||
DWORD nTotalBytes = nDefaultTotalBytes;
|
||||
|
||||
bSuccess = TRUE;
|
||||
do
|
||||
#ifndef RA_NOPROGRESS
|
||||
if (pProgressDialog)
|
||||
{
|
||||
dwSize = nBufferSize;
|
||||
if (WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_CONTENT_LENGTH, WINHTTP_HEADER_NAME_BY_INDEX, pBuffer, &dwSize, WINHTTP_NO_HEADER_INDEX))
|
||||
{
|
||||
nTotalBytes = wcstoul((const wchar_t*)pBuffer, NULL, 10);
|
||||
|
||||
SetProgressMessage(pProgressDialog, 0, nTotalBytes);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
while (bSuccess)
|
||||
{
|
||||
nBytesAvailable = 0;
|
||||
WinHttpQueryDataAvailable(hRequest, &nBytesAvailable);
|
||||
@@ -424,20 +505,17 @@ static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage,
|
||||
|
||||
do
|
||||
{
|
||||
if (nBytesAvailable > sizeof(buffer))
|
||||
nBytesToRead = sizeof(buffer);
|
||||
if (nBytesAvailable > nBufferSize)
|
||||
nBytesToRead = nBufferSize;
|
||||
else
|
||||
nBytesToRead = nBytesAvailable;
|
||||
|
||||
nBytesFetched = 0;
|
||||
if (WinHttpReadData(hRequest, buffer, nBytesToRead, &nBytesFetched))
|
||||
if (WinHttpReadData(hRequest, pBuffer, nBytesToRead, &nBytesFetched))
|
||||
{
|
||||
size_t nBytesWritten = fnDownload(buffer, nBytesFetched, pDownloadUserData);
|
||||
size_t nBytesWritten = fnDownload(pBuffer, nBytesFetched, pDownloadUserData, pStatusCode);
|
||||
if (nBytesWritten < nBytesFetched)
|
||||
{
|
||||
if (*pStatusCode == 200)
|
||||
*pStatusCode = 998;
|
||||
|
||||
bSuccess = FALSE;
|
||||
break;
|
||||
}
|
||||
@@ -453,8 +531,27 @@ static BOOL DoBlockingHttpCall(const char* sHostUrl, const char* sRequestedPage,
|
||||
bSuccess = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef RA_NOPROGRESS
|
||||
if (pProgressDialog)
|
||||
{
|
||||
if (pProgressDialog->HasUserCancelled())
|
||||
{
|
||||
bSuccess = FALSE;
|
||||
*pStatusCode = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
pProgressDialog->SetProgress(*pBytesRead, nTotalBytes);
|
||||
|
||||
if (nTotalBytes != nDefaultTotalBytes)
|
||||
SetProgressMessage(pProgressDialog, *pBytesRead, nTotalBytes);
|
||||
}
|
||||
#endif
|
||||
} while (nBytesAvailable > 0);
|
||||
} while (TRUE);
|
||||
};
|
||||
|
||||
free(pBuffer);
|
||||
}
|
||||
|
||||
WinHttpCloseHandle(hRequest);
|
||||
@@ -502,7 +599,7 @@ static BOOL DoBlockingHttpCallWithRetry(const char* sHostUrl, const char* sReque
|
||||
downloadBuffer.pBuffer = pBufferOut;
|
||||
downloadBuffer.nBufferSize = nBufferOutSize;
|
||||
|
||||
if (DoBlockingHttpCall(sHostUrl, sRequestedPage, sPostData, DownloadToBuffer, &downloadBuffer, pBytesRead, pStatusCode) != FALSE)
|
||||
if (DoBlockingHttpCall(sHostUrl, sRequestedPage, sPostData, DownloadToBuffer, &downloadBuffer, pBytesRead, pStatusCode, NULL) != FALSE)
|
||||
return TRUE;
|
||||
|
||||
if (!IsNetworkError(*pStatusCode))
|
||||
@@ -515,26 +612,54 @@ static BOOL DoBlockingHttpCallWithRetry(const char* sHostUrl, const char* sReque
|
||||
}
|
||||
|
||||
static BOOL DoBlockingHttpCallWithRetry(const char* sHostUrl, const char* sRequestedPage, const char* sPostData,
|
||||
FILE* pFile, DWORD* pBytesRead, DWORD* pStatusCode)
|
||||
FILE* pFile, DWORD* pBytesRead, DWORD* pStatusCode, const wchar_t* sMessage)
|
||||
{
|
||||
int nRetries = 4;
|
||||
do
|
||||
{
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
if (DoBlockingHttpCall(sHostUrl, sRequestedPage, sPostData, DownloadToFile, pFile, pBytesRead, pStatusCode) != FALSE)
|
||||
return TRUE;
|
||||
IProgressDialog* pProgressDialog = NULL;
|
||||
#ifndef RA_NOPROGRESS
|
||||
HRESULT hrInit = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
HRESULT hr = CoCreateInstance(CLSID_ProgressDialog, NULL, CLSCTX_INPROC_SERVER, IID_IProgressDialog, (LPVOID*)&pProgressDialog);
|
||||
|
||||
if (!IsNetworkError(*pStatusCode))
|
||||
return FALSE;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
if (sMessage)
|
||||
pProgressDialog->SetLine(1, sMessage, FALSE, NULL);
|
||||
pProgressDialog->StartProgressDialog(NULL, NULL, PROGDLG_NORMAL, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
--nRetries;
|
||||
} while (nRetries);
|
||||
BOOL success = FALSE;
|
||||
int nRetries = 4;
|
||||
do
|
||||
{
|
||||
fseek(pFile, 0, SEEK_SET);
|
||||
if (DoBlockingHttpCall(sHostUrl, sRequestedPage, sPostData, DownloadToFile, pFile, pBytesRead, pStatusCode, pProgressDialog) != FALSE)
|
||||
{
|
||||
success = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
if (!IsNetworkError(*pStatusCode))
|
||||
break;
|
||||
|
||||
--nRetries;
|
||||
} while (nRetries);
|
||||
|
||||
#ifndef RA_NOPROGRESS
|
||||
if (pProgressDialog)
|
||||
{
|
||||
pProgressDialog->StopProgressDialog();
|
||||
pProgressDialog->Release();
|
||||
}
|
||||
|
||||
if (hrInit == S_OK)
|
||||
CoUninitialize();
|
||||
#endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
#ifndef RA_UTEST
|
||||
static std::wstring GetIntegrationPath()
|
||||
static std::wstring GetIntegrationPath(const wchar_t* sFilename)
|
||||
{
|
||||
wchar_t sBuffer[2048];
|
||||
DWORD iIndex = GetModuleFileNameW(0, sBuffer, 2048);
|
||||
@@ -542,29 +667,33 @@ static std::wstring GetIntegrationPath()
|
||||
--iIndex;
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
wcscpy_s(&sBuffer[iIndex], sizeof(sBuffer)/sizeof(sBuffer[0]) - iIndex, L"RA_Integration.dll");
|
||||
wcscpy_s(&sBuffer[iIndex], sizeof(sBuffer)/sizeof(sBuffer[0]) - iIndex, sFilename);
|
||||
#else
|
||||
wcscpy(&sBuffer[iIndex], L"RA_Integration.dll");
|
||||
wcscpy(&sBuffer[iIndex], sFilename);
|
||||
#endif
|
||||
|
||||
return std::wstring(sBuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
static void FetchIntegrationFromWeb(char* sLatestVersionUrl, DWORD* pStatusCode)
|
||||
{
|
||||
DWORD nBytesRead = 0;
|
||||
const wchar_t* sDownloadFilename = L"RA_Integration.download";
|
||||
const wchar_t* sFilename = L"RA_Integration.dll";
|
||||
const wchar_t* sOldFilename = L"RA_Integration.old";
|
||||
const std::wstring sDownloadFilename = GetIntegrationPath(RA_INT_DLL ".download");
|
||||
const std::wstring sOldFilename = GetIntegrationPath(RA_INT_DLL ".old");
|
||||
const std::wstring sNewFilename = GetIntegrationPath(RA_INT_DLL);
|
||||
std::wstring sFilename = sNewFilename;
|
||||
|
||||
#ifdef RA_X64
|
||||
if (GetFileAttributesW(sFilename.c_str()) == INVALID_FILE_ATTRIBUTES)
|
||||
sFilename = GetIntegrationPath(L"RA_Integration.dll");
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||
FILE* pf;
|
||||
errno_t nErr = _wfopen_s(&pf, sDownloadFilename, L"wb");
|
||||
errno_t nErr = _wfopen_s(&pf, sDownloadFilename.c_str(), L"wb");
|
||||
#else
|
||||
FILE* pf = _wfopen(sDownloadFilename, L"wb");
|
||||
FILE* pf = _wfopen(sDownloadFilename.c_str(), L"wb");
|
||||
#endif
|
||||
|
||||
if (!pf)
|
||||
@@ -573,12 +702,13 @@ static void FetchIntegrationFromWeb(char* sLatestVersionUrl, DWORD* pStatusCode)
|
||||
wchar_t sErrBuffer[2048];
|
||||
_wcserror_s(sErrBuffer, sizeof(sErrBuffer) / sizeof(sErrBuffer[0]), nErr);
|
||||
|
||||
std::wstring sErrMsg = std::wstring(L"Unable to write ") + sOldFilename + L"\n" + sErrBuffer;
|
||||
std::wstring sErrMsg = std::wstring(L"Unable to write " RA_INT_DLL L".download\n") + sErrBuffer;
|
||||
#else
|
||||
std::wstring sErrMsg = std::wstring(L"Unable to write ") + sOldFilename + L"\n" + _wcserror(errno);
|
||||
std::wstring sErrMsg = std::wstring(L"Unable to write " RA_INT_DLL L".download\n") + _wcserror(errno);
|
||||
#endif
|
||||
|
||||
MessageBoxW(nullptr, sErrMsg.c_str(), L"Error", MB_OK | MB_ICONERROR);
|
||||
*pStatusCode = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -594,36 +724,36 @@ static void FetchIntegrationFromWeb(char* sLatestVersionUrl, DWORD* pStatusCode)
|
||||
}
|
||||
*pSplit++ = '\0';
|
||||
|
||||
if (DoBlockingHttpCallWithRetry(sLatestVersionUrl, pSplit, nullptr, pf, &nBytesRead, pStatusCode))
|
||||
if (DoBlockingHttpCallWithRetry(sLatestVersionUrl, pSplit, nullptr, pf, &nBytesRead, pStatusCode, "Downloading " RA_INT_DLL))
|
||||
{
|
||||
fclose(pf);
|
||||
|
||||
/* wait up to one second for the DLL to actually be released - sometimes it's not immediate */
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
if (GetModuleHandleW(sFilename) == nullptr)
|
||||
if (GetModuleHandleW(sFilename.c_str()) == nullptr)
|
||||
break;
|
||||
|
||||
Sleep(100);
|
||||
}
|
||||
|
||||
// delete the last old dll if it's still present
|
||||
DeleteFileW(sOldFilename);
|
||||
DeleteFileW(sOldFilename.c_str());
|
||||
|
||||
// if there's a dll present, rename it
|
||||
if (GetFileAttributesW(sFilename) != INVALID_FILE_ATTRIBUTES &&
|
||||
!MoveFileW(sFilename, sOldFilename))
|
||||
if (GetFileAttributesW(sFilename.c_str()) != INVALID_FILE_ATTRIBUTES &&
|
||||
!MoveFileW(sFilename.c_str(), sOldFilename.c_str()))
|
||||
{
|
||||
MessageBoxW(nullptr, L"Could not rename old dll", L"Error", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
// rename the download to be the dll
|
||||
else if (!MoveFileW(sDownloadFilename, sFilename))
|
||||
else if (!MoveFileW(sDownloadFilename.c_str(), sNewFilename.c_str()))
|
||||
{
|
||||
MessageBoxW(nullptr, L"Could not rename new dll", L"Error", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
|
||||
// delete the old dll
|
||||
DeleteFileW(sOldFilename);
|
||||
DeleteFileW(sOldFilename.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -631,8 +761,6 @@ static void FetchIntegrationFromWeb(char* sLatestVersionUrl, DWORD* pStatusCode)
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
|
||||
static std::string GetLastErrorAsString()
|
||||
{
|
||||
@@ -657,9 +785,15 @@ static const char* CCONV _RA_InstallIntegration()
|
||||
{
|
||||
SetErrorMode(0);
|
||||
|
||||
std::wstring sIntegrationPath = GetIntegrationPath();
|
||||
std::wstring sIntegrationPath = GetIntegrationPath(RA_INT_DLL);
|
||||
|
||||
DWORD dwAttrib = GetFileAttributesW(sIntegrationPath.c_str());
|
||||
#ifdef RA_X64
|
||||
if (dwAttrib == INVALID_FILE_ATTRIBUTES) {
|
||||
sIntegrationPath = GetIntegrationPath(L"RA_Integration.dll");
|
||||
dwAttrib = GetFileAttributesW(sIntegrationPath.c_str());
|
||||
}
|
||||
#endif
|
||||
if (dwAttrib == INVALID_FILE_ATTRIBUTES)
|
||||
return "0.0";
|
||||
|
||||
@@ -667,7 +801,23 @@ static const char* CCONV _RA_InstallIntegration()
|
||||
if (g_hRADLL == nullptr)
|
||||
{
|
||||
char buffer[1024];
|
||||
sprintf_s(buffer, 1024, "Could not load RA_Integration.dll: %d\n%s\n", ::GetLastError(), GetLastErrorAsString().c_str());
|
||||
if (::GetLastError() == ERROR_BAD_EXE_FORMAT)
|
||||
{
|
||||
#ifdef RA_X64
|
||||
sprintf_s(buffer, sizeof(buffer), "Could not load RA_Integration-x64.dll (error %d)\nAre you trying to load the 32-bit version?\n", ::GetLastError());
|
||||
#else
|
||||
sprintf_s(buffer, sizeof(buffer), "Could not load RA_Integration.dll (error %d)\nAre you trying to load the 64-bit version?\n", ::GetLastError());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef RA_X64
|
||||
sprintf_s(buffer, sizeof(buffer), "Could not load RA_Integration-x64.dll (error %d)\n%s\n", ::GetLastError(), GetLastErrorAsString().c_str());
|
||||
#else
|
||||
sprintf_s(buffer, sizeof(buffer), "Could not load RA_Integration.dll (error %d)\n%s\n", ::GetLastError(), GetLastErrorAsString().c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
MessageBoxA(nullptr, buffer, "Warning", MB_OK | MB_ICONWARNING);
|
||||
|
||||
return "0.0";
|
||||
@@ -876,7 +1026,7 @@ static void RA_InitCommon(HWND hMainHWND, int nEmulatorID, const char* sClientNa
|
||||
GetJsonField(buffer, "LatestVersion", sVersionBuffer, sizeof(sVersionBuffer));
|
||||
const unsigned long long nLatestDLLVer = ParseVersion(sVersionBuffer);
|
||||
|
||||
#if defined(_M_X64) || defined(__amd64__)
|
||||
#ifdef RA_X64
|
||||
GetJsonField(buffer, "LatestVersionUrlX64", sLatestVersionUrl, sizeof(sLatestVersionUrl));
|
||||
#else
|
||||
GetJsonField(buffer, "LatestVersionUrl", sLatestVersionUrl, sizeof(sLatestVersionUrl));
|
||||
@@ -930,16 +1080,18 @@ static void RA_InitCommon(HWND hMainHWND, int nEmulatorID, const char* sClientNa
|
||||
|
||||
if (nMBReply == IDYES)
|
||||
{
|
||||
//FetchIntegrationFromWeb(sLatestVersionUrl, &nStatusCode);
|
||||
nStatusCode = 0;
|
||||
FetchIntegrationFromWeb(sLatestVersionUrl, &nStatusCode);
|
||||
|
||||
if (nStatusCode == 200)
|
||||
nVerInstalled = ParseVersion(_RA_InstallIntegration());
|
||||
|
||||
if (nVerInstalled < nLatestDLLVer)
|
||||
if (nStatusCode != 0) // 0 indicates an error was already reported
|
||||
{
|
||||
sprintf_s(buffer, sizeof(buffer), "Failed to update toolset (status code %u).", nStatusCode);
|
||||
MessageBoxA(hMainHWND, buffer, "Error", MB_OK | MB_ICONERROR);
|
||||
if (nStatusCode == 200)
|
||||
nVerInstalled = ParseVersion(_RA_InstallIntegration());
|
||||
|
||||
if (nVerInstalled < nLatestDLLVer)
|
||||
{
|
||||
sprintf_s(buffer, sizeof(buffer), "Failed to update toolset (status code %u).", nStatusCode);
|
||||
MessageBoxA(hMainHWND, buffer, "Error", MB_OK | MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vendored
+8
@@ -1,3 +1,11 @@
|
||||
# v12.3.0
|
||||
* add rc_client_get_next_achievement_info
|
||||
* rc_client image functions will now return RC_INSUFFICENT_BUFFER instead of truncating if buffer is not large enough
|
||||
* fix race condition where rich presence from previous game may get associated to current game
|
||||
* fix rc_client_has_leaderboards returning true if the game only has hidden leaderboards
|
||||
* fix memory leak parsing large achievements
|
||||
* fix incomplete rich presence display condition affecting later display conditions
|
||||
|
||||
# v12.2.1
|
||||
* fix parsing of leaderboards with comparisons in legacy-formatted values
|
||||
* fix validation warning on long AddSource chains
|
||||
|
||||
+5
@@ -523,6 +523,11 @@ typedef struct rc_client_achievement_t {
|
||||
*/
|
||||
RC_EXPORT const rc_client_achievement_t* RC_CCONV rc_client_get_achievement_info(rc_client_t* client, uint32_t id);
|
||||
|
||||
/**
|
||||
* Gets the next achievement after a provided achievement that fits in the specified bucket. Returns NULL if none found.
|
||||
*/
|
||||
RC_EXPORT const rc_client_achievement_t * RC_CCONV rc_client_get_next_achievement_info(rc_client_t * client, const rc_client_achievement_t * achievement, int bucket);
|
||||
|
||||
/**
|
||||
* Gets the URL for the achievement image.
|
||||
* Returns RC_OK on success.
|
||||
|
||||
Vendored
+107
-17
@@ -637,7 +637,13 @@ static int rc_client_get_image_url(char buffer[], size_t buffer_size, int image_
|
||||
image_request.image_name = image_name;
|
||||
result = rc_api_init_fetch_image_request_hosted(&request, &image_request, NULL);
|
||||
if (result == RC_OK)
|
||||
snprintf(buffer, buffer_size, "%s", request.url);
|
||||
{
|
||||
const size_t len = strlen(request.url);
|
||||
if (len >= buffer_size)
|
||||
result = RC_INSUFFICIENT_BUFFER;
|
||||
else
|
||||
memcpy(buffer, request.url, len + 1);
|
||||
}
|
||||
|
||||
rc_api_destroy_request(&request);
|
||||
return result;
|
||||
@@ -898,7 +904,11 @@ int rc_client_user_get_image_url(const rc_client_user_t* user, char buffer[], si
|
||||
return RC_INVALID_STATE;
|
||||
|
||||
if (user->avatar_url) {
|
||||
snprintf(buffer, buffer_size, "%s", user->avatar_url);
|
||||
const size_t len = strlen(user->avatar_url);
|
||||
if (len >= buffer_size)
|
||||
return RC_INSUFFICIENT_BUFFER;
|
||||
|
||||
memcpy(buffer, user->avatar_url, len + 1);
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
@@ -3514,7 +3524,11 @@ int rc_client_game_get_image_url(const rc_client_game_t* game, char buffer[], si
|
||||
return RC_INVALID_STATE;
|
||||
|
||||
if (game->badge_url) {
|
||||
snprintf(buffer, buffer_size, "%s", game->badge_url);
|
||||
const size_t len = strlen(game->badge_url);
|
||||
if (len >= buffer_size)
|
||||
return RC_INSUFFICIENT_BUFFER;
|
||||
|
||||
memcpy(buffer, game->badge_url, len + 1);
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
@@ -4307,6 +4321,62 @@ const rc_client_achievement_t* rc_client_get_achievement_info(rc_client_t* clien
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const rc_client_achievement_t* rc_client_get_next_achievement_info(rc_client_t* client,
|
||||
const rc_client_achievement_t* achievement, int bucket)
|
||||
{
|
||||
const rc_client_achievement_info_t* after = (const rc_client_achievement_info_t*)achievement;
|
||||
rc_client_achievement_info_t* achievement_info;
|
||||
time_t recent_unlock_time;
|
||||
rc_client_subset_info_t* subset;
|
||||
|
||||
if (!client)
|
||||
return NULL;
|
||||
|
||||
#ifdef RC_CLIENT_SUPPORTS_EXTERNAL
|
||||
if (client->state.external_client && client->state.external_client->get_next_achievement_info)
|
||||
return client->state.external_client->get_next_achievement_info(achievement ? achievement->id : 0, bucket);
|
||||
#endif
|
||||
|
||||
if (!client->game)
|
||||
return NULL;
|
||||
|
||||
recent_unlock_time = time(NULL) - RC_CLIENT_RECENT_UNLOCK_DELAY_SECONDS;
|
||||
for (subset = client->game->subsets; subset; subset = subset->next) {
|
||||
if (subset->active && subset->public_.num_achievements > 0) {
|
||||
const rc_client_achievement_info_t* start = subset->achievements;
|
||||
const rc_client_achievement_info_t* stop = start + subset->public_.num_achievements;
|
||||
if (after == NULL || (after >= start && after <= stop)) {
|
||||
/* found a subset containing the provided achievement. look for the next
|
||||
* achievement matching the requested bucket */
|
||||
uint32_t index = after ? (uint32_t)(after - start) + 1 : 0;
|
||||
do {
|
||||
if (index >= subset->public_.num_achievements) {
|
||||
/* done with this subset. find the next active subset with achievements */
|
||||
do {
|
||||
subset = subset->next;
|
||||
if (!subset)
|
||||
return NULL;
|
||||
} while (!subset->active || subset->public_.num_achievements == 0);
|
||||
|
||||
index = 0;
|
||||
}
|
||||
|
||||
/* found an achievement. check to see if it matches the requested bucket. */
|
||||
achievement_info = &subset->achievements[index];
|
||||
rc_client_update_achievement_display_information(client, achievement_info, recent_unlock_time);
|
||||
if (achievement_info->public_.bucket == bucket)
|
||||
return &achievement_info->public_;
|
||||
|
||||
++index;
|
||||
} while (1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int rc_client_achievement_get_image_url(const rc_client_achievement_t* achievement, int state, char buffer[], size_t buffer_size)
|
||||
{
|
||||
const int image_type = (state == RC_CLIENT_ACHIEVEMENT_STATE_UNLOCKED) ?
|
||||
@@ -4316,12 +4386,20 @@ int rc_client_achievement_get_image_url(const rc_client_achievement_t* achieveme
|
||||
return rc_client_get_image_url(buffer, buffer_size, image_type, "00000");
|
||||
|
||||
if (image_type == RC_IMAGE_TYPE_ACHIEVEMENT && achievement->badge_url) {
|
||||
snprintf(buffer, buffer_size, "%s", achievement->badge_url);
|
||||
const size_t len = strlen(achievement->badge_url);
|
||||
if (len >= buffer_size)
|
||||
return RC_INSUFFICIENT_BUFFER;
|
||||
|
||||
memcpy(buffer, achievement->badge_url, len + 1);
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
if (image_type == RC_IMAGE_TYPE_ACHIEVEMENT_LOCKED && achievement->badge_locked_url) {
|
||||
snprintf(buffer, buffer_size, "%s", achievement->badge_locked_url);
|
||||
const size_t len = strlen(achievement->badge_locked_url);
|
||||
if (len >= buffer_size)
|
||||
return RC_INSUFFICIENT_BUFFER;
|
||||
|
||||
memcpy(buffer, achievement->badge_locked_url, len + 1);
|
||||
return RC_OK;
|
||||
}
|
||||
|
||||
@@ -4870,6 +4948,7 @@ int rc_client_has_leaderboards(rc_client_t* client)
|
||||
{
|
||||
rc_client_subset_info_t* subset;
|
||||
int result;
|
||||
uint32_t i;
|
||||
|
||||
if (!client)
|
||||
return 0;
|
||||
@@ -4884,17 +4963,21 @@ int rc_client_has_leaderboards(rc_client_t* client)
|
||||
|
||||
rc_mutex_lock(&client->state.mutex);
|
||||
|
||||
subset = client->game->subsets;
|
||||
result = 0;
|
||||
for (; subset; subset = subset->next)
|
||||
for (subset = client->game->subsets; subset; subset = subset->next)
|
||||
{
|
||||
if (!subset->active)
|
||||
continue;
|
||||
|
||||
if (subset->public_.num_leaderboards > 0) {
|
||||
result = 1;
|
||||
break;
|
||||
for (i = 0; i < subset->public_.num_leaderboards; ++i) {
|
||||
if (!subset->leaderboards[i].hidden) {
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
@@ -5438,6 +5521,14 @@ static void rc_client_ping(rc_client_scheduled_callback_data_t* callback_data, r
|
||||
if (client->state.frames_processed != client->state.frames_at_last_ping) {
|
||||
client->state.frames_at_last_ping = client->state.frames_processed;
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = client->user.username;
|
||||
api_params.api_token = client->user.token;
|
||||
api_params.game_id = client->game->public_.id;
|
||||
api_params.rich_presence = buffer;
|
||||
api_params.game_hash = client->game->public_.hash;
|
||||
api_params.hardcore = client->state.hardcore;
|
||||
|
||||
if (!client->callbacks.rich_presence_override ||
|
||||
!client->callbacks.rich_presence_override(client, buffer, sizeof(buffer))) {
|
||||
rc_mutex_lock(&client->state.mutex);
|
||||
@@ -5448,13 +5539,12 @@ static void rc_client_ping(rc_client_scheduled_callback_data_t* callback_data, r
|
||||
rc_mutex_unlock(&client->state.mutex);
|
||||
}
|
||||
|
||||
memset(&api_params, 0, sizeof(api_params));
|
||||
api_params.username = client->user.username;
|
||||
api_params.api_token = client->user.token;
|
||||
api_params.game_id = client->game->public_.id;
|
||||
api_params.rich_presence = buffer;
|
||||
api_params.game_hash = client->game->public_.hash;
|
||||
api_params.hardcore = client->state.hardcore;
|
||||
/* there's a miniscule chance the game will be changed out while we're waiting for the lock.
|
||||
* if that happens, discard this ping. the new game will have scheduled its own ping.
|
||||
* don't reschedule this one. */
|
||||
if (!client->game || client->game->public_.id != api_params.game_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = rc_api_init_ping_request_hosted(&request, &api_params, &client->state.host);
|
||||
if (result != RC_OK) {
|
||||
|
||||
+4
@@ -5,6 +5,8 @@
|
||||
|
||||
#include "rc_api_runtime.h"
|
||||
|
||||
#ifdef RC_CLIENT_SUPPORTS_EXTERNAL
|
||||
|
||||
#define RC_CONVERSION_FILL(obj, obj_type, src_type) memset((uint8_t*)obj + sizeof(src_type), 0, sizeof(obj_type) - sizeof(src_type))
|
||||
|
||||
/* https://media.retroachievements.org/Badge/123456_lock.png is 58 with null terminator */
|
||||
@@ -275,3 +277,5 @@ rc_client_achievement_list_t* rc_client_external_convert_v1_achievement_list(con
|
||||
|
||||
return (rc_client_achievement_list_t*)new_list;
|
||||
}
|
||||
|
||||
#endif /* RC_CLIENT_SUPPORTS_EXTERNAL */
|
||||
|
||||
+5
-1
@@ -46,6 +46,7 @@ typedef void (RC_CCONV* rc_client_external_add_game_hash_func_t)(const char* has
|
||||
struct rc_client_achievement_list_info_t;
|
||||
typedef struct rc_client_achievement_list_info_t* (RC_CCONV *rc_client_external_create_achievement_list_func_t)(int category, int grouping);
|
||||
typedef const rc_client_achievement_t* (RC_CCONV *rc_client_external_get_achievement_info_func_t)(uint32_t id);
|
||||
typedef const rc_client_achievement_t* (RC_CCONV* rc_client_external_get_next_achievement_info_func_t)(uint32_t id, int grouping);
|
||||
|
||||
/* NOTE: rc_client_external_create_leaderboard_list_func_t returns an internal wrapper structure which contains the public list
|
||||
* and a destructor function. */
|
||||
@@ -152,9 +153,12 @@ typedef struct rc_client_external_t
|
||||
/* VERSION 6 */
|
||||
rc_client_external_create_subset_list_func_t create_subset_list;
|
||||
|
||||
/* VERSION 7 */
|
||||
rc_client_external_get_next_achievement_info_func_t get_next_achievement_info;
|
||||
|
||||
} rc_client_external_t;
|
||||
|
||||
#define RC_CLIENT_EXTERNAL_VERSION 5
|
||||
#define RC_CLIENT_EXTERNAL_VERSION 7
|
||||
|
||||
void rc_client_add_game_hash(rc_client_t* client, const char* hash, uint32_t game_id);
|
||||
void rc_client_load_unknown_game(rc_client_t* client, const char* hash);
|
||||
|
||||
Vendored
+2
-2
@@ -8,8 +8,8 @@
|
||||
RC_BEGIN_C_DECLS
|
||||
|
||||
#define RCHEEVOS_VERSION_MAJOR 12
|
||||
#define RCHEEVOS_VERSION_MINOR 2
|
||||
#define RCHEEVOS_VERSION_PATCH 1
|
||||
#define RCHEEVOS_VERSION_MINOR 3
|
||||
#define RCHEEVOS_VERSION_PATCH 0
|
||||
|
||||
#define RCHEEVOS_MAKE_VERSION(major, minor, patch) (major * 1000000 + minor * 1000 + patch)
|
||||
#define RCHEEVOS_VERSION RCHEEVOS_MAKE_VERSION(RCHEEVOS_VERSION_MAJOR, RCHEEVOS_VERSION_MINOR, RCHEEVOS_VERSION_PATCH)
|
||||
|
||||
+7
@@ -134,10 +134,12 @@ static int rc_find_next_classification(const char* memaddr) {
|
||||
break;
|
||||
|
||||
default:
|
||||
rc_destroy_parse_state(&parse);
|
||||
return classification;
|
||||
}
|
||||
} while (*memaddr++ == '_');
|
||||
|
||||
rc_destroy_parse_state(&parse);
|
||||
return RC_CONDITION_CLASSIFICATION_OTHER;
|
||||
}
|
||||
|
||||
@@ -261,6 +263,11 @@ rc_condset_t* rc_parse_condset(const char** memaddr, rc_parse_state_t* parse) {
|
||||
|
||||
next = &self->conditions;
|
||||
|
||||
/* prevent bleedthrough of incomplete conditions from other groups */
|
||||
parse->addsource_oper = RC_OPERATOR_NONE;
|
||||
parse->addsource_parent.type = RC_OPERAND_NONE;
|
||||
parse->indirect_parent.type = RC_OPERAND_NONE;
|
||||
|
||||
/* each condition set has a functionally new recall accumulator */
|
||||
parse->remember.type = RC_OPERAND_NONE;
|
||||
|
||||
|
||||
+1
-1
@@ -913,7 +913,7 @@ uint32_t rc_runtime_progress_size(const rc_runtime_t* runtime, void* unused_L)
|
||||
|
||||
result = rc_runtime_progress_serialize_internal(&progress);
|
||||
if (result != RC_OK)
|
||||
return result;
|
||||
return 0;
|
||||
|
||||
return progress.offset;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODEC_AV1STD_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODEC_AV1STD_DECODE_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODEC_AV1STD_ENCODE_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODEC_H264STD_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODEC_H264STD_DECODE_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODEC_H264STD_ENCODE_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODEC_H265STD_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODEC_H265STD_DECODE_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODEC_H265STD_ENCODE_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODEC_VP9STD_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODEC_VP9STD_DECODE_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VIDEO_CODECS_COMMON_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+2
-1
@@ -44,8 +44,9 @@
|
||||
typedef VkResult(VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t *pVersion);
|
||||
// This is defined in vk_layer.h which will be found by the loader, but if an ICD is building against this
|
||||
// file directly, it won't be found.
|
||||
#ifndef PFN_GetPhysicalDeviceProcAddr
|
||||
#ifndef IS_DEFINED_PFN_GetPhysicalDeviceProcAddr
|
||||
typedef PFN_vkVoidFunction(VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char *pName);
|
||||
#define IS_DEFINED_PFN_GetPhysicalDeviceProcAddr
|
||||
#endif
|
||||
|
||||
// Typedefs for loader/ICD interface
|
||||
|
||||
+3
@@ -27,7 +27,10 @@
|
||||
#define VK_CURRENT_CHAIN_VERSION 1
|
||||
|
||||
// Typedef for use in the interfaces below
|
||||
#ifndef IS_DEFINED_PFN_GetPhysicalDeviceProcAddr
|
||||
typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName);
|
||||
#define IS_DEFINED_PFN_GetPhysicalDeviceProcAddr
|
||||
#endif
|
||||
|
||||
// Version negotiation values
|
||||
typedef enum VkNegotiateLayerStructType {
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
// File: vk_platform.h
|
||||
//
|
||||
/*
|
||||
** Copyright 2014-2025 The Khronos Group Inc.
|
||||
** Copyright 2014-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_ANDROID_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_BETA_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1192
-519
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_DIRECTFB_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_FUCHSIA_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_GGP_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_IOS_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_MACOS_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_METAL_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-63
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_OHOS_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -113,68 +113,6 @@ VKAPI_ATTR VkResult VKAPI_CALL vkCreateSurfaceOHOS(
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// VK_OHOS_native_buffer is a preprocessor guard. Do not pass it to API calls.
|
||||
#define VK_OHOS_native_buffer 1
|
||||
struct OHBufferHandle;
|
||||
#define VK_OHOS_NATIVE_BUFFER_SPEC_VERSION 1
|
||||
#define VK_OHOS_NATIVE_BUFFER_EXTENSION_NAME "VK_OHOS_native_buffer"
|
||||
|
||||
typedef enum VkSwapchainImageUsageFlagBitsOHOS {
|
||||
VK_SWAPCHAIN_IMAGE_USAGE_SHARED_BIT_OHOS = 0x00000001,
|
||||
VK_SWAPCHAIN_IMAGE_USAGE_FLAG_BITS_MAX_ENUM_OHOS = 0x7FFFFFFF
|
||||
} VkSwapchainImageUsageFlagBitsOHOS;
|
||||
typedef VkFlags VkSwapchainImageUsageFlagsOHOS;
|
||||
typedef struct VkNativeBufferOHOS {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
struct OHBufferHandle* handle;
|
||||
} VkNativeBufferOHOS;
|
||||
|
||||
typedef struct VkSwapchainImageCreateInfoOHOS {
|
||||
VkStructureType sType;
|
||||
const void* pNext;
|
||||
VkSwapchainImageUsageFlagsOHOS usage;
|
||||
} VkSwapchainImageCreateInfoOHOS;
|
||||
|
||||
typedef struct VkPhysicalDevicePresentationPropertiesOHOS {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
VkBool32 sharedImage;
|
||||
} VkPhysicalDevicePresentationPropertiesOHOS;
|
||||
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkGetSwapchainGrallocUsageOHOS)(VkDevice device, VkFormat format, VkImageUsageFlags imageUsage, uint64_t* grallocUsage);
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkAcquireImageOHOS)(VkDevice device, VkImage image, int32_t nativeFenceFd, VkSemaphore semaphore, VkFence fence);
|
||||
typedef VkResult (VKAPI_PTR *PFN_vkQueueSignalReleaseImageOHOS)(VkQueue queue, uint32_t waitSemaphoreCount, const VkSemaphore* pWaitSemaphores, VkImage image, int32_t* pNativeFenceFd);
|
||||
|
||||
#ifndef VK_NO_PROTOTYPES
|
||||
#ifndef VK_ONLY_EXPORTED_PROTOTYPES
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkGetSwapchainGrallocUsageOHOS(
|
||||
VkDevice device,
|
||||
VkFormat format,
|
||||
VkImageUsageFlags imageUsage,
|
||||
uint64_t* grallocUsage);
|
||||
#endif
|
||||
|
||||
#ifndef VK_ONLY_EXPORTED_PROTOTYPES
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkAcquireImageOHOS(
|
||||
VkDevice device,
|
||||
VkImage image,
|
||||
int32_t nativeFenceFd,
|
||||
VkSemaphore semaphore,
|
||||
VkFence fence);
|
||||
#endif
|
||||
|
||||
#ifndef VK_ONLY_EXPORTED_PROTOTYPES
|
||||
VKAPI_ATTR VkResult VKAPI_CALL vkQueueSignalReleaseImageOHOS(
|
||||
VkQueue queue,
|
||||
uint32_t waitSemaphoreCount,
|
||||
const VkSemaphore* pWaitSemaphores,
|
||||
VkImage image,
|
||||
int32_t* pNativeFenceFd);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_SCREEN_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_VI_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_WAYLAND_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_WIN32_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_XCB_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_XLIB_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
#define VULKAN_XLIB_XRANDR_H_ 1
|
||||
|
||||
/*
|
||||
** Copyright 2015-2025 The Khronos Group Inc.
|
||||
** Copyright 2015-2026 The Khronos Group Inc.
|
||||
**
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
Vendored
+108
-44
@@ -20,6 +20,11 @@ Some things that WIL includes to whet your appetite:
|
||||
- [`include/wil/registry.h`](include/wil/registry.h) ([documentation](https://github.com/microsoft/wil/wiki/Registry-Helpers)): Type-safe functions to read from, write to,
|
||||
and watch the registry. Also, registry watchers that can call a lambda function or a callback function
|
||||
you provide whenever a certain tree within the Windows registry changes.
|
||||
- [`include/wil/network.h`](include/wil/network.h): ([documentation](https://github.com/microsoft/wil/wiki/Network-Helpers)) Supports Winsock and network APIs
|
||||
by providing a header-include list which addresses the inter-header include dependendies;
|
||||
provides RAII objects for WSAStartup refcounts as well as the various addrinfo* types
|
||||
returned from the family of getaddrinfo* functions; provides a type-safe class for managing
|
||||
the entire family of sockaddr-related structures.
|
||||
- [`include/wil/result.h`](include/wil/result.h)
|
||||
([documentation](https://github.com/Microsoft/wil/wiki/Error-handling-helpers)):
|
||||
Preprocessor macros to help you check for errors from Windows API functions,
|
||||
@@ -59,70 +64,128 @@ Note that even though WIL is a header-only library, you still need to install th
|
||||
|
||||
To get started contributing to WIL, first make sure that you have:
|
||||
|
||||
* The latest version of [Visual Studio](https://visualstudio.microsoft.com/downloads/) or Build Tools for Visual Studio with the latest MSVC C++ build tools and Address Sanitizer components included.
|
||||
* The latest version of [Visual Studio](https://visualstudio.microsoft.com/downloads/) or Build Tools for Visual Studio with the latest MSVC C++
|
||||
build tools and Address Sanitizer components included. In Visual Studio Installer's Import Configuration tool, pick [.vsconfig](.vsconfig)
|
||||
to the necessary workloads installed.
|
||||
* The most recent [Windows SDK](https://developer.microsoft.com/windows/downloads/windows-sdk)
|
||||
* [Nuget](https://www.nuget.org/downloads) downloaded and added to `PATH`
|
||||
* (`winget install nuget`; see [Install NuGet client tools](https://learn.microsoft.com/nuget/install-nuget-client-tools))
|
||||
* [vcpkg](https://vcpkg.io) available on your system.
|
||||
Follow their [getting started](https://vcpkg.io/en/getting-started) guide to get set up.
|
||||
You'll need to provide the path to vcpkg when initializing with CMake by passing `-DCMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake`.
|
||||
* [Nuget](https://www.nuget.org/downloads) downloaded and added to `PATH` - see [Install NuGet client tools](https://learn.microsoft.com/nuget/install-nuget-client-tools)
|
||||
* [vcpkg](https://vcpkg.io) available on your system. Follow their [getting started](https://vcpkg.io/en/getting-started) guide to get set up. Make sure the `VCKPKG_ROOT` environment variable is set, and the path to `vcpkg.exe` is in your `%PATH%`.
|
||||
* A recent version of [Clang](http://releases.llvm.org/download.html)
|
||||
|
||||
You can install these with WinGet in a console command line:
|
||||
|
||||
```powershell
|
||||
winget install Microsoft.VisualStudio.2022.Community
|
||||
winget install Microsoft.WindowsSDK.10.0.22621
|
||||
winget install Microsoft.NuGet -e
|
||||
winget install Kitware.CMake -e
|
||||
winget install Ninja-build.Ninja -e
|
||||
|
||||
# Select "Add LLVM to the system path for all users"
|
||||
winget install -i llvm.llvm
|
||||
```
|
||||
|
||||
By default, `init.cmd` and `cmake` attempt to find vcpkg's cmake integration toolchain file on their own, by
|
||||
looking in the `VCPKG_ROOT` environment variable. After bootstrapping, you can use `setx` to have this variable
|
||||
across shell sessions. Make sure the directory containing `vcpkg.exe` is in your `PATH`.
|
||||
|
||||
If `VCPKG_ROOT` is not set you can pass its location to CMake or the `init.cmd` script with one of these:
|
||||
|
||||
* `cmake [...] --toolchain [path to vcpkg]/scripts/buildsystems/vcpkg.cmake`
|
||||
* `scripts\init.cmd [...] --vcpkg <path to vcpkg>`
|
||||
|
||||
Note that if you use the `init.cmd` script (mentioned below), this path can be specified or auto-detected if you:
|
||||
1. Manually specify the path to the root of your vcpkg clone via the `-p` or `--vcpkg` argument,
|
||||
1. Have the `VCPKG_ROOT` environment variable set to the root of your vcpkg clone.
|
||||
You can use the `setx` command to have this variable persist across shell sessions,
|
||||
1. Have the path to the root of your vcpkg clone added to your `PATH` (i.e. the path to `vcpkg.exe`), or
|
||||
1. If your vcpkg clone is located at the root of the same drive as your WIL clone (e.g. `C:\vcpkg` if your WIL clone is on the `C:` drive)
|
||||
|
||||
If you are doing any non-trivial work, also be sure to have:
|
||||
## Visual Studio 2022
|
||||
|
||||
* A recent version of [Clang](http://releases.llvm.org/download.html)
|
||||
* (`winget install -i llvm.llvm` and select `Add LLVM to the system path for all users`)
|
||||
Visual Studio 2022 has [fully integrated CMake support](https://learn.microsoft.com/cpp/build/cmake-projects-in-visual-studio). Opening
|
||||
this directory in Visual Studio 2022 uses the default "clang Debug" configurations. Other configurations for "clang Release," "msvc Debug,"
|
||||
and "msvc Release" are available in the Configuration drop-down.
|
||||
|
||||
## Initial configuration
|
||||
Use "Build > Build All" to compile all targets.
|
||||
|
||||
Once everything is installed (you'll need to restart Terminal if you updated `PATH` and don't have [this 2023 fix](https://github.com/microsoft/terminal/pull/14999)), open a VS native command window (e.g. `x64 Native Tools Command Prompt for VS 2022` \[_not_ `Developer Command Prompt for VS2022`]).
|
||||
## Visual Studio Code
|
||||
|
||||
* If you are familiar with CMake you can get started building normally.
|
||||
* Otherwise, or if you prefer to skip all of the boilerplate, you can use the `init.cmd` script in the [scripts](scripts) directory.
|
||||
For example:
|
||||
```cmd
|
||||
C:\wil> scripts\init.cmd -c clang -g ninja -b debug
|
||||
```
|
||||
You can execute `init.cmd --help` for a summary of available options.
|
||||
The `scripts/init_all.cmd` script will run the `init.cmd` script for all combinations of Clang/MSVC and Debug/RelWithDebInfo.
|
||||
Note that for either script, projects will only be generated for the architecture of the current VS command window.
|
||||
Microsoft's [CMake Tools for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cmake-tools) make working
|
||||
in VSCode easy.
|
||||
|
||||
To set up Visual Studio with IntelliSense, see below.
|
||||
If you used the `init.cmd` script, the corresponding build output directory should contain a `compile_commands.json` file that describes the commands used to compile each input file.
|
||||
Some editors such as Visual Studio Code can be configured to use this file to provide better auto-complete, tooltips, etc.
|
||||
Visual Studio Code, in particular should auto-detect the presence of this file and prompt you to use it for better IntelliSense.
|
||||
If you are not auto-prompted, this can be manually configured in the workspace's C/C++ properties under the property name `compileCommands`.
|
||||
1. Start a "Native Tools Command Prompt" (see below)
|
||||
1. Launch VS Code from the prompt, giving it the path to this repo (like `code c:\wil`)
|
||||
3. Use "CMake: Select Configure Preset" to pick `clang`, then "CMake: Select Build Preset" to pick `clang Debug`, then "CMake: Select Build Target" and pick `all`
|
||||
4. Use "CMake: Build" to compile all targets
|
||||
|
||||
### Visual Studio setup
|
||||
## Command Line
|
||||
|
||||
To generate a Visual Studio solution with IntelliSense:
|
||||
```cmd
|
||||
C:\wil> scripts\init.cmd -c msvc -g msbuild
|
||||
Once everything is installed (you'll need to restart Terminal if you updated `PATH` and don't have [this 2023 fix](https://github.com/microsoft/terminal/pull/14999)),
|
||||
open a VS native command window (e.g. `x64 Native Tools Command Prompt for VS 2022` \[_not_ `Developer Command Prompt for VS2022`]).
|
||||
|
||||
You can use a [CMake preset](./CMakePresets.json) to configure the environment:
|
||||
|
||||
```powershell
|
||||
# Configure for clang compiler, then build clang-debug
|
||||
C:\wil> cmake --preset "clang"
|
||||
C:\wil> cmake --build --preset "clang-debug"
|
||||
```
|
||||
|
||||
That will create a `.sln` file in the corresponding `build/` subdirectory (e.g. `build/msvc64debug`).
|
||||
You can open this solution in Visual Studio to develop and build, or you can invoke MSBuild directly.
|
||||
You can also use [`scripts/init.cmd`](./scripts/init.cmd) to pick the configuration:
|
||||
|
||||
> **Important!** When using MSVC as the generator, the build type (`-b` argument to `init.cmd`) is mostly ignored by Visual Studio (since you can change the build type in the IDE), however this selection may still have an impact on project generation due to logic in the CMake files.
|
||||
```cmd
|
||||
C:\wil> scripts\init.cmd -c clang -g ninja -b debug
|
||||
```
|
||||
|
||||
You can also get decent IntelliSense just by opening the repo directory in Visual Studio; VS should auto-detect CMake. You'll have to compile and run tests in a terminal window, though.
|
||||
This script supports using msbuild as the generator/build-tool (pass `-g msbuild`) and the other [`CMAKE_BUILD_TYPE` values](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html)
|
||||
(pass `-b minsizerel`). You can execute `init.cmd --help` for a summary of available options.
|
||||
|
||||
The `scripts/init_all.cmd` script will run the `init.cmd` script for all combinations of Clang/MSVC and Debug/RelWithDebInfo.
|
||||
|
||||
> **Note**: For either script, projects will only be generated for the architecture of the current VS command window.
|
||||
|
||||
## Inner loop
|
||||
|
||||
The scripts use a common directory pattern of `build/$(compiler)$(arch)$(type)` for the build output root. E.g. `build/clang64debug` when using Clang as the compiler, x64 as the architecture, and Debug as the build type. It is this directory where you will want to build from.
|
||||
In Visual Studio 2022, select a startup item (e.g. `witest.exe`) and use "Debug > Start Debugging". Targets will be
|
||||
rebuilt as needed. Use "Build > Rebuild All" to rebuild all tests. Use the Visual Studio Test Explorer to run the
|
||||
tests.
|
||||
|
||||
For example, if you initialized using the command above (`scripts\init.cmd -c clang -g ninja -b debug`), you can build the tests like so:
|
||||
```cmd
|
||||
C:\wil\build\clang64debug> ninja
|
||||
In VS Code, use "CMake: Set Launch/Debug Target" and select a target (e.g. `witest.exe`). Use "CMake: Debug" (default keybind `Shift-F5`)
|
||||
to run the selected test [in VS Code's debugger environment.](https://code.visualstudio.com/docs/cpp/cpp-debug).
|
||||
Switch to [VS Code's "testing" tab,](https://code.visualstudio.com/docs/debugtest/testing) and click the "Run Tests"
|
||||
option.
|
||||
|
||||
For command-line CMake (configured with `cmake --preset ...`) build use, some examples:
|
||||
```powershell
|
||||
# Build for MSVC release, all targets
|
||||
C:\wil> cmake --build --preset "msvc-release"
|
||||
|
||||
# Build only one test (e.g. for improved compile times)
|
||||
C:\wil> cmake --build --preset "msvc-release" --target "witest.noexcept"
|
||||
|
||||
# Clean outputs, then build one target
|
||||
C:\wil> cmake --build --preset "msvc-release" --clean-first --target "witest"
|
||||
|
||||
# Run tests
|
||||
C:\wil> ctest --preset "msvc-release"
|
||||
```
|
||||
Or, if you want to only build a single test (e.g. for improved compile times):
|
||||
```cmd
|
||||
C:\wil\build\clang64debug> ninja witest.noexcept
|
||||
|
||||
For command-line Ninja (configured with `init.cmd -c clang -b debug`) build use, some examples:
|
||||
```powershell
|
||||
# Build all tests
|
||||
C:\wil> ninja -C build\clang-x64-debug
|
||||
|
||||
# Build only one test
|
||||
C:\wil> ninja -C build\clang-x64-debug witest
|
||||
|
||||
# Clean outputs, then build one target
|
||||
C:\wil> ninja -C build\clang-x64-debug -j 0 clean witest.app
|
||||
|
||||
# Run the tests (PowerShell)
|
||||
C:\wil> Get-ChildItem -Recurse -File build\clang-x64-debug\witest*.exe | %{ Write-Host $_ ; & $_ }
|
||||
|
||||
# Run the tests (cmd)
|
||||
C:\wil> for /F %f IN ('dir /s /b build\clang\tests\witest*.exe') do %f
|
||||
```
|
||||
|
||||
The output is a number of test executables. If you used the initialization script(s) mentioned above, or if you followed
|
||||
@@ -131,6 +194,9 @@ which will execute any test executables that have been built, erroring out - and
|
||||
fails. Note that MSBuild will modify the output directory names, so this script is only compatible with using Ninja as the
|
||||
generator.
|
||||
|
||||
> **Note:** The `witest.app` test is significantly slower than the other tests. You can use Test Explorer or the Testing
|
||||
> tab to hide it while doing quick validation.
|
||||
|
||||
## Build everything
|
||||
|
||||
If you are at the tail end of of a change, you can execute the following to get a wide range of coverage:
|
||||
@@ -139,8 +205,6 @@ C:\wil> scripts\init_all.cmd
|
||||
C:\wil> scripts\build_all.cmd
|
||||
C:\wil> scripts\runtests.cmd
|
||||
```
|
||||
Note that this will only test for the architecture that corresponds to the command window you opened. You will want to
|
||||
repeat this process for the other architecture (e.g. by using the `x86 Native Tools Command Prompt for VS 2022` in addition to `x64`).
|
||||
|
||||
## Formatting
|
||||
|
||||
@@ -204,7 +268,7 @@ C:\wil> scripts\run-clang-format.cmd
|
||||
```
|
||||
Additionally, we've added a build target that will invoke this script, named `format`:
|
||||
```cmd
|
||||
C:\wil\build\clang64debug> ninja format
|
||||
C:\wil\build\clang-x64-debug> ninja format
|
||||
```
|
||||
Please note that this all assumes that your Visual Studio installation is up to date.
|
||||
If it's out of date, code unrelated to your changes may get formatted unexpectedly.
|
||||
|
||||
+48
-5
@@ -282,7 +282,7 @@ namespace details
|
||||
return *this;
|
||||
}
|
||||
|
||||
StoredCallContextInfo(StoredCallContextInfo const& other) WI_NOEXCEPT : m_ownsMessage(false)
|
||||
StoredCallContextInfo(StoredCallContextInfo const& other) WI_NOEXCEPT
|
||||
{
|
||||
contextId = other.contextId;
|
||||
contextName = other.contextName;
|
||||
@@ -296,7 +296,7 @@ namespace details
|
||||
}
|
||||
}
|
||||
|
||||
StoredCallContextInfo(_In_opt_ PCSTR staticContextName) WI_NOEXCEPT : m_ownsMessage(false)
|
||||
StoredCallContextInfo(_In_opt_ PCSTR staticContextName) WI_NOEXCEPT
|
||||
{
|
||||
contextId = 0;
|
||||
contextName = staticContextName;
|
||||
@@ -365,7 +365,7 @@ namespace details
|
||||
}
|
||||
}
|
||||
|
||||
bool m_ownsMessage;
|
||||
bool m_ownsMessage{false};
|
||||
};
|
||||
|
||||
template <typename TActivity>
|
||||
@@ -530,8 +530,8 @@ protected:
|
||||
static bool WasAlreadyReportedToTelemetry(long failureId) WI_NOEXCEPT
|
||||
{
|
||||
static long volatile s_lastFailureSeen = -1;
|
||||
auto wasSeen = (s_lastFailureSeen == failureId);
|
||||
s_lastFailureSeen = failureId;
|
||||
long oldValue = InterlockedExchange(&s_lastFailureSeen, failureId);
|
||||
auto wasSeen = (oldValue == failureId);
|
||||
return wasSeen;
|
||||
}
|
||||
|
||||
@@ -4731,6 +4731,49 @@ WIL_WARN_DEPRECATED_1612_PRAGMA("IMPLEMENT_TRACELOGGING_CLASS")
|
||||
varName8, \
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_CRITICAL_DATA), \
|
||||
TelemetryPrivacyDataTag(PrivacyTag))
|
||||
#define DEFINE_COMPLIANT_CRITICAL_DATA_EVENT_PARAM9( \
|
||||
EventId, \
|
||||
PrivacyTag, \
|
||||
VarType1, \
|
||||
varName1, \
|
||||
VarType2, \
|
||||
varName2, \
|
||||
VarType3, \
|
||||
varName3, \
|
||||
VarType4, \
|
||||
varName4, \
|
||||
VarType5, \
|
||||
varName5, \
|
||||
VarType6, \
|
||||
varName6, \
|
||||
VarType7, \
|
||||
varName7, \
|
||||
VarType8, \
|
||||
varName8, \
|
||||
VarType9, \
|
||||
varName9) \
|
||||
DEFINE_TRACELOGGING_EVENT_PARAM9( \
|
||||
EventId, \
|
||||
VarType1, \
|
||||
varName1, \
|
||||
VarType2, \
|
||||
varName2, \
|
||||
VarType3, \
|
||||
varName3, \
|
||||
VarType4, \
|
||||
varName4, \
|
||||
VarType5, \
|
||||
varName5, \
|
||||
VarType6, \
|
||||
varName6, \
|
||||
VarType7, \
|
||||
varName7, \
|
||||
VarType8, \
|
||||
varName8, \
|
||||
VarType9, \
|
||||
varName9, \
|
||||
TraceLoggingKeyword(MICROSOFT_KEYWORD_CRITICAL_DATA), \
|
||||
TelemetryPrivacyDataTag(PrivacyTag))
|
||||
|
||||
#define DEFINE_COMPLIANT_CRITICAL_DATA_EVENT_CV(EventId, PrivacyTag) \
|
||||
DEFINE_TRACELOGGING_EVENT_CV(EventId, TraceLoggingKeyword(MICROSOFT_KEYWORD_CRITICAL_DATA), TelemetryPrivacyDataTag(PrivacyTag))
|
||||
|
||||
Vendored
+73
-75
@@ -65,20 +65,20 @@ namespace details
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
inline static HRESULT query(_In_ T* ptr, REFIID riid, _COM_Outptr_ void** result)
|
||||
static HRESULT query(_In_ T* ptr, REFIID riid, _COM_Outptr_ void** result)
|
||||
{
|
||||
return ptr->QueryInterface(riid, result);
|
||||
}
|
||||
|
||||
template <typename T, typename TResult>
|
||||
inline static HRESULT query(_In_ T* ptr, _COM_Outptr_ TResult** result)
|
||||
static HRESULT query(_In_ T* ptr, _COM_Outptr_ TResult** result)
|
||||
{
|
||||
return query_dispatch(ptr, typename details::is_com_convertible<T*, TResult*>::type(), result);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T, typename TResult>
|
||||
inline static HRESULT query_dispatch(_In_ T* ptr, wistd::true_type, _COM_Outptr_ TResult** result) // convertible
|
||||
static HRESULT query_dispatch(_In_ T* ptr, wistd::true_type, _COM_Outptr_ TResult** result) // convertible
|
||||
{
|
||||
*result = ptr;
|
||||
(*result)->AddRef();
|
||||
@@ -86,7 +86,7 @@ namespace details
|
||||
}
|
||||
|
||||
template <typename T, typename TResult>
|
||||
inline static HRESULT query_dispatch(_In_ T* ptr, wistd::false_type, _COM_Outptr_ TResult** result) // not convertible
|
||||
static HRESULT query_dispatch(_In_ T* ptr, wistd::false_type, _COM_Outptr_ TResult** result) // not convertible
|
||||
{
|
||||
auto hr = ptr->QueryInterface(IID_PPV_ARGS(result));
|
||||
__analysis_assume(SUCCEEDED(hr) || (*result == nullptr));
|
||||
@@ -103,7 +103,7 @@ namespace details
|
||||
class weak_query_policy
|
||||
{
|
||||
public:
|
||||
inline static HRESULT query(_In_ IWeakReference* ptr, REFIID riid, _COM_Outptr_ void** result)
|
||||
static HRESULT query(_In_ IWeakReference* ptr, REFIID riid, _COM_Outptr_ void** result)
|
||||
{
|
||||
WI_ASSERT_MSG(riid != __uuidof(IWeakReference), "Cannot resolve a weak reference to IWeakReference");
|
||||
*result = nullptr;
|
||||
@@ -125,7 +125,7 @@ namespace details
|
||||
}
|
||||
|
||||
template <typename TResult>
|
||||
inline static HRESULT query(_In_ IWeakReference* ptr, _COM_Outptr_ TResult** result)
|
||||
static HRESULT query(_In_ IWeakReference* ptr, _COM_Outptr_ TResult** result)
|
||||
{
|
||||
static_assert(!wistd::is_same<IWeakReference, TResult>::value, "Cannot resolve a weak reference to IWeakReference");
|
||||
return query_dispatch(ptr, wistd::is_base_of<IInspectable, TResult>(), result);
|
||||
@@ -161,7 +161,7 @@ namespace details
|
||||
class agile_query_policy
|
||||
{
|
||||
public:
|
||||
inline static HRESULT query(_In_ IAgileReference* ptr, REFIID riid, _COM_Outptr_ void** result)
|
||||
static HRESULT query(_In_ IAgileReference* ptr, REFIID riid, _COM_Outptr_ void** result) WI_NOEXCEPT
|
||||
{
|
||||
WI_ASSERT_MSG(riid != __uuidof(IAgileReference), "Cannot resolve a agile reference to IAgileReference");
|
||||
auto hr = ptr->Resolve(riid, result);
|
||||
@@ -170,7 +170,7 @@ namespace details
|
||||
}
|
||||
|
||||
template <typename TResult>
|
||||
static HRESULT query(_In_ IAgileReference* ptr, _COM_Outptr_ TResult** result)
|
||||
static HRESULT query(_In_ IAgileReference* ptr, _COM_Outptr_ TResult** result) WI_NOEXCEPT
|
||||
{
|
||||
static_assert(!wistd::is_same<IAgileReference, TResult>::value, "Cannot resolve a agile reference to IAgileReference");
|
||||
return query(ptr, __uuidof(TResult), reinterpret_cast<void**>(result));
|
||||
@@ -294,14 +294,14 @@ public:
|
||||
//! Assign a like `com_ptr_t` (releases current pointer, copies and AddRef's the parameter).
|
||||
com_ptr_t& operator=(const com_ptr_t& other) WI_NOEXCEPT
|
||||
{
|
||||
return operator=(other.get());
|
||||
return operator=(other.get()); // NOLINT(misc-unconventional-assign-operator): Can't see through function call
|
||||
}
|
||||
|
||||
//! Assign a convertible `com_ptr_t` (releases current pointer, copies and AddRef's the parameter).
|
||||
template <class U, typename err, class = wistd::enable_if_t<__is_convertible_to(U*, pointer)>>
|
||||
com_ptr_t& operator=(const com_ptr_t<U, err>& other) WI_NOEXCEPT
|
||||
{
|
||||
return operator=(static_cast<pointer>(other.get()));
|
||||
return operator=(static_cast<pointer>(other.get())); // NOLINT(misc-unconventional-assign-operator): Can't see through function call
|
||||
}
|
||||
|
||||
//! Move assign from a like `com_ptr_t` (releases current pointer, avoids AddRef/Release by moving the parameter).
|
||||
@@ -488,7 +488,7 @@ public:
|
||||
//! `com_ptr_t` type will be @ref com_ptr or @ref com_ptr_failfast (matching the error handling form of the
|
||||
//! pointer being queried (exception based or fail-fast).
|
||||
template <class U>
|
||||
WI_NODISCARD inline com_ptr_t<U, err_policy> query() const
|
||||
WI_NODISCARD com_ptr_t<U, err_policy> query() const
|
||||
{
|
||||
static_assert(wistd::is_same<void, result>::value, "query requires exceptions or fail fast; use try_query or query_to");
|
||||
return com_ptr_t<U, err_policy>(m_ptr, details::tag_com_query());
|
||||
@@ -617,7 +617,7 @@ public:
|
||||
//! not supported. The returned `com_ptr_t` will have the same error handling policy (exceptions, failfast or
|
||||
//! error codes) as the pointer being queried.
|
||||
template <class U>
|
||||
WI_NODISCARD inline com_ptr_t<U, err_policy> try_query() const
|
||||
WI_NODISCARD com_ptr_t<U, err_policy> try_query() const
|
||||
{
|
||||
return com_ptr_t<U, err_policy>(m_ptr, details::tag_try_com_query());
|
||||
}
|
||||
@@ -696,7 +696,7 @@ public:
|
||||
//! null. The returned `com_ptr_t` type will be @ref com_ptr or @ref com_ptr_failfast (matching the error handling
|
||||
//! form of the pointer being queried (exception based or fail-fast).
|
||||
template <class U>
|
||||
WI_NODISCARD inline com_ptr_t<U, err_policy> copy() const
|
||||
WI_NODISCARD com_ptr_t<U, err_policy> copy() const
|
||||
{
|
||||
static_assert(wistd::is_same<void, result>::value, "copy requires exceptions or fail fast; use the try_copy or copy_to method");
|
||||
return com_ptr_t<U, err_policy>(m_ptr, details::tag_com_copy());
|
||||
@@ -790,7 +790,7 @@ public:
|
||||
//! not supported or the pointer being queried is null. The returned `com_ptr_t` will have the same error
|
||||
//! handling policy (exceptions, failfast or error codes) as the pointer being queried.
|
||||
template <class U>
|
||||
WI_NODISCARD inline com_ptr_t<U, err_policy> try_copy() const
|
||||
WI_NODISCARD com_ptr_t<U, err_policy> try_copy() const
|
||||
{
|
||||
return com_ptr_t<U, err_policy>(m_ptr, details::tag_try_com_copy());
|
||||
}
|
||||
@@ -805,7 +805,7 @@ public:
|
||||
//! not specify the type directly to the template.
|
||||
//! @return A `bool` indicating `true` of the query was successful (the returned parameter is non-null).
|
||||
template <class U>
|
||||
_Success_return_ bool try_copy_to(_COM_Outptr_result_maybenull_ U** ptrResult) const
|
||||
_Success_return_ bool try_copy_to(_COM_Outptr_result_maybenull_ U** ptrResult) const WI_NOEXCEPT
|
||||
{
|
||||
if (m_ptr)
|
||||
{
|
||||
@@ -826,7 +826,7 @@ public:
|
||||
//! on failure or if the source pointer being queried is null.
|
||||
//! @return A `bool` indicating `true` of the query was successful (the returned parameter is non-null). Querying
|
||||
//! a null pointer will return `false` with a null result.
|
||||
_Success_return_ bool try_copy_to(REFIID riid, _COM_Outptr_result_maybenull_ void** ptrResult) const
|
||||
_Success_return_ bool try_copy_to(REFIID riid, _COM_Outptr_result_maybenull_ void** ptrResult) const WI_NOEXCEPT
|
||||
{
|
||||
if (m_ptr)
|
||||
{
|
||||
@@ -842,33 +842,33 @@ public:
|
||||
|
||||
//! Copy construct from a compatible WRL ComPtr<T>.
|
||||
template <class U, class = wistd::enable_if_t<__is_convertible_to(U*, pointer)>>
|
||||
com_ptr_t(const Microsoft::WRL::ComPtr<U>& other) WI_NOEXCEPT : com_ptr_t(static_cast<pointer>(other.Get()))
|
||||
com_ptr_t(const ::Microsoft::WRL::ComPtr<U>& other) WI_NOEXCEPT : com_ptr_t(static_cast<pointer>(other.Get()))
|
||||
{
|
||||
}
|
||||
|
||||
//! Move construct from a compatible WRL ComPtr<T>.
|
||||
template <class U, class = wistd::enable_if_t<__is_convertible_to(U*, pointer)>>
|
||||
com_ptr_t(Microsoft::WRL::ComPtr<U>&& other) WI_NOEXCEPT : m_ptr(other.Detach())
|
||||
com_ptr_t(::Microsoft::WRL::ComPtr<U>&& other) WI_NOEXCEPT : m_ptr(other.Detach())
|
||||
{
|
||||
}
|
||||
|
||||
//! Assign from a compatible WRL ComPtr<T>.
|
||||
template <class U, class = wistd::enable_if_t<__is_convertible_to(U*, pointer)>>
|
||||
com_ptr_t& operator=(const Microsoft::WRL::ComPtr<U>& other) WI_NOEXCEPT
|
||||
com_ptr_t& operator=(const ::Microsoft::WRL::ComPtr<U>& other) WI_NOEXCEPT
|
||||
{
|
||||
return operator=(static_cast<pointer>(other.Get()));
|
||||
return operator=(static_cast<pointer>(other.Get())); // NOLINT(misc-unconventional-assign-operator): Can't see through function call
|
||||
}
|
||||
|
||||
//! Move assign from a compatible WRL ComPtr<T>.
|
||||
template <class U, class = wistd::enable_if_t<__is_convertible_to(U*, pointer)>>
|
||||
com_ptr_t& operator=(Microsoft::WRL::ComPtr<U>&& other) WI_NOEXCEPT
|
||||
com_ptr_t& operator=(::Microsoft::WRL::ComPtr<U>&& other) WI_NOEXCEPT
|
||||
{
|
||||
attach(other.Detach());
|
||||
return *this;
|
||||
}
|
||||
|
||||
//! Swap pointers with a WRL ComPtr<T> to the same interface.
|
||||
void swap(Microsoft::WRL::ComPtr<T>& other) WI_NOEXCEPT
|
||||
void swap(::Microsoft::WRL::ComPtr<T>& other) WI_NOEXCEPT
|
||||
{
|
||||
auto ptr = m_ptr;
|
||||
m_ptr = other.Detach();
|
||||
@@ -876,29 +876,28 @@ public:
|
||||
}
|
||||
|
||||
//! Swap pointers with a rvalue reference to a WRL ComPtr<T> to the same interface.
|
||||
void swap(Microsoft::WRL::ComPtr<T>&& other) WI_NOEXCEPT
|
||||
void swap(::Microsoft::WRL::ComPtr<T>&& other) WI_NOEXCEPT
|
||||
{
|
||||
swap(other);
|
||||
}
|
||||
//! @} // WRL compatibility
|
||||
|
||||
public:
|
||||
// Internal Helpers
|
||||
/// @cond
|
||||
template <class U>
|
||||
inline com_ptr_t(_In_ U* ptr, details::tag_com_query) : m_ptr(nullptr)
|
||||
com_ptr_t(_In_ U* ptr, details::tag_com_query) : m_ptr(nullptr)
|
||||
{
|
||||
err_policy::HResult(details::query_policy_t<U>::query(ptr, &m_ptr));
|
||||
}
|
||||
|
||||
template <class U>
|
||||
inline com_ptr_t(_In_ U* ptr, details::tag_try_com_query) WI_NOEXCEPT : m_ptr(nullptr)
|
||||
com_ptr_t(_In_ U* ptr, details::tag_try_com_query) WI_NOEXCEPT : m_ptr(nullptr)
|
||||
{
|
||||
details::query_policy_t<U>::query(ptr, &m_ptr);
|
||||
}
|
||||
|
||||
template <class U>
|
||||
inline com_ptr_t(_In_opt_ U* ptr, details::tag_com_copy) : m_ptr(nullptr)
|
||||
com_ptr_t(_In_opt_ U* ptr, details::tag_com_copy) : m_ptr(nullptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
@@ -907,7 +906,7 @@ public:
|
||||
}
|
||||
|
||||
template <class U>
|
||||
inline com_ptr_t(_In_opt_ U* ptr, details::tag_try_com_copy) WI_NOEXCEPT : m_ptr(nullptr)
|
||||
com_ptr_t(_In_opt_ U* ptr, details::tag_try_com_copy) WI_NOEXCEPT : m_ptr(nullptr)
|
||||
{
|
||||
if (ptr)
|
||||
{
|
||||
@@ -1030,13 +1029,13 @@ inline bool operator!=(wistd::nullptr_t, const com_ptr_t<TRight, ErrRight>& righ
|
||||
// WRL ComPtr support
|
||||
|
||||
template <typename T, typename ErrLeft>
|
||||
inline void swap(com_ptr_t<T, ErrLeft>& left, Microsoft::WRL::ComPtr<T>& right) WI_NOEXCEPT
|
||||
inline void swap(com_ptr_t<T, ErrLeft>& left, ::Microsoft::WRL::ComPtr<T>& right) WI_NOEXCEPT
|
||||
{
|
||||
left.swap(right);
|
||||
}
|
||||
|
||||
template <typename TLeft, typename ErrLeft, typename TRight>
|
||||
inline bool operator==(const com_ptr_t<TLeft, ErrLeft>& left, const Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
inline bool operator==(const com_ptr_t<TLeft, ErrLeft>& left, const ::Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
static_assert(
|
||||
__is_convertible_to(TLeft*, TRight*) || __is_convertible_to(TRight*, TLeft*),
|
||||
@@ -1045,7 +1044,7 @@ inline bool operator==(const com_ptr_t<TLeft, ErrLeft>& left, const Microsoft::W
|
||||
}
|
||||
|
||||
template <typename TLeft, typename ErrLeft, typename TRight>
|
||||
inline bool operator<(const com_ptr_t<TLeft, ErrLeft>& left, const Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
inline bool operator<(const com_ptr_t<TLeft, ErrLeft>& left, const ::Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
static_assert(
|
||||
__is_convertible_to(TLeft*, TRight*) || __is_convertible_to(TRight*, TLeft*),
|
||||
@@ -1054,37 +1053,37 @@ inline bool operator<(const com_ptr_t<TLeft, ErrLeft>& left, const Microsoft::WR
|
||||
}
|
||||
|
||||
template <typename TLeft, typename ErrLeft, typename TRight>
|
||||
inline bool operator!=(const com_ptr_t<TLeft, ErrLeft>& left, const Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
inline bool operator!=(const com_ptr_t<TLeft, ErrLeft>& left, const ::Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
return (!(left == right));
|
||||
}
|
||||
|
||||
template <typename TLeft, typename ErrLeft, typename TRight>
|
||||
inline bool operator>=(const com_ptr_t<TLeft, ErrLeft>& left, const Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
inline bool operator>=(const com_ptr_t<TLeft, ErrLeft>& left, const ::Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
return (!(left < right));
|
||||
}
|
||||
|
||||
template <typename TLeft, typename ErrLeft, typename TRight>
|
||||
inline bool operator>(const com_ptr_t<TLeft, ErrLeft>& left, const Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
inline bool operator>(const com_ptr_t<TLeft, ErrLeft>& left, const ::Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
return (right < left);
|
||||
}
|
||||
|
||||
template <typename TLeft, typename ErrLeft, typename TRight>
|
||||
inline bool operator<=(const com_ptr_t<TLeft, ErrLeft>& left, const Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
inline bool operator<=(const com_ptr_t<TLeft, ErrLeft>& left, const ::Microsoft::WRL::ComPtr<TRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
return (!(right < left));
|
||||
}
|
||||
|
||||
template <typename T, typename ErrRight>
|
||||
inline void swap(Microsoft::WRL::ComPtr<T>& left, com_ptr_t<T, ErrRight>& right) WI_NOEXCEPT
|
||||
inline void swap(::Microsoft::WRL::ComPtr<T>& left, com_ptr_t<T, ErrRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
right.swap(left);
|
||||
}
|
||||
|
||||
template <typename TLeft, typename TRight, typename ErrRight>
|
||||
inline bool operator==(const Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
inline bool operator==(const ::Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
static_assert(
|
||||
__is_convertible_to(TLeft*, TRight*) || __is_convertible_to(TRight*, TLeft*),
|
||||
@@ -1093,7 +1092,7 @@ inline bool operator==(const Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_
|
||||
}
|
||||
|
||||
template <typename TLeft, typename TRight, typename ErrRight>
|
||||
inline bool operator<(const Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
inline bool operator<(const ::Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
static_assert(
|
||||
__is_convertible_to(TLeft*, TRight*) || __is_convertible_to(TRight*, TLeft*),
|
||||
@@ -1102,25 +1101,25 @@ inline bool operator<(const Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t
|
||||
}
|
||||
|
||||
template <typename TLeft, typename TRight, typename ErrRight>
|
||||
inline bool operator!=(const Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
inline bool operator!=(const ::Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
return (!(left == right));
|
||||
}
|
||||
|
||||
template <typename TLeft, typename TRight, typename ErrRight>
|
||||
inline bool operator>=(const Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
inline bool operator>=(const ::Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
return (!(left < right));
|
||||
}
|
||||
|
||||
template <typename TLeft, typename TRight, typename ErrRight>
|
||||
inline bool operator>(const Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
inline bool operator>(const ::Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
return (right < left);
|
||||
}
|
||||
|
||||
template <typename TLeft, typename TRight, typename ErrRight>
|
||||
inline bool operator<=(const Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
inline bool operator<=(const ::Microsoft::WRL::ComPtr<TLeft>& left, const com_ptr_t<TRight, ErrRight>& right) WI_NOEXCEPT
|
||||
{
|
||||
return (!(right < left));
|
||||
}
|
||||
@@ -1224,7 +1223,7 @@ inline bool operator<=(TLeft* left, const com_ptr_t<TRight, ErrRight>& right) WI
|
||||
//! forwarding reference template that can be used as an input com pointer. That input com pointer is allowed to be any of:
|
||||
//! * Raw Pointer: `T* com_raw_ptr(T* ptr)`
|
||||
//! * Wil com_ptr: `T* com_raw_ptr(const wil::com_ptr_t<T, err>& ptr)`
|
||||
//! * WRL ComPtr: `T* com_raw_ptr(const Microsoft::WRL::ComPtr<T>& ptr)`
|
||||
//! * WRL ComPtr: `T* com_raw_ptr(const ::Microsoft::WRL::ComPtr<T>& ptr)`
|
||||
//! * C++/CX hat: `IInspectable* com_raw_ptr(Platform::Object^ ptr)`
|
||||
//!
|
||||
//! Which in turn allows code like the following to be written:
|
||||
@@ -1249,7 +1248,7 @@ T* com_raw_ptr(const wil::com_ptr_t<T, err>& ptr)
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T* com_raw_ptr(const Microsoft::WRL::ComPtr<T>& ptr)
|
||||
T* com_raw_ptr(const ::Microsoft::WRL::ComPtr<T>& ptr)
|
||||
{
|
||||
return ptr.Get();
|
||||
}
|
||||
@@ -1278,9 +1277,9 @@ inline IInspectable* com_raw_ptr(T^ ptr)
|
||||
//! }
|
||||
//! ~~~
|
||||
template <typename T>
|
||||
com_ptr<T> make_com_ptr(T* p)
|
||||
com_ptr<T> make_com_ptr(T* ptr)
|
||||
{
|
||||
return p;
|
||||
return ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1294,9 +1293,9 @@ com_ptr<T> make_com_ptr(T* p)
|
||||
//! }
|
||||
//! ~~~
|
||||
template <typename T>
|
||||
com_ptr_nothrow<T> make_com_ptr_nothrow(T* p)
|
||||
com_ptr_nothrow<T> make_com_ptr_nothrow(T* ptr)
|
||||
{
|
||||
return p;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//! Constructs a `com_ptr_failfast` from a raw pointer.
|
||||
@@ -1309,9 +1308,9 @@ com_ptr_nothrow<T> make_com_ptr_nothrow(T* p)
|
||||
//! }
|
||||
//! ~~~
|
||||
template <typename T>
|
||||
com_ptr_failfast<T> make_com_ptr_failfast(T* p)
|
||||
com_ptr_failfast<T> make_com_ptr_failfast(T* ptr)
|
||||
{
|
||||
return p;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
//! @name Stand-alone query helpers
|
||||
@@ -2135,8 +2134,8 @@ namespace details
|
||||
std::tuple<wil::com_ptr_t<Results, error_policy>...> resultTuple;
|
||||
|
||||
std::apply(
|
||||
[i = 0, &multiQis](auto&... a) mutable {
|
||||
(a.attach(reinterpret_cast<typename std::remove_reference<decltype(a)>::type::pointer>(multiQis[i++].pItf)), ...);
|
||||
[i = 0, &multiQis](auto&... ptrs) mutable {
|
||||
(ptrs.attach(reinterpret_cast<typename std::remove_reference<decltype(ptrs)>::type::pointer>(multiQis[i++].pItf)), ...);
|
||||
},
|
||||
resultTuple);
|
||||
return std::tuple<HRESULT, decltype(resultTuple)>(hr, std::move(resultTuple));
|
||||
@@ -2163,8 +2162,8 @@ namespace details
|
||||
{
|
||||
hr = multiQi->QueryMultipleInterfaces(ARRAYSIZE(multiQis), multiQis);
|
||||
std::apply(
|
||||
[i = 0, &multiQis](auto&... a) mutable {
|
||||
(a.attach(reinterpret_cast<typename std::remove_reference<decltype(a)>::type::pointer>(multiQis[i++].pItf)), ...);
|
||||
[i = 0, &multiQis](auto&... ptrs) mutable {
|
||||
(ptrs.attach(reinterpret_cast<typename std::remove_reference<decltype(ptrs)>::type::pointer>(multiQis[i++].pItf)), ...);
|
||||
},
|
||||
resultTuple);
|
||||
}
|
||||
@@ -2381,9 +2380,9 @@ RETURN_HR_IF(E_INVALIDARG, size > ULONG_MAX);
|
||||
*/
|
||||
inline HRESULT stream_size_nothrow(_In_ IStream* stream, _Out_ unsigned long long* value)
|
||||
{
|
||||
STATSTG st{};
|
||||
RETURN_IF_FAILED(stream->Stat(&st, STATFLAG_NONAME));
|
||||
*value = st.cbSize.QuadPart;
|
||||
STATSTG info{};
|
||||
RETURN_IF_FAILED(stream->Stat(&info, STATFLAG_NONAME));
|
||||
*value = info.cbSize.QuadPart;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -3207,12 +3206,14 @@ namespace details
|
||||
template <typename TStoredType, typename IEnumType>
|
||||
struct com_iterator
|
||||
{
|
||||
private:
|
||||
using TActualStoredType =
|
||||
wistd::conditional_t<wistd::is_same_v<TStoredType, void>, typename wil::details::com_enumerator_traits<IEnumType>::smart_result, TStoredType>;
|
||||
|
||||
wil::com_ptr<IEnumType> m_enum{};
|
||||
TActualStoredType m_currentValue{};
|
||||
|
||||
public:
|
||||
using smart_result = TActualStoredType;
|
||||
com_iterator(com_iterator&&) = default;
|
||||
com_iterator(com_iterator const&) = default;
|
||||
@@ -3293,7 +3294,7 @@ WI_NODISCARD auto make_range(IEnumXxx* enumPtr)
|
||||
|
||||
struct iterator_range
|
||||
{
|
||||
|
||||
private:
|
||||
static_assert(!wistd::is_same_v<TActualStoredType, void>, "You must specify a type to receive the enumerated objects.");
|
||||
|
||||
// the stored type must be constructible from the output type of the enumerator
|
||||
@@ -3301,9 +3302,11 @@ WI_NODISCARD auto make_range(IEnumXxx* enumPtr)
|
||||
wistd::is_constructible_v<TActualStoredType, typename wil::details::com_enumerator_traits<IEnumXxx>::Result>,
|
||||
"The type you specified cannot be converted to the enumerator's output type.");
|
||||
|
||||
wil::com_ptr<IEnumXxx> m_enumerator{};
|
||||
|
||||
public:
|
||||
using enumerator_type = com_iterator<TActualStoredType, IEnumXxx>;
|
||||
|
||||
wil::com_ptr<IEnumXxx> m_enumerator{};
|
||||
iterator_range(IEnumXxx* enumPtr) : m_enumerator(enumPtr)
|
||||
{
|
||||
}
|
||||
@@ -3323,10 +3326,10 @@ WI_NODISCARD auto make_range(IEnumXxx* enumPtr)
|
||||
}
|
||||
|
||||
template <typename TEnum, typename = wistd::enable_if_t<wil::details::has_next_v<TEnum*>>>
|
||||
auto make_range(const wil::com_ptr<TEnum>& e)
|
||||
auto make_range(const wil::com_ptr<TEnum>& enumerable)
|
||||
{
|
||||
using Enumerated = typename wil::details::com_enumerator_traits<TEnum>::smart_result;
|
||||
return wil::make_range<Enumerated>(e.get());
|
||||
return wil::make_range<Enumerated>(enumerable.get());
|
||||
}
|
||||
|
||||
#ifdef __IShellItemArray_INTERFACE_DEFINED__
|
||||
@@ -3387,18 +3390,13 @@ public:
|
||||
err_policy::LastErrorIfFalse(static_cast<bool>(m_timer));
|
||||
if (m_timer)
|
||||
{
|
||||
FILETIME ft = filetime::get_system_time();
|
||||
ft = filetime::add(ft, filetime::convert_msec_to_100ns(timeoutInMilliseconds));
|
||||
SetThreadpoolTimer(m_timer.get(), &ft, timeoutInMilliseconds, 0);
|
||||
FILETIME target = filetime::get_system_time();
|
||||
target = filetime::add(target, filetime::convert_msec_to_100ns(timeoutInMilliseconds));
|
||||
SetThreadpoolTimer(m_timer.get(), &target, timeoutInMilliseconds, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool timed_out() const
|
||||
{
|
||||
return m_timedOut;
|
||||
}
|
||||
|
||||
operator bool() const noexcept
|
||||
{
|
||||
// All construction calls must succeed to provide us with a non-null m_timer value.
|
||||
@@ -3418,15 +3416,15 @@ private:
|
||||
{
|
||||
// The timer is waited upon during destruction so it is safe to rely on the this pointer in context.
|
||||
com_timeout_t* self = static_cast<com_timeout_t*>(context);
|
||||
if (SUCCEEDED(CoCancelCall(self->m_threadId, 0)))
|
||||
{
|
||||
self->m_timedOut = true;
|
||||
}
|
||||
|
||||
// There may not be an in-flight call to a marshaled COM function, so this may fail. We also don't synchronize
|
||||
// with other threads, so success/failure can't reliably be communicated to the thread that owns this object, so
|
||||
// we just ignore the result.
|
||||
(void)::CoCancelCall(self->m_threadId, 0);
|
||||
}
|
||||
|
||||
wil::unique_call<decltype(&details::CoDisableCallCancellationNull), details::CoDisableCallCancellationNull, false> m_ensureDisable{};
|
||||
wil::unique_call<decltype(&details::CoDisableCallCancellationNull), details::CoDisableCallCancellationNull, false> m_ensureDisable;
|
||||
DWORD m_threadId{};
|
||||
bool m_timedOut{};
|
||||
|
||||
// The threadpool timer goes last so that it destructs first, waiting until the timer callback has completed.
|
||||
wil::unique_threadpool_timer_nocancel m_timer;
|
||||
|
||||
+45
-41
@@ -149,6 +149,7 @@ namespace details
|
||||
template <apartment_variable_leak_action leak_action = apartment_variable_leak_action::fail_fast, typename test_hook = apartment_variable_platform>
|
||||
struct apartment_variable_base
|
||||
{
|
||||
protected:
|
||||
inline static winrt::slim_mutex s_lock;
|
||||
|
||||
struct apartment_variable_storage
|
||||
@@ -169,6 +170,50 @@ namespace details
|
||||
// Apartment id -> variables storage.
|
||||
inline static wil::object_without_destructor_on_shutdown<std::unordered_map<unsigned long long, apartment_variable_storage>> s_apartmentStorage;
|
||||
|
||||
// NOTE: Requires 's_lock' to be held
|
||||
static apartment_variable_storage* get_current_apartment_variable_storage()
|
||||
{
|
||||
auto storage = s_apartmentStorage.get().find(test_hook::GetApartmentId());
|
||||
if (storage != s_apartmentStorage.get().end())
|
||||
{
|
||||
return &storage->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// NOTE: Requires 's_lock' to be held
|
||||
apartment_variable_storage* ensure_current_apartment_variables()
|
||||
{
|
||||
auto variables = get_current_apartment_variable_storage();
|
||||
if (variables)
|
||||
{
|
||||
return variables;
|
||||
}
|
||||
|
||||
struct ApartmentObserver : public winrt::implements<ApartmentObserver, IApartmentShutdown>
|
||||
{
|
||||
void STDMETHODCALLTYPE OnUninitialize(unsigned long long apartmentId) noexcept override
|
||||
{
|
||||
// This code runs at apartment rundown so be careful to avoid deadlocks by
|
||||
// extracting the variables under the lock then release them outside.
|
||||
auto variables = [apartmentId]() {
|
||||
auto lock = winrt::slim_lock_guard(s_lock);
|
||||
return s_apartmentStorage.get().extract(apartmentId);
|
||||
}();
|
||||
WI_ASSERT(variables.key() == apartmentId);
|
||||
// The system implicitly releases the shutdown observer
|
||||
// after invoking the callback and does not allow calling unregister
|
||||
// in the callback. So release the reference to the registration.
|
||||
variables.mapped().cookie.release();
|
||||
}
|
||||
};
|
||||
auto shutdownRegistration = test_hook::RegisterForApartmentShutdown(winrt::make<ApartmentObserver>().get());
|
||||
return &s_apartmentStorage.get()
|
||||
.insert({test_hook::GetApartmentId(), apartment_variable_storage(std::move(shutdownRegistration))})
|
||||
.first->second;
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr apartment_variable_base() = default;
|
||||
~apartment_variable_base()
|
||||
{
|
||||
@@ -226,47 +271,6 @@ namespace details
|
||||
return *any;
|
||||
}
|
||||
|
||||
static apartment_variable_storage* get_current_apartment_variable_storage()
|
||||
{
|
||||
auto storage = s_apartmentStorage.get().find(test_hook::GetApartmentId());
|
||||
if (storage != s_apartmentStorage.get().end())
|
||||
{
|
||||
return &storage->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
apartment_variable_storage* ensure_current_apartment_variables()
|
||||
{
|
||||
auto variables = get_current_apartment_variable_storage();
|
||||
if (variables)
|
||||
{
|
||||
return variables;
|
||||
}
|
||||
|
||||
struct ApartmentObserver : public winrt::implements<ApartmentObserver, IApartmentShutdown>
|
||||
{
|
||||
void STDMETHODCALLTYPE OnUninitialize(unsigned long long apartmentId) noexcept override
|
||||
{
|
||||
// This code runs at apartment rundown so be careful to avoid deadlocks by
|
||||
// extracting the variables under the lock then release them outside.
|
||||
auto variables = [apartmentId]() {
|
||||
auto lock = winrt::slim_lock_guard(s_lock);
|
||||
return s_apartmentStorage.get().extract(apartmentId);
|
||||
}();
|
||||
WI_ASSERT(variables.key() == apartmentId);
|
||||
// The system implicitly releases the shutdown observer
|
||||
// after invoking the callback and does not allow calling unregister
|
||||
// in the callback. So release the reference to the registration.
|
||||
variables.mapped().cookie.release();
|
||||
}
|
||||
};
|
||||
auto shutdownRegistration = test_hook::RegisterForApartmentShutdown(winrt::make<ApartmentObserver>().get());
|
||||
return &s_apartmentStorage.get()
|
||||
.insert({test_hook::GetApartmentId(), apartment_variable_storage(std::move(shutdownRegistration))})
|
||||
.first->second;
|
||||
}
|
||||
|
||||
// get current value or custom-construct one on demand
|
||||
template <typename T>
|
||||
std::any& get_or_create(any_maker<T>&& creator)
|
||||
|
||||
Vendored
+197
-23
@@ -83,8 +83,76 @@
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
/// @cond
|
||||
#if defined(__MINGW32__) && !defined(_NATIVE_WCHAR_T_DEFINED)
|
||||
using __wchar_t = wchar_t;
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
#include <sal.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#ifndef _Post_z_
|
||||
#ifdef __z
|
||||
#define _Post_z_ SAL__post SAL__valid __z
|
||||
#else
|
||||
#define _Post_z_ SAL__post SAL__valid
|
||||
#endif
|
||||
#endif
|
||||
#ifndef _Pre_maybenull_
|
||||
#define _Pre_maybenull_ SAL__pre SAL__maybenull
|
||||
#endif
|
||||
#ifndef _Translates_last_error_to_HRESULT_
|
||||
#define _Translates_last_error_to_HRESULT_
|
||||
#endif
|
||||
#ifndef _Translates_Win32_to_HRESULT_
|
||||
#define _Translates_Win32_to_HRESULT_(x)
|
||||
#endif
|
||||
#ifndef _Translates_NTSTATUS_to_HRESULT_
|
||||
#define _Translates_NTSTATUS_to_HRESULT_(x)
|
||||
#endif
|
||||
#ifndef _Pre_opt_valid_
|
||||
#define _Pre_opt_valid_ SAL__pre SAL__valid SAL__maybenull
|
||||
#endif
|
||||
#ifndef _Frees_ptr_
|
||||
#define _Frees_ptr_ __drv_freesMem(Mem)
|
||||
#endif
|
||||
#ifndef _Frees_ptr_opt_
|
||||
#define _Frees_ptr_opt_ __drv_freesMem(Mem) SAL__maybenull
|
||||
#endif
|
||||
#ifndef _Pre_valid_
|
||||
#define _Pre_valid_ SAL__pre SAL__valid
|
||||
#endif
|
||||
#ifndef _Ret_opt_bytecap_
|
||||
#define _Ret_opt_bytecap_(n)
|
||||
#endif
|
||||
extern "C"
|
||||
{
|
||||
inline void WriteRelease(long* p, long v)
|
||||
{
|
||||
__atomic_store_n(p, v, __ATOMIC_RELEASE);
|
||||
}
|
||||
inline long ReadAcquire(const long* p)
|
||||
{
|
||||
return __atomic_load_n(p, __ATOMIC_ACQUIRE);
|
||||
}
|
||||
inline long InterlockedIncrementNoFence(volatile long* ptr)
|
||||
{
|
||||
return __atomic_add_fetch(ptr, 1, __ATOMIC_RELAXED);
|
||||
}
|
||||
inline long InterlockedDecrementNoFence(volatile long* ptr)
|
||||
{
|
||||
return __atomic_sub_fetch(ptr, 1, __ATOMIC_RELAXED);
|
||||
}
|
||||
#if !__has_builtin(_ReturnAddress)
|
||||
inline void* _ReturnAddress(void)
|
||||
{
|
||||
return __builtin_return_address(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Some SAL remapping / decoration to better support Doxygen. Macros that look like function calls can
|
||||
// confuse Doxygen when they are used to decorate a function or variable. We simplify some of these to
|
||||
// basic macros without the function for common use cases.
|
||||
@@ -263,7 +331,11 @@
|
||||
#include "wistd_type_traits.h"
|
||||
|
||||
//! This macro inserts ODR violation protection; the macro allows it to be compatible with straight "C" code
|
||||
#if defined(_MSC_VER)
|
||||
#define WI_ODR_PRAGMA(NAME, TOKEN) __pragma(detect_mismatch("ODR_violation_" NAME "_mismatch", TOKEN))
|
||||
#else
|
||||
#define WI_ODR_PRAGMA(NAME, TOKEN)
|
||||
#endif
|
||||
|
||||
#ifdef WIL_KERNEL_MODE
|
||||
WI_ODR_PRAGMA("WIL_KERNEL_MODE", "1")
|
||||
@@ -398,6 +470,15 @@ check fails as opposed to the invalid parameter handler that the STL invokes. Th
|
||||
// Until we'll have C++17 enabled in our code base, we're falling back to SAL
|
||||
#define WI_NODISCARD __WI_LIBCPP_NODISCARD_ATTRIBUTE
|
||||
|
||||
#ifdef __has_cpp_attribute
|
||||
#if __has_cpp_attribute(nodiscard) >= 201907L
|
||||
#define WI_NODISCARD_REASON(x) [[nodiscard(x)]]
|
||||
#endif
|
||||
#endif
|
||||
#ifndef WI_NODISCARD_REASON
|
||||
#define WI_NODISCARD_REASON(x) WI_NODISCARD
|
||||
#endif
|
||||
|
||||
#define __R_ENABLE_IF_IS_CLASS(ptrType) wistd::enable_if_t<wistd::is_class<ptrType>::value, void*> = nullptr
|
||||
#define __R_ENABLE_IF_IS_NOT_CLASS(ptrType) wistd::enable_if_t<!wistd::is_class<ptrType>::value, void*> = nullptr
|
||||
|
||||
@@ -455,6 +536,21 @@ check fails as opposed to the invalid parameter handler that the STL invokes. Th
|
||||
//! ~~~~
|
||||
//! @{
|
||||
|
||||
namespace wil
|
||||
{
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
template <unsigned long long flag>
|
||||
struct verify_single_flag_helper
|
||||
{
|
||||
static_assert((flag != 0) && ((flag & (flag - 1)) == 0), "Single flag expected, zero or multiple flags found");
|
||||
static constexpr unsigned long long value = flag;
|
||||
};
|
||||
} // namespace details
|
||||
} // namespace wil
|
||||
/// @endcond
|
||||
|
||||
//! Returns the unsigned type of the same width and numeric value as the given enum
|
||||
#define WI_EnumValue(val) static_cast<::wil::integral_from_enum<decltype(val)>>(val)
|
||||
//! Validates that exactly ONE bit is set in compile-time constant `flag`
|
||||
@@ -560,20 +656,26 @@ The above example is used within WIL to decide whether or not the library contai
|
||||
desktop APIs. Building this functionality as `#IFDEF`s within functions would create ODR violations, whereas
|
||||
doing it with global function pointers and header initialization allows a runtime determination. */
|
||||
#define WI_HEADER_INITIALIZATION_FUNCTION(name, fn)
|
||||
#elif defined(_M_IX86)
|
||||
#elif defined(_M_IX86) || defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM) || defined(_M_ARM64)
|
||||
#if defined(_MSC_VER)
|
||||
#ifdef _M_IX86
|
||||
#define WI_HEADER_INITIALIZATION_FUNCTION(name, fn) \
|
||||
extern "C" \
|
||||
{ \
|
||||
__declspec(selectany) unsigned char g_header_init_##name = static_cast<unsigned char>(fn()); \
|
||||
} \
|
||||
__pragma(comment(linker, "/INCLUDE:_g_header_init_" #name))
|
||||
#elif defined(_M_IA64) || defined(_M_AMD64) || defined(_M_ARM) || defined(_M_ARM64)
|
||||
#else
|
||||
#define WI_HEADER_INITIALIZATION_FUNCTION(name, fn) \
|
||||
extern "C" \
|
||||
{ \
|
||||
__declspec(selectany) unsigned char g_header_init_##name = static_cast<unsigned char>(fn()); \
|
||||
} \
|
||||
__pragma(comment(linker, "/INCLUDE:g_header_init_" #name))
|
||||
#endif
|
||||
#else
|
||||
#define WI_HEADER_INITIALIZATION_FUNCTION(name, expr) inline int name##_header_init = ((expr)(), 0)
|
||||
#endif
|
||||
#else
|
||||
#error linker pragma must include g_header_init variation
|
||||
#endif
|
||||
@@ -594,6 +696,7 @@ namespace details
|
||||
class pointer_range
|
||||
{
|
||||
public:
|
||||
// NOLINTNEXTLINE(performance-unnecessary-value-param): These should be pointers
|
||||
pointer_range(T begin_, T end_) : m_begin(begin_), m_end(end_)
|
||||
{
|
||||
}
|
||||
@@ -620,6 +723,7 @@ for (auto& obj : make_range(objPointerBegin, objPointerEnd)) { }
|
||||
template <typename T>
|
||||
details::pointer_range<T> make_range(T begin, T end)
|
||||
{
|
||||
// NOLINTNEXTLINE(performance-unnecessary-value-param): These are expected to be pointers and cheap to copy
|
||||
return details::pointer_range<T>(begin, end);
|
||||
}
|
||||
|
||||
@@ -686,18 +790,6 @@ struct variadic_logical_or<false, Rest...> : variadic_logical_or<Rest...>::type
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
template <unsigned long long flag>
|
||||
struct verify_single_flag_helper
|
||||
{
|
||||
static_assert((flag != 0) && ((flag & (flag - 1)) == 0), "Single flag expected, zero or multiple flags found");
|
||||
static const unsigned long long value = flag;
|
||||
};
|
||||
} // namespace details
|
||||
/// @endcond
|
||||
|
||||
//! @defgroup typesafety Type Validation
|
||||
//! Helpers to validate variable types to prevent accidental, but allowed type conversions.
|
||||
//! These helpers are most useful when building macros that accept a particular type. Putting these functions around the types
|
||||
@@ -712,32 +804,32 @@ boolean, BOOLEAN, and classes with an explicit bool cast.
|
||||
@param val The logical bool expression
|
||||
@return A C++ bool representing the evaluation of `val`. */
|
||||
template <typename T, __R_ENABLE_IF_IS_CLASS(T)>
|
||||
_Post_satisfies_(return == static_cast<bool>(val)) inline constexpr bool verify_bool(const T& val) WI_NOEXCEPT
|
||||
_Post_satisfies_(return == static_cast<bool>(val)) constexpr bool verify_bool(const T& val) WI_NOEXCEPT
|
||||
{
|
||||
return static_cast<bool>(val);
|
||||
}
|
||||
|
||||
template <typename T, __R_ENABLE_IF_IS_NOT_CLASS(T)>
|
||||
inline constexpr bool verify_bool(T /*val*/) WI_NOEXCEPT
|
||||
constexpr bool verify_bool(T /*val*/) WI_NOEXCEPT
|
||||
{
|
||||
static_assert(!wistd::is_same<T, T>::value, "Wrong Type: bool/BOOL/BOOLEAN/boolean expected");
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == val) inline constexpr bool verify_bool<bool>(bool val) WI_NOEXCEPT
|
||||
_Post_satisfies_(return == val) constexpr bool verify_bool<bool>(bool val) WI_NOEXCEPT
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == (val != 0)) inline constexpr bool verify_bool<int>(int val) WI_NOEXCEPT
|
||||
_Post_satisfies_(return == (val != 0)) constexpr bool verify_bool<int>(int val) WI_NOEXCEPT
|
||||
{
|
||||
return (val != 0);
|
||||
}
|
||||
|
||||
template <>
|
||||
_Post_satisfies_(return == (val != 0)) inline constexpr bool verify_bool<unsigned char>(unsigned char val) WI_NOEXCEPT
|
||||
_Post_satisfies_(return == (val != 0)) constexpr bool verify_bool<unsigned char>(unsigned char val) WI_NOEXCEPT
|
||||
{
|
||||
return (val != 0);
|
||||
}
|
||||
@@ -748,7 +840,7 @@ accept any `int` value as long as that is the underlying typedef behind `BOOL`.
|
||||
@param val The Win32 BOOL returning expression
|
||||
@return A Win32 BOOL representing the evaluation of `val`. */
|
||||
template <typename T>
|
||||
_Post_satisfies_(return == val) inline constexpr int verify_BOOL(T val) WI_NOEXCEPT
|
||||
_Post_satisfies_(return == val) constexpr int verify_BOOL(T val) WI_NOEXCEPT
|
||||
{
|
||||
// Note: Written in terms of 'int' as BOOL is actually: typedef int BOOL;
|
||||
static_assert((wistd::is_same<T, int>::value), "Wrong Type: BOOL expected");
|
||||
@@ -777,7 +869,7 @@ RETURN_HR_IF(static_cast<HRESULT>(UIA_E_NOTSUPPORTED), (patternId != UIA_DragPat
|
||||
@param hr The HRESULT returning expression
|
||||
@return An HRESULT representing the evaluation of `val`. */
|
||||
template <typename T>
|
||||
_Post_satisfies_(return == hr) inline constexpr long verify_hresult(T hr) WI_NOEXCEPT
|
||||
_Post_satisfies_(return == hr) constexpr long verify_hresult(T hr) WI_NOEXCEPT
|
||||
{
|
||||
// Note: Written in terms of 'long' as HRESULT is actually: typedef _Return_type_success_(return >= 0) long HRESULT
|
||||
static_assert(wistd::is_same<T, long>::value, "Wrong Type: HRESULT expected");
|
||||
@@ -837,11 +929,11 @@ namespace details
|
||||
{
|
||||
// Use size-specific casts to avoid sign extending numbers -- avoid warning C4310: cast truncates constant value
|
||||
#define __WI_MAKE_UNSIGNED(val) \
|
||||
(__pragma(warning(push)) __pragma(warning(disable : 4310 4309))( \
|
||||
(__WI_PUSH_WARNINGS __WI_MSVC_DISABLE_WARNING(4310 4309)( \
|
||||
sizeof(val) == 1 ? static_cast<unsigned char>(val) \
|
||||
: sizeof(val) == 2 ? static_cast<unsigned short>(val) \
|
||||
: sizeof(val) == 4 ? static_cast<unsigned long>(val) \
|
||||
: static_cast<unsigned long long>(val)) __pragma(warning(pop)))
|
||||
: static_cast<unsigned long long>(val)) __WI_POP_WARNINGS)
|
||||
#define __WI_IS_UNSIGNED_SINGLE_FLAG_SET(val) ((val) && !((val) & ((val) - 1)))
|
||||
#define __WI_IS_SINGLE_FLAG_SET(val) __WI_IS_UNSIGNED_SINGLE_FLAG_SET(__WI_MAKE_UNSIGNED(val))
|
||||
|
||||
@@ -912,6 +1004,88 @@ using integral_from_enum = typename details::variable_size_mapping<T>::type;
|
||||
//! Declares a name that intentionally hides a name from an outer scope.
|
||||
//! Use this to prevent accidental use of a parameter or lambda captured variable.
|
||||
using hide_name = void(struct hidden_name);
|
||||
|
||||
/** A helper tag type used to disambiguate function overloads by assigning priority to each overload.
|
||||
This is primarily useful when using SFINAE on different properties of a type that might overlap. For example, consider
|
||||
the following code:
|
||||
~~~
|
||||
template <typename T, std::enable_if_t<condition_a<T>, int> = 0>
|
||||
void doit(const T&);
|
||||
template <typename T, std::enable_if_t<condition_b<T>, int> = 0>
|
||||
void doit(const T&);
|
||||
~~~
|
||||
If `doit` is called with a type `T` that satisfies both `condition_a<T>` and `condition_b<T>`, the code will fail to
|
||||
compile. One way to solve this issue is to change the condiiton of the second overload to
|
||||
`condition_b<T> && !condition_a<T>`, however this can get quite complicated and verbose fast. With `priority_tag`, this
|
||||
could get simplified down to:
|
||||
~~~
|
||||
template <typename T, std::enable_if_t<condition_a<T>, int> = 0>
|
||||
void doit_impl(const T&, priority_tag<1>);
|
||||
template <typename T, std::enable_if_t<condition_b<T>, int> = 0>
|
||||
void doit_impl(const T&, priority_tag<0>);
|
||||
|
||||
template <typename T>
|
||||
void doit(const T& val)
|
||||
{
|
||||
doit_impl(val, priority_tag<1>{});
|
||||
}
|
||||
~~~
|
||||
This will invoke the first overload if a type `T` satisfies both `condition_a<T>` and `condition_b<T>`.
|
||||
*/
|
||||
template <int N>
|
||||
struct priority_tag : priority_tag<N - 1>
|
||||
{
|
||||
};
|
||||
|
||||
/// @cond
|
||||
template <>
|
||||
struct priority_tag<0>
|
||||
{
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
// Helper type to determine if a type "behaves like a std::basic_string_view." Note that this type is designed to
|
||||
// match types such as std::basic_string_view, std::basic_string, and winrt::hstring while _not_ matching against
|
||||
// things like std::array or std::vector.
|
||||
template <typename T, typename CharT>
|
||||
struct is_string_view_like_t
|
||||
{
|
||||
private:
|
||||
// winrt::hstring doesn't have much to differentiate itself from std::array/std::vector apart from 'c_str' which
|
||||
// std::basic_string_view lacks. Therefore we need an "OR" condition to get the behavior we want
|
||||
template <typename U>
|
||||
static wistd::true_type has_cstr(
|
||||
U* ptr, wistd::enable_if_t<wistd::is_convertible_v<decltype(ptr->c_str()), wistd::add_const_t<CharT>*>>*);
|
||||
template <typename U>
|
||||
static wistd::false_type has_cstr(U* ptr, ...);
|
||||
|
||||
template <typename U>
|
||||
static wistd::true_type has_substr(U* ptr, wistd::enable_if_t<wistd::is_same_v<decltype(ptr->substr(0, 0)), U>>*);
|
||||
template <typename U>
|
||||
static wistd::false_type has_substr(U*, ...);
|
||||
|
||||
template <typename U>
|
||||
static wistd::true_type test(
|
||||
U* obj,
|
||||
wistd::enable_if_t<wistd::is_same_v<typename U::value_type, CharT>>*, // T::value_type == CharT
|
||||
wistd::enable_if_t<wistd::is_convertible_v<decltype(obj->size()), size_t>>*, // T::size() well formed and convertible to size_t
|
||||
wistd::enable_if_t<wistd::is_convertible_v<decltype(obj->data()), wistd::add_const_t<CharT>*>>*, // T::data() well formed and convertible to const CharT*
|
||||
wistd::enable_if_t<decltype(has_cstr<U>(nullptr, nullptr))::value || decltype(has_substr<U>(nullptr, nullptr))::value>*); // T::c_str() or T::substr() well formed
|
||||
|
||||
template <typename U>
|
||||
static wistd::false_type test(U*, ...);
|
||||
|
||||
public:
|
||||
static constexpr bool value = decltype(test<T>(nullptr, nullptr, nullptr, nullptr, nullptr))::value;
|
||||
};
|
||||
|
||||
template <typename T, typename CharT>
|
||||
constexpr bool is_string_view_like = is_string_view_like_t<T, CharT>::value;
|
||||
} // namespace details
|
||||
/// @endcond
|
||||
} // namespace wil
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
+18
-5
@@ -328,7 +328,7 @@ struct result_holder
|
||||
result_holder(result_holder const&) = delete;
|
||||
void operator=(result_holder const&) = delete;
|
||||
|
||||
~result_holder() noexcept(false)
|
||||
~result_holder() noexcept
|
||||
{
|
||||
if (restricted_error && g_pfnDestroyRestrictedErrorInformation)
|
||||
{
|
||||
@@ -342,10 +342,9 @@ struct result_holder
|
||||
result.wrap.~result_wrapper();
|
||||
break;
|
||||
case result_status::error:
|
||||
// Rethrow unobserved exception. Delete this line to
|
||||
// discard unobserved exceptions.
|
||||
if (result.error)
|
||||
std::rethrow_exception(result.error);
|
||||
// Discard unobserved exception. There is nowhere to report it,
|
||||
// and abandonment might validly happen if an exception occurs
|
||||
// before the owner of the task can await it.
|
||||
result.error.~exception_ptr();
|
||||
}
|
||||
}
|
||||
@@ -532,11 +531,25 @@ struct task_promise : promise_base<T>
|
||||
this->emplace_value(wistd::forward<U>(value));
|
||||
}
|
||||
|
||||
// Workaround a bug in MSVC where it does not properly deduce the return type.
|
||||
// Using a constraint is simpler and does not have the issue.
|
||||
#if _HAS_CXX20
|
||||
|
||||
void return_value(T const& value)
|
||||
requires(!wistd::is_reference_v<T>)
|
||||
{
|
||||
this->emplace_value(value);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
template <typename Dummy = void>
|
||||
wistd::enable_if_t<!wistd::is_reference_v<T>, Dummy> return_value(T const& value)
|
||||
{
|
||||
this->emplace_value(value);
|
||||
}
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
template <>
|
||||
|
||||
+14
-8
@@ -14,7 +14,11 @@
|
||||
#define __WIL_CPPWINRT_INCLUDED
|
||||
|
||||
#include "common.h"
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
#include <unknwn.h>
|
||||
#include <inspectable.h>
|
||||
#include <hstring.h>
|
||||
@@ -31,7 +35,7 @@ namespace wil::details
|
||||
{
|
||||
// Since the C++/WinRT version macro is a string...
|
||||
// For example: "2.0.221104.6"
|
||||
inline constexpr int version_from_string(const char* versionString)
|
||||
constexpr int version_from_string(const char* versionString)
|
||||
{
|
||||
int result = 0;
|
||||
while ((*versionString >= '0') && (*versionString <= '9'))
|
||||
@@ -43,12 +47,12 @@ inline constexpr int version_from_string(const char* versionString)
|
||||
return result;
|
||||
}
|
||||
|
||||
inline constexpr int major_version_from_string(const char* versionString)
|
||||
constexpr int major_version_from_string(const char* versionString)
|
||||
{
|
||||
return version_from_string(versionString);
|
||||
}
|
||||
|
||||
inline constexpr int minor_version_from_string(const char* versionString)
|
||||
constexpr int minor_version_from_string(const char* versionString)
|
||||
{
|
||||
int dotCount = 0;
|
||||
while ((*versionString != '\0'))
|
||||
@@ -101,10 +105,12 @@ static_assert(::wil::details::major_version_from_string(CPPWINRT_VERSION) >= 2,
|
||||
// In C++/WinRT 2.0 and beyond, this function pointer exists. In earlier versions it does not. It's much easier to avoid
|
||||
// linker errors than it is to SFINAE on variable existence, so we declare the variable here, but are careful not to
|
||||
// use it unless the version of C++/WinRT is high enough
|
||||
// NOLINTBEGIN(readability-redundant-declaration)
|
||||
extern std::int32_t(__stdcall* winrt_to_hresult_handler)(void*) noexcept;
|
||||
|
||||
// The same is true with this function pointer as well, except that the version must be 2.X or higher.
|
||||
extern void(__stdcall* winrt_throw_hresult_handler)(uint32_t, char const*, char const*, void*, winrt::hresult const) noexcept;
|
||||
// NOLINTEND(readability-redundant-declaration)
|
||||
/// @endcond
|
||||
|
||||
/// @cond
|
||||
@@ -314,9 +320,9 @@ inline ::IInspectable* com_raw_ptr(const winrt::Windows::Foundation::IInspectabl
|
||||
template <typename T>
|
||||
T convert_from_abi(::IUnknown* from)
|
||||
{
|
||||
T to{nullptr}; // `T` is a projected type.
|
||||
winrt::check_hresult(from->QueryInterface(winrt::guid_of<T>(), winrt::put_abi(to)));
|
||||
return to;
|
||||
T result{nullptr}; // `T` is a projected type.
|
||||
winrt::check_hresult(from->QueryInterface(winrt::guid_of<T>(), winrt::put_abi(result)));
|
||||
return result;
|
||||
}
|
||||
|
||||
// For obtaining an object from an interop method on the factory. Example:
|
||||
@@ -333,9 +339,9 @@ auto capture_interop(HRESULT (__stdcall Interface::*method)(InterfaceArgs...), A
|
||||
// For obtaining an object from an interop method on an instance. Example:
|
||||
// winrt::UserActivitySession session = wil::capture_interop<winrt::UserActivitySession>(activity, &IUserActivityInterop::CreateSessionForWindow, hwnd);
|
||||
template <typename WinRTResult, typename Interface, typename... InterfaceArgs, typename... Args>
|
||||
auto capture_interop(winrt::Windows::Foundation::IUnknown const& o, HRESULT (__stdcall Interface::*method)(InterfaceArgs...), Args&&... args)
|
||||
auto capture_interop(winrt::Windows::Foundation::IUnknown const& obj, HRESULT (__stdcall Interface::*method)(InterfaceArgs...), Args&&... args)
|
||||
{
|
||||
return winrt::capture<WinRTResult>(o.as<Interface>(), method, std::forward<Args>(args)...);
|
||||
return winrt::capture<WinRTResult>(obj.as<Interface>(), method, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
/** Holds a reference to the host C++/WinRT module to prevent it from being unloaded.
|
||||
|
||||
@@ -111,6 +111,89 @@ struct single_threaded_rw_property : single_threaded_property<T>
|
||||
|
||||
#endif // __WIL_CPPWINRT_AUTHORING_PROPERTIES_INCLUDED
|
||||
|
||||
#if (!defined(__WIL_CPPWINRT_AUTHORING_INCLUDED_ICLASSFACTORY) && defined(__IClassFactory_INTERFACE_DEFINED__)) || \
|
||||
defined(WIL_DOXYGEN) // class factory
|
||||
/// @cond
|
||||
#define __WIL_CPPWINRT_AUTHORING_INCLUDED_ICLASSFACTORY
|
||||
/// @endcond
|
||||
|
||||
template <typename T, typename... Rest>
|
||||
struct class_factory : winrt::implements<class_factory<T, Rest...>, IClassFactory, winrt::no_weak_ref, Rest...>
|
||||
{
|
||||
HRESULT __stdcall CreateInstance(IUnknown* outer, GUID const& iid, void** result) noexcept final
|
||||
try
|
||||
{
|
||||
*result = nullptr;
|
||||
|
||||
if (!outer)
|
||||
{
|
||||
return winrt::make_self<T>().as(iid, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
return CLASS_E_NOAGGREGATION;
|
||||
}
|
||||
}
|
||||
CATCH_RETURN()
|
||||
|
||||
HRESULT __stdcall LockServer(BOOL lock) noexcept final
|
||||
try
|
||||
{
|
||||
if (lock)
|
||||
{
|
||||
++winrt::get_module_lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
--winrt::get_module_lock();
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
CATCH_RETURN()
|
||||
};
|
||||
|
||||
#endif // !defined(__WIL_CPPWINRT_AUTHORING_INCLUDED_ICLASSFACTORY) && defined(__IClassFactory_INTERFACE_DEFINED__)
|
||||
|
||||
#if (!defined(__WIL_CPPWINRT_AUTHORING_INCLUDED_COM_SERVER) && defined(__WIL_CPPWINRT_AUTHORING_INCLUDED_ICLASSFACTORY) && defined(__WIL__COMBASEAPI_H_)) || \
|
||||
defined(WIL_DOXYGEN) // COM server
|
||||
/// @cond
|
||||
#define __WIL_CPPWINRT_AUTHORING_INCLUDED_COM_SERVER
|
||||
/// @endcond
|
||||
|
||||
template <typename T>
|
||||
WI_NODISCARD_REASON("The class is unregistered when the returned value is destructed")
|
||||
unique_com_class_object_cookie
|
||||
register_com_server(GUID const& guid, DWORD context = CLSCTX_LOCAL_SERVER, DWORD flags = REGCLS_MULTIPLEUSE)
|
||||
{
|
||||
unique_com_class_object_cookie registration;
|
||||
winrt::check_hresult(CoRegisterClassObject(
|
||||
guid, winrt::make<class_factory<T, winrt::no_module_lock>>().get(), context, flags, registration.put()));
|
||||
return registration;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
WI_NODISCARD_REASON("The classes are unregistered when the returned value is destructed")
|
||||
std::vector<unique_com_class_object_cookie> register_com_server(
|
||||
std::array<GUID, sizeof...(Ts)> const& guids, DWORD context = CLSCTX_LOCAL_SERVER, DWORD flags = REGCLS_MULTIPLEUSE)
|
||||
{
|
||||
std::vector<wil::unique_com_class_object_cookie> registrations;
|
||||
registrations.reserve(sizeof...(Ts));
|
||||
|
||||
std::size_t i = 0;
|
||||
(registrations.push_back(wil::register_com_server<Ts>(guids[i++], context, flags | REGCLS_SUSPENDED)), ...);
|
||||
|
||||
// allow the user to keep class objects suspended if they've explicitly passed REGCLS_SUSPENDED.
|
||||
if (!WI_IsFlagSet(flags, REGCLS_SUSPENDED))
|
||||
{
|
||||
winrt::check_hresult(CoResumeClassObjects());
|
||||
}
|
||||
|
||||
return registrations;
|
||||
}
|
||||
|
||||
#endif // (!defined(__WIL_CPPWINRT_AUTHORING_INCLUDED_COM_SERVER) && defined(__WIL_CPPWINRT_AUTHORING_INCLUDED_ICLASSFACTORY) && defined(__WIL__COMBASEAPI_H_))
|
||||
|
||||
#if (!defined(__WIL_CPPWINRT_AUTHORING_INCLUDED_FOUNDATION) && defined(WINRT_Windows_Foundation_H)) || \
|
||||
defined(WIL_DOXYGEN) // WinRT / XAML helpers
|
||||
/// @cond
|
||||
|
||||
+21
-2
@@ -977,7 +977,21 @@ namespace details
|
||||
{
|
||||
*result = nullptr;
|
||||
|
||||
wistd::unique_ptr<char[]> resultHolder(new (std::nothrow) char[allocationSize]);
|
||||
// NOTE: We need to use '::operator new' here because we return as 'unique_ptr<T>' instead of 'unique_ptr<T[]>'
|
||||
// and 'delete' is incompatible with 'new[]' (say, if we allocate an array of bytes with 'char[]'). Note that it
|
||||
// _is_ valid to allocate with '::operator new' and deallocate with 'delete ptr' so long as the type of 'ptr'
|
||||
// does not have class-specific allocation functions and 'ptr' points to an object of the specified type.
|
||||
|
||||
// default_delete does not handle pointer-to-void
|
||||
struct void_deleter
|
||||
{
|
||||
void operator()(void* ptr) WI_NOEXCEPT
|
||||
{
|
||||
::operator delete(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
wistd::unique_ptr<void, void_deleter> resultHolder(::operator new(allocationSize, std::nothrow));
|
||||
RETURN_IF_NULL_ALLOC(resultHolder);
|
||||
|
||||
for (;;)
|
||||
@@ -993,7 +1007,7 @@ namespace details
|
||||
if (lastError == ERROR_MORE_DATA)
|
||||
{
|
||||
allocationSize *= 2;
|
||||
resultHolder.reset(new (std::nothrow) char[allocationSize]);
|
||||
resultHolder.reset(::operator new(allocationSize, std::nothrow));
|
||||
RETURN_IF_NULL_ALLOC(resultHolder);
|
||||
}
|
||||
else if (lastError == ERROR_NO_MORE_FILES) // for folder enumeration cases
|
||||
@@ -1028,6 +1042,11 @@ RETURN_IF_FAILED(GetFileInfoNoThrow<FileNameInfo>(fileHandle, fileNameInfo));
|
||||
template <FILE_INFO_BY_HANDLE_CLASS infoClass, typename wistd::enable_if<!details::MapInfoClassToInfoStruct<infoClass>::isFixed, int>::type = 0>
|
||||
HRESULT GetFileInfoNoThrow(HANDLE fileHandle, wistd::unique_ptr<typename details::MapInfoClassToInfoStruct<infoClass>::type>& result) WI_NOEXCEPT
|
||||
{
|
||||
#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
|
||||
static_assert(
|
||||
__STDCPP_DEFAULT_NEW_ALIGNMENT__ >= alignof(typename details::MapInfoClassToInfoStruct<infoClass>::type),
|
||||
"Memory allocated by 'details::GetFileInfo' may not be aligned correctly");
|
||||
#endif
|
||||
void* rawResult;
|
||||
HRESULT hr = details::GetFileInfo(
|
||||
fileHandle,
|
||||
|
||||
+42
-39
@@ -16,7 +16,7 @@
|
||||
#include "common.h"
|
||||
|
||||
#if WIL_USE_STL
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -27,7 +27,11 @@
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
#include "resource.h"
|
||||
|
||||
#ifdef _KERNEL_MODE
|
||||
@@ -66,6 +70,12 @@ namespace reg
|
||||
|
||||
// Open key for reading and writing. Equivalent to KEY_ALL_ACCESS.
|
||||
readwrite,
|
||||
|
||||
// Open key for reading from 64-bit registry.
|
||||
read64,
|
||||
|
||||
// Open key for reading and writing from 64-bit registry. Equivalent to KEY_ALL_ACCESS.
|
||||
readwrite64,
|
||||
};
|
||||
|
||||
/// @cond
|
||||
@@ -101,6 +111,10 @@ namespace reg
|
||||
return KEY_READ;
|
||||
case key_access::readwrite:
|
||||
return KEY_ALL_ACCESS;
|
||||
case key_access::read64:
|
||||
return KEY_READ | KEY_WOW64_64KEY;
|
||||
case key_access::readwrite64:
|
||||
return KEY_ALL_ACCESS | KEY_WOW64_64KEY;
|
||||
}
|
||||
FAIL_FAST();
|
||||
RESULT_NORETURN_RESULT(0);
|
||||
@@ -447,6 +461,7 @@ namespace reg
|
||||
}
|
||||
// including the last null buffer space in the returned buffer-size-bytes
|
||||
// as the registry API we call guarantees null termination
|
||||
// NOLINTNEXTLINE(bugprone-misplaced-widening-cast): size_t and DWORD are effectively the same on x86
|
||||
return static_cast<DWORD>((::wcslen(value) + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
@@ -537,6 +552,7 @@ namespace reg
|
||||
{
|
||||
// including the last null buffer space in the returned buffer-size-bytes
|
||||
// as the registry API we call guarantees null termination
|
||||
// NOLINTNEXTLINE(bugprone-misplaced-widening-cast): size_t and DWORD are effectively the same on x86
|
||||
return static_cast<DWORD>((string.size() + 1) * sizeof(wchar_t));
|
||||
}
|
||||
|
||||
@@ -573,6 +589,8 @@ namespace reg
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(bugprone-exception-escape): Only reduces the size
|
||||
inline size_t trim_buffer(::std::wstring& buffer) WI_NOEXCEPT
|
||||
{
|
||||
// remove any embedded null characters
|
||||
@@ -891,16 +909,16 @@ namespace reg
|
||||
|
||||
// constexpr expressions to determining the get* and set* registry value types
|
||||
// for all supported types T to read/write values
|
||||
template <typename T>
|
||||
template <typename T = void>
|
||||
DWORD get_value_type() WI_NOEXCEPT
|
||||
{
|
||||
static_assert(sizeof(T) != sizeof(T), "Unsupported type for get_value_type");
|
||||
static_assert(!wistd::is_same_v<T, T>, "Unsupported type for get_value_type");
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename T = void>
|
||||
DWORD set_value_type() WI_NOEXCEPT
|
||||
{
|
||||
static_assert(sizeof(T) != sizeof(T), "Unsupported type for set_value_type");
|
||||
static_assert(!wistd::is_same_v<T, T>, "Unsupported type for set_value_type");
|
||||
}
|
||||
|
||||
template <>
|
||||
@@ -1077,7 +1095,7 @@ namespace reg
|
||||
reg_view_t& operator=(reg_view_t&&) = delete;
|
||||
|
||||
typename err_policy::result open_key(
|
||||
_In_opt_ _In_opt_ PCWSTR subKey, _Out_ HKEY* hkey, ::wil::reg::key_access access = ::wil::reg::key_access::read) const
|
||||
_In_opt_ PCWSTR subKey, _Out_ HKEY* hkey, ::wil::reg::key_access access = ::wil::reg::key_access::read) const
|
||||
{
|
||||
constexpr DWORD zero_options{0};
|
||||
return err_policy::HResult(
|
||||
@@ -1124,7 +1142,7 @@ namespace reg
|
||||
typename err_policy::result get_value_char_array(
|
||||
_In_opt_ PCWSTR subkey, _In_opt_ PCWSTR value_name, WCHAR (&return_value)[Length], DWORD type, _Out_opt_ DwordType* requiredBytes) const
|
||||
{
|
||||
constexpr DwordType zero_value{0ul};
|
||||
constexpr DwordType zero_value{0UL};
|
||||
::wil::assign_to_opt_param(requiredBytes, zero_value);
|
||||
DWORD data_size_bytes{Length * sizeof(WCHAR)};
|
||||
const auto hr = HRESULT_FROM_WIN32(::RegGetValueW(
|
||||
@@ -1306,18 +1324,18 @@ namespace reg
|
||||
constexpr size_t iterator_max_valuename_length = 16383;
|
||||
|
||||
// function overloads to allow *_enumerator objects to be constructed from all 3 types of HKEY representatives
|
||||
inline HKEY get_hkey(HKEY h) WI_NOEXCEPT
|
||||
inline HKEY get_hkey(HKEY key) WI_NOEXCEPT
|
||||
{
|
||||
return h;
|
||||
return key;
|
||||
}
|
||||
inline HKEY get_hkey(const ::wil::unique_hkey& h) WI_NOEXCEPT
|
||||
inline HKEY get_hkey(const ::wil::unique_hkey& key) WI_NOEXCEPT
|
||||
{
|
||||
return h.get();
|
||||
return key.get();
|
||||
}
|
||||
#if defined(__WIL_WINREG_STL)
|
||||
inline HKEY get_hkey(const ::wil::shared_hkey& h) WI_NOEXCEPT
|
||||
inline HKEY get_hkey(const ::wil::shared_hkey& key) WI_NOEXCEPT
|
||||
{
|
||||
return h.get();
|
||||
return key.get();
|
||||
}
|
||||
#endif // #if defined(__WIL_WINREG_STL)
|
||||
|
||||
@@ -1327,7 +1345,7 @@ namespace reg
|
||||
// reference these overload functions
|
||||
inline void clear_name(::std::wstring& name, size_t) WI_NOEXCEPT
|
||||
{
|
||||
name.assign(name.size(), L'\0');
|
||||
std::fill(name.begin(), name.end(), L'\0');
|
||||
}
|
||||
inline ::std::wstring copy_name(const ::std::wstring& str, size_t length) WI_NOEXCEPT
|
||||
{
|
||||
@@ -1442,7 +1460,7 @@ namespace reg
|
||||
class key_iterator_data
|
||||
{
|
||||
public:
|
||||
T name{};
|
||||
T name{}; // NOLINT(misc-non-private-member-variables-in-classes): Part of original interface & cannot change
|
||||
|
||||
key_iterator_data(HKEY key = nullptr) WI_NOEXCEPT : m_hkey{key}
|
||||
{
|
||||
@@ -1600,8 +1618,8 @@ namespace reg
|
||||
class value_iterator_data
|
||||
{
|
||||
public:
|
||||
T name{};
|
||||
DWORD type = REG_NONE;
|
||||
T name{}; // NOLINT(misc-non-private-member-variables-in-classes): Part of original interface & cannot change
|
||||
DWORD type = REG_NONE; // NOLINT(misc-non-private-member-variables-in-classes): Part of original interface & cannot change
|
||||
|
||||
value_iterator_data(HKEY key = nullptr) WI_NOEXCEPT : m_hkey{key}
|
||||
{
|
||||
@@ -1711,10 +1729,8 @@ namespace reg
|
||||
|
||||
// resize and try again - growing exponentially up to the max
|
||||
string_length *= 2;
|
||||
if (string_length > ::wil::reg::reg_iterator_details::iterator_max_valuename_length + 1)
|
||||
{
|
||||
string_length = ::wil::reg::reg_iterator_details::iterator_max_valuename_length + 1;
|
||||
}
|
||||
string_length = (wistd::min)(
|
||||
string_length, static_cast<DWORD>(::wil::reg::reg_iterator_details::iterator_max_valuename_length + 1));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1817,16 +1833,8 @@ namespace reg
|
||||
iterator_t& operator+=(size_t offset)
|
||||
{
|
||||
uint32_t newIndex = m_data.m_index + static_cast<uint32_t>(offset);
|
||||
if (newIndex < m_data.m_index)
|
||||
{
|
||||
// fail on integer overflow
|
||||
THROW_HR(E_INVALIDARG);
|
||||
}
|
||||
if (newIndex == ::wil::reg::reg_iterator_details::iterator_end_offset)
|
||||
{
|
||||
// fail if this creates an end iterator
|
||||
THROW_HR(E_INVALIDARG);
|
||||
}
|
||||
THROW_HR_IF(E_INVALIDARG, newIndex < m_data.m_index); // fail on integer overflow
|
||||
THROW_HR_IF(E_INVALIDARG, newIndex == ::wil::reg::reg_iterator_details::iterator_end_offset); // fail if this creates an end iterator
|
||||
|
||||
// iterate by the integer offset
|
||||
for (size_t count = 0; count < offset; ++count)
|
||||
@@ -1880,14 +1888,9 @@ namespace reg
|
||||
HRESULT move_next() WI_NOEXCEPT
|
||||
{
|
||||
const auto newIndex = m_data.m_index + 1;
|
||||
if (newIndex < m_data.m_index)
|
||||
if ((newIndex < m_data.m_index) || // fail on integer overflow
|
||||
(newIndex == ::wil::reg::reg_iterator_details::iterator_end_offset)) // fail if this creates an end iterator
|
||||
{
|
||||
// fail on integer overflow
|
||||
m_last_error = E_INVALIDARG;
|
||||
}
|
||||
else if (newIndex == ::wil::reg::reg_iterator_details::iterator_end_offset)
|
||||
{
|
||||
// fail if this creates an end iterator
|
||||
m_last_error = E_INVALIDARG;
|
||||
}
|
||||
else
|
||||
@@ -1956,4 +1959,4 @@ namespace reg
|
||||
|
||||
} // namespace reg
|
||||
} // namespace wil
|
||||
#endif // __WIL_REGISTRY_HELPERS_INCLUDED
|
||||
#endif // __WIL_REGISTRY_HELPERS_INCLUDED
|
||||
|
||||
+800
-158
File diff suppressed because it is too large
Load Diff
Vendored
+10
-7
@@ -32,9 +32,11 @@
|
||||
#error This header is not supported in kernel-mode.
|
||||
#endif
|
||||
|
||||
// The updated behavior of running init-list ctors during placement new is proper & correct, disable the warning that requests developers verify they want it
|
||||
#pragma warning(push)
|
||||
// The updated behavior of running init-list ctors during placement new is proper & correct, disable the warning that requests developers verify they want it
|
||||
#pragma warning(disable : 4351)
|
||||
// remove this after fixing - volatile access of '<expression>' is subject to /volatile:<iso|ms> setting; consider using __iso_volatile_load/store intrinsic functions
|
||||
#pragma warning(disable : 4746)
|
||||
|
||||
namespace wil
|
||||
{
|
||||
@@ -107,6 +109,7 @@ namespace details_abi
|
||||
*pointer = nullptr;
|
||||
ULONG_PTR value = 0;
|
||||
__WIL_PRIVATE_RETURN_IF_FAILED(TryGetValue(name, &value));
|
||||
// NOLINTNEXTLINE(performance-no-int-to-ptr): Provenance concealment is intentional here
|
||||
*pointer = reinterpret_cast<void*>(value << 2);
|
||||
return S_OK;
|
||||
}
|
||||
@@ -403,7 +406,7 @@ namespace details_abi
|
||||
T* GetLocal(bool shouldAllocate = false) WI_NOEXCEPT
|
||||
{
|
||||
DWORD const threadId = ::GetCurrentThreadId();
|
||||
size_t const index = (threadId % ARRAYSIZE(m_hashArray));
|
||||
size_t const index = ((threadId >> 2) % ARRAYSIZE(m_hashArray)); // Reduce hash collisions; thread IDs are even.
|
||||
for (auto pNode = m_hashArray[index]; pNode != nullptr; pNode = pNode->pNext)
|
||||
{
|
||||
if (pNode->threadId == threadId)
|
||||
@@ -435,7 +438,7 @@ namespace details_abi
|
||||
private:
|
||||
struct Node
|
||||
{
|
||||
DWORD threadId = 0xffffffffu;
|
||||
DWORD threadId = 0xffffffffU;
|
||||
Node* pNext = nullptr;
|
||||
T value{};
|
||||
};
|
||||
@@ -518,7 +521,7 @@ namespace details_abi
|
||||
{
|
||||
::ZeroMemory(&info, sizeof(info));
|
||||
|
||||
info.failureId = sequenceId;
|
||||
info.failureId = static_cast<long>(sequenceId);
|
||||
info.hr = hr;
|
||||
info.pszFile = fileName;
|
||||
info.uLineNumber = lineNumber;
|
||||
@@ -666,7 +669,7 @@ namespace details_abi
|
||||
unsigned int minSequenceId,
|
||||
_In_opt_ const DiagnosticsInfo* diagnostics,
|
||||
HRESULT matchRequirement,
|
||||
void* returnAddress)
|
||||
void* returnAddress) const
|
||||
{
|
||||
// First attempt to get the last error and then see if it matches the error returned from
|
||||
// the last caught exception. If it does, then we're good to go and we return that last error.
|
||||
@@ -838,7 +841,7 @@ public:
|
||||
/** Retrieves the origination of the last error that occurred since this class was constructed.
|
||||
The optional parameter allows the failure information returned to be filtered to a specific
|
||||
result. */
|
||||
inline bool GetLastError(FailureInfo& info, HRESULT matchRequirement = S_OK)
|
||||
bool GetLastError(FailureInfo& info, HRESULT matchRequirement = S_OK)
|
||||
{
|
||||
if (m_data)
|
||||
{
|
||||
@@ -849,7 +852,7 @@ public:
|
||||
|
||||
/** Retrieves the origin of the current exception (within a catch block) since this class was constructed.
|
||||
See @ref GetCaughtExceptionError for more information */
|
||||
inline __declspec(noinline) bool GetCaughtExceptionError(
|
||||
__declspec(noinline) bool GetCaughtExceptionError(
|
||||
_Inout_ wil::FailureInfo& info, const DiagnosticsInfo* diagnostics = nullptr, HRESULT matchRequirement = S_OK)
|
||||
{
|
||||
if (m_data)
|
||||
|
||||
+120
-85
@@ -20,8 +20,12 @@
|
||||
#include "common.h"
|
||||
|
||||
#if !defined(__WIL_MIN_KERNEL) && !defined(WIL_KERNEL_MODE)
|
||||
#ifdef __MINGW32__
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Setup the debug behavior. For kernel-mode, we ignore NDEBUG because that gets set automatically
|
||||
// for driver projects. We mimic the behavior of NT_ASSERT which checks only for DBG.
|
||||
@@ -34,7 +38,11 @@
|
||||
|
||||
/// @cond
|
||||
#if defined(_PREFAST_)
|
||||
#ifdef __cplusplus
|
||||
#define __WI_ANALYSIS_ASSUME(_exp) _Analysis_assume_(static_cast<bool>(_exp))
|
||||
#else
|
||||
#define __WI_ANALYSIS_ASSUME(_exp) _Analysis_assume_(_exp)
|
||||
#endif
|
||||
#else
|
||||
#ifdef RESULT_DEBUG
|
||||
#define __WI_ANALYSIS_ASSUME(_exp) ((void)0)
|
||||
@@ -248,6 +256,7 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
|
||||
//*****************************************************************************
|
||||
|
||||
/// @cond
|
||||
// NOLINTBEGIN(bugprone-macro-parentheses): Uses of these macros are tightly controlled
|
||||
#define __R_DIAGNOSTICS(diagnostics) diagnostics.returnAddress, diagnostics.line, diagnostics.file, nullptr, nullptr
|
||||
#define __R_DIAGNOSTICS_RA(diagnostics, address) \
|
||||
diagnostics.returnAddress, diagnostics.line, diagnostics.file, nullptr, nullptr, address
|
||||
@@ -319,11 +328,14 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
|
||||
#define __R_INFO_ONLY(CODE) \
|
||||
__R_IF_CALLERADDRESS(_ReturnAddress() __R_IF_COMMA) \
|
||||
__R_IF_LINE(__R_LINE_VALUE) \
|
||||
__R_IF_FILE(__R_COMMA __R_FILE_VALUE) __R_IF_FUNCTION(__R_COMMA __FUNCTION__) __R_IF_CODE(__R_COMMA CODE)
|
||||
__R_IF_FILE(__R_COMMA __R_FILE_VALUE) \
|
||||
__R_IF_FUNCTION(__R_COMMA __FUNCTION__) __R_IF_CODE(__R_COMMA CODE) // NOLINT(bugprone-lambda-function-name)
|
||||
#define __R_INFO(CODE) __R_INFO_ONLY(CODE) __R_IF_TRAIL_COMMA
|
||||
#define __R_INFO_NOFILE_ONLY(CODE) \
|
||||
__R_IF_CALLERADDRESS(_ReturnAddress() __R_IF_COMMA) \
|
||||
__R_IF_LINE(__R_LINE_VALUE) __R_IF_FILE(__R_COMMA "wil") __R_IF_FUNCTION(__R_COMMA __FUNCTION__) __R_IF_CODE(__R_COMMA CODE)
|
||||
__R_IF_LINE(__R_LINE_VALUE) \
|
||||
__R_IF_FILE(__R_COMMA "wil") \
|
||||
__R_IF_FUNCTION(__R_COMMA __FUNCTION__) __R_IF_CODE(__R_COMMA CODE) // NOLINT(bugprone-lambda-function-name)
|
||||
#define __R_INFO_NOFILE(CODE) __R_INFO_NOFILE_ONLY(CODE) __R_IF_TRAIL_COMMA
|
||||
#define __R_FN_PARAMS_ONLY \
|
||||
__R_IF_CALLERADDRESS(void* callerReturnAddress __R_IF_COMMA) \
|
||||
@@ -361,8 +373,13 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
|
||||
template <unsigned int optimizerCounter> \
|
||||
inline __declspec(noinline) RESULT_NORETURN RetType MethodName
|
||||
#else
|
||||
#if defined(_MSC_VER) || defined(__clang__)
|
||||
#define __R_DIRECT_METHOD(RetType, MethodName) inline __declspec(noinline) RetType MethodName
|
||||
#define __R_DIRECT_NORET_METHOD(RetType, MethodName) inline __declspec(noinline) RESULT_NORETURN RetType MethodName
|
||||
#else
|
||||
#define __R_DIRECT_METHOD(RetType, MethodName) inline RetType MethodName
|
||||
#define __R_DIRECT_NORET_METHOD(RetType, MethodName) inline RetType MethodName
|
||||
#endif
|
||||
#endif
|
||||
#define __R_DIRECT_FN_PARAMS __R_FN_PARAMS
|
||||
#define __R_DIRECT_FN_PARAMS_ONLY __R_FN_PARAMS_ONLY
|
||||
@@ -517,12 +534,14 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
|
||||
#define __RFF_INFO_ONLY(CODE) \
|
||||
__RFF_IF_CALLERADDRESS(_ReturnAddress() __RFF_IF_COMMA) \
|
||||
__RFF_IF_LINE(__R_LINE_VALUE) \
|
||||
__RFF_IF_FILE(__RFF_COMMA __R_FILE_VALUE) __RFF_IF_FUNCTION(__RFF_COMMA __FUNCTION__) __RFF_IF_CODE(__RFF_COMMA CODE)
|
||||
__RFF_IF_FILE(__RFF_COMMA __R_FILE_VALUE) \
|
||||
__RFF_IF_FUNCTION(__RFF_COMMA __FUNCTION__) __RFF_IF_CODE(__RFF_COMMA CODE) // NOLINT(bugprone-lambda-function-name)
|
||||
#define __RFF_INFO(CODE) __RFF_INFO_ONLY(CODE) __RFF_IF_TRAIL_COMMA
|
||||
#define __RFF_INFO_NOFILE_ONLY(CODE) \
|
||||
__RFF_IF_CALLERADDRESS(_ReturnAddress() __RFF_IF_COMMA) \
|
||||
__RFF_IF_LINE(__R_LINE_VALUE) \
|
||||
__RFF_IF_FILE(__RFF_COMMA "wil") __RFF_IF_FUNCTION(__RFF_COMMA __FUNCTION__) __RFF_IF_CODE(__RFF_COMMA CODE)
|
||||
__RFF_IF_FILE(__RFF_COMMA "wil") \
|
||||
__RFF_IF_FUNCTION(__RFF_COMMA __FUNCTION__) __RFF_IF_CODE(__RFF_COMMA CODE) // NOLINT(bugprone-lambda-function-name)
|
||||
#define __RFF_INFO_NOFILE(CODE) __RFF_INFO_NOFILE_ONLY(CODE) __RFF_IF_TRAIL_COMMA
|
||||
#define __RFF_FN_PARAMS_ONLY \
|
||||
__RFF_IF_CALLERADDRESS(void* callerReturnAddress __RFF_IF_COMMA) \
|
||||
@@ -811,6 +830,7 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
|
||||
return __R_FN(Return_NtStatus)(__R_INFO(str) __status); \
|
||||
} \
|
||||
__WI_SUPPRESS_BREAKING_WARNINGS_E while ((void)0, 0)
|
||||
// NOLINTEND(bugprone-macro-parentheses)
|
||||
/// @endcond
|
||||
|
||||
//*****************************************************************************
|
||||
@@ -1127,19 +1147,19 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
|
||||
// Always logs a known failure
|
||||
#define LOG_HR(hr) __R_FN(Log_Hr)(__R_INFO(#hr) wil::verify_hresult(hr))
|
||||
#define LOG_LAST_ERROR() __R_FN(Log_GetLastError)(__R_INFO_ONLY(nullptr))
|
||||
#define LOG_WIN32(win32err) __R_FN(Log_Win32)(__R_INFO(#win32err) win32err)
|
||||
#define LOG_NTSTATUS(status) __R_FN(Log_NtStatus)(__R_INFO(#status) status)
|
||||
#define LOG_WIN32(win32err) __R_FN(Log_Win32)(__R_INFO(#win32err)(win32err))
|
||||
#define LOG_NTSTATUS(status) __R_FN(Log_NtStatus)(__R_INFO(#status)(status))
|
||||
|
||||
// Conditionally logs failures - returns parameter value
|
||||
#define LOG_IF_FAILED(hr) __R_FN(Log_IfFailed)(__R_INFO(#hr) wil::verify_hresult(hr))
|
||||
#define LOG_IF_WIN32_BOOL_FALSE(win32BOOL) __R_FN(Log_IfWin32BoolFalse)(__R_INFO(#win32BOOL) wil::verify_BOOL(win32BOOL))
|
||||
#define LOG_IF_WIN32_ERROR(win32err) __R_FN(Log_IfWin32Error)(__R_INFO(#win32err) win32err)
|
||||
#define LOG_IF_NULL_ALLOC(ptr) __R_FN(Log_IfNullAlloc)(__R_INFO(#ptr) ptr)
|
||||
#define LOG_IF_WIN32_ERROR(win32err) __R_FN(Log_IfWin32Error)(__R_INFO(#win32err)(win32err))
|
||||
#define LOG_IF_NULL_ALLOC(ptr) __R_FN(Log_IfNullAlloc)(__R_INFO(#ptr)(ptr))
|
||||
#define LOG_HR_IF(hr, condition) __R_FN(Log_HrIf)(__R_INFO(#condition) wil::verify_hresult(hr), wil::verify_bool(condition))
|
||||
#define LOG_HR_IF_NULL(hr, ptr) __R_FN(Log_HrIfNull)(__R_INFO(#ptr) wil::verify_hresult(hr), ptr)
|
||||
#define LOG_LAST_ERROR_IF(condition) __R_FN(Log_GetLastErrorIf)(__R_INFO(#condition) wil::verify_bool(condition))
|
||||
#define LOG_LAST_ERROR_IF_NULL(ptr) __R_FN(Log_GetLastErrorIfNull)(__R_INFO(#ptr) ptr)
|
||||
#define LOG_IF_NTSTATUS_FAILED(status) __R_FN(Log_IfNtStatusFailed)(__R_INFO(#status) status)
|
||||
#define LOG_LAST_ERROR_IF_NULL(ptr) __R_FN(Log_GetLastErrorIfNull)(__R_INFO(#ptr)(ptr))
|
||||
#define LOG_IF_NTSTATUS_FAILED(status) __R_FN(Log_IfNtStatusFailed)(__R_INFO(#status)(status))
|
||||
|
||||
// Alternatives for SUCCEEDED(hr) and FAILED(hr) that conditionally log failures
|
||||
#define SUCCEEDED_LOG(hr) SUCCEEDED(LOG_IF_FAILED(hr))
|
||||
@@ -1197,21 +1217,21 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
|
||||
// Always fail fast a known failure
|
||||
#define FAIL_FAST_HR(hr) __RFF_FN(FailFast_Hr)(__RFF_INFO(#hr) wil::verify_hresult(hr))
|
||||
#define FAIL_FAST_LAST_ERROR() __RFF_FN(FailFast_GetLastError)(__RFF_INFO_ONLY(nullptr))
|
||||
#define FAIL_FAST_WIN32(win32err) __RFF_FN(FailFast_Win32)(__RFF_INFO(#win32err) win32err)
|
||||
#define FAIL_FAST_NTSTATUS(status) __RFF_FN(FailFast_NtStatus)(__RFF_INFO(#status) status)
|
||||
#define FAIL_FAST_WIN32(win32err) __RFF_FN(FailFast_Win32)(__RFF_INFO(#win32err)(win32err))
|
||||
#define FAIL_FAST_NTSTATUS(status) __RFF_FN(FailFast_NtStatus)(__RFF_INFO(#status)(status))
|
||||
|
||||
// Conditionally fail fast failures - returns parameter value
|
||||
#define FAIL_FAST_IF_FAILED(hr) __RFF_FN(FailFast_IfFailed)(__RFF_INFO(#hr) wil::verify_hresult(hr))
|
||||
#define FAIL_FAST_IF_WIN32_BOOL_FALSE(win32BOOL) \
|
||||
__RFF_FN(FailFast_IfWin32BoolFalse)(__RFF_INFO(#win32BOOL) wil::verify_BOOL(win32BOOL))
|
||||
#define FAIL_FAST_IF_WIN32_ERROR(win32err) __RFF_FN(FailFast_IfWin32Error)(__RFF_INFO(#win32err) win32err)
|
||||
#define FAIL_FAST_IF_NULL_ALLOC(ptr) __RFF_FN(FailFast_IfNullAlloc)(__RFF_INFO(#ptr) ptr)
|
||||
#define FAIL_FAST_IF_WIN32_ERROR(win32err) __RFF_FN(FailFast_IfWin32Error)(__RFF_INFO(#win32err)(win32err))
|
||||
#define FAIL_FAST_IF_NULL_ALLOC(ptr) __RFF_FN(FailFast_IfNullAlloc)(__RFF_INFO(#ptr)(ptr))
|
||||
#define FAIL_FAST_HR_IF(hr, condition) \
|
||||
__RFF_FN(FailFast_HrIf)(__RFF_INFO(#condition) wil::verify_hresult(hr), wil::verify_bool(condition))
|
||||
#define FAIL_FAST_HR_IF_NULL(hr, ptr) __RFF_FN(FailFast_HrIfNull)(__RFF_INFO(#ptr) wil::verify_hresult(hr), ptr)
|
||||
#define FAIL_FAST_LAST_ERROR_IF(condition) __RFF_FN(FailFast_GetLastErrorIf)(__RFF_INFO(#condition) wil::verify_bool(condition))
|
||||
#define FAIL_FAST_LAST_ERROR_IF_NULL(ptr) __RFF_FN(FailFast_GetLastErrorIfNull)(__RFF_INFO(#ptr) ptr)
|
||||
#define FAIL_FAST_IF_NTSTATUS_FAILED(status) __RFF_FN(FailFast_IfNtStatusFailed)(__RFF_INFO(#status) status)
|
||||
#define FAIL_FAST_LAST_ERROR_IF_NULL(ptr) __RFF_FN(FailFast_GetLastErrorIfNull)(__RFF_INFO(#ptr)(ptr))
|
||||
#define FAIL_FAST_IF_NTSTATUS_FAILED(status) __RFF_FN(FailFast_IfNtStatusFailed)(__RFF_INFO(#status)(status))
|
||||
|
||||
// Always fail fast a known failure - fail fast a var-arg message on failure
|
||||
#define FAIL_FAST_HR_MSG(hr, fmt, ...) \
|
||||
@@ -1253,7 +1273,7 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
|
||||
|
||||
// Conditionally fail fast failures - returns parameter value
|
||||
#define FAIL_FAST_IF(condition) __RFF_FN(FailFast_If)(__RFF_INFO(#condition) wil::verify_bool(condition))
|
||||
#define FAIL_FAST_IF_NULL(ptr) __RFF_FN(FailFast_IfNull)(__RFF_INFO(#ptr) ptr)
|
||||
#define FAIL_FAST_IF_NULL(ptr) __RFF_FN(FailFast_IfNull)(__RFF_INFO(#ptr)(ptr))
|
||||
|
||||
// Always fail fast a known failure - fail fast a var-arg message on failure
|
||||
#define FAIL_FAST_MSG(fmt, ...) __RFF_FN(FailFast_UnexpectedMsg)(__RFF_INFO(nullptr) __WI_CHECK_MSG_FMT(fmt, ##__VA_ARGS__))
|
||||
@@ -1312,22 +1332,22 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
|
||||
// Always throw a known failure
|
||||
#define THROW_HR(hr) __R_FN(Throw_Hr)(__R_INFO(#hr) wil::verify_hresult(hr))
|
||||
#define THROW_LAST_ERROR() __R_FN(Throw_GetLastError)(__R_INFO_ONLY(nullptr))
|
||||
#define THROW_WIN32(win32err) __R_FN(Throw_Win32)(__R_INFO(#win32err) win32err)
|
||||
#define THROW_EXCEPTION(exception) wil::details::ReportFailure_CustomException(__R_INFO(#exception) exception)
|
||||
#define THROW_NTSTATUS(status) __R_FN(Throw_NtStatus)(__R_INFO(#status) status)
|
||||
#define THROW_WIN32(win32err) __R_FN(Throw_Win32)(__R_INFO(#win32err)(win32err))
|
||||
#define THROW_EXCEPTION(exception) wil::details::ReportFailure_CustomException(__R_INFO(#exception)(exception))
|
||||
#define THROW_NTSTATUS(status) __R_FN(Throw_NtStatus)(__R_INFO(#status)(status))
|
||||
|
||||
// Conditionally throw failures - returns parameter value
|
||||
#define THROW_IF_FAILED(hr) __R_FN(Throw_IfFailed)(__R_INFO(#hr) wil::verify_hresult(hr))
|
||||
#define THROW_IF_WIN32_BOOL_FALSE(win32BOOL) __R_FN(Throw_IfWin32BoolFalse)(__R_INFO(#win32BOOL) wil::verify_BOOL(win32BOOL))
|
||||
#define THROW_IF_WIN32_ERROR(win32err) __R_FN(Throw_IfWin32Error)(__R_INFO(#win32err) win32err)
|
||||
#define THROW_IF_NULL_ALLOC(ptr) __R_FN(Throw_IfNullAlloc)(__R_INFO(#ptr) ptr)
|
||||
#define THROW_IF_WIN32_ERROR(win32err) __R_FN(Throw_IfWin32Error)(__R_INFO(#win32err)(win32err))
|
||||
#define THROW_IF_NULL_ALLOC(ptr) __R_FN(Throw_IfNullAlloc)(__R_INFO(#ptr)(ptr))
|
||||
#define THROW_HR_IF(hr, condition) __R_FN(Throw_HrIf)(__R_INFO(#condition) wil::verify_hresult(hr), wil::verify_bool(condition))
|
||||
#define THROW_HR_IF_NULL(hr, ptr) __R_FN(Throw_HrIfNull)(__R_INFO(#ptr) wil::verify_hresult(hr), ptr)
|
||||
#define THROW_WIN32_IF(win32err, condition) \
|
||||
__R_FN(Throw_Win32If)(__R_INFO(#condition) wil::verify_win32(win32err), wil::verify_bool(condition))
|
||||
#define THROW_LAST_ERROR_IF(condition) __R_FN(Throw_GetLastErrorIf)(__R_INFO(#condition) wil::verify_bool(condition))
|
||||
#define THROW_LAST_ERROR_IF_NULL(ptr) __R_FN(Throw_GetLastErrorIfNull)(__R_INFO(#ptr) ptr)
|
||||
#define THROW_IF_NTSTATUS_FAILED(status) __R_FN(Throw_IfNtStatusFailed)(__R_INFO(#status) status)
|
||||
#define THROW_LAST_ERROR_IF_NULL(ptr) __R_FN(Throw_GetLastErrorIfNull)(__R_INFO(#ptr)(ptr))
|
||||
#define THROW_IF_NTSTATUS_FAILED(status) __R_FN(Throw_IfNtStatusFailed)(__R_INFO(#status)(status))
|
||||
|
||||
// Always throw a known failure - throw a var-arg message on failure
|
||||
#define THROW_HR_MSG(hr, fmt, ...) \
|
||||
@@ -1410,9 +1430,8 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
|
||||
#define CATCH_LOG_RETURN() \
|
||||
catch (...) \
|
||||
{ \
|
||||
__pragma(warning(suppress : 4297)); \
|
||||
LOG_CAUGHT_EXCEPTION(); \
|
||||
return; \
|
||||
__pragma(warning(push)) __pragma(warning(disable : 4297)) LOG_CAUGHT_EXCEPTION(); \
|
||||
__pragma(warning(pop)) return; \
|
||||
}
|
||||
#define CATCH_LOG_MSG(fmt, ...) \
|
||||
catch (...) \
|
||||
@@ -1423,9 +1442,8 @@ WI_ODR_PRAGMA("WIL_FreeMemory", "0")
|
||||
#define CATCH_LOG_RETURN_MSG(fmt, ...) \
|
||||
catch (...) \
|
||||
{ \
|
||||
__pragma(warning(suppress : 4297)); \
|
||||
LOG_CAUGHT_EXCEPTION_MSG(fmt, ##__VA_ARGS__); \
|
||||
return; \
|
||||
__pragma(warning(push)) __pragma(warning(disable : 4297)) LOG_CAUGHT_EXCEPTION_MSG(fmt, ##__VA_ARGS__); \
|
||||
__pragma(warning(pop)) return; \
|
||||
}
|
||||
#define CATCH_FAIL_FAST() \
|
||||
catch (...) \
|
||||
@@ -1794,7 +1812,7 @@ inline HRESULT GetFailureLogString(
|
||||
// it for OutputDebugString or exception message, then generate the default string.
|
||||
if (pszDest[0] == L'\0')
|
||||
{
|
||||
PCSTR pszType = "";
|
||||
PCSTR pszType = ""; // NOLINT(clang-analyzer-deadcode.DeadStores): Good hygiene
|
||||
switch (failure.type)
|
||||
{
|
||||
case FailureType::Exception:
|
||||
@@ -1897,6 +1915,7 @@ inline HRESULT GetFailureLogString(
|
||||
{
|
||||
dest = details::LogStringPrintf(dest, destEnd, L"\n");
|
||||
}
|
||||
(void)dest; // Most recent stores are for consistency and debugging
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2065,7 +2084,10 @@ namespace details
|
||||
template <typename TFunctor>
|
||||
struct functor_wrapper_void : public IFunctor
|
||||
{
|
||||
private:
|
||||
TFunctor&& functor;
|
||||
|
||||
public:
|
||||
functor_wrapper_void(TFunctor&& functor_) : functor(wistd::forward<TFunctor>(functor_))
|
||||
{
|
||||
}
|
||||
@@ -2082,7 +2104,10 @@ namespace details
|
||||
template <typename TFunctor>
|
||||
struct functor_wrapper_HRESULT : public IFunctor
|
||||
{
|
||||
private:
|
||||
TFunctor&& functor;
|
||||
|
||||
public:
|
||||
functor_wrapper_HRESULT(TFunctor& functor_) : functor(wistd::forward<TFunctor>(functor_))
|
||||
{
|
||||
}
|
||||
@@ -2095,8 +2120,11 @@ namespace details
|
||||
template <typename TFunctor, typename TReturn>
|
||||
struct functor_wrapper_other : public IFunctor
|
||||
{
|
||||
private:
|
||||
TFunctor&& functor;
|
||||
TReturn& retVal;
|
||||
|
||||
public:
|
||||
functor_wrapper_other(TFunctor& functor_, TReturn& retval_) : functor(wistd::forward<TFunctor>(functor_)), retVal(retval_)
|
||||
{
|
||||
}
|
||||
@@ -2179,7 +2207,7 @@ namespace details
|
||||
__RFF_CONDITIONAL_METHOD(bool, FailFastImmediate_If)(bool condition) WI_NOEXCEPT;
|
||||
} // namespace __RFF_NS_NAME
|
||||
|
||||
RESULT_NORETURN inline void __stdcall WilFailFast(const FailureInfo& info);
|
||||
RESULT_NORETURN inline void __stdcall WilFailFast(const FailureInfo& failure);
|
||||
inline void LogFailure(
|
||||
__R_FN_PARAMS_FULL,
|
||||
FailureType type,
|
||||
@@ -2504,7 +2532,7 @@ namespace details
|
||||
{
|
||||
}
|
||||
|
||||
template <typename param_t>
|
||||
template <typename param_t> // NOLINTNEXTLINE(bugprone-forwarding-reference-overload): Internal type
|
||||
RefAndObject(param_t&& param1) : m_refCount(1), m_object(wistd::forward<param_t>(param1))
|
||||
{
|
||||
}
|
||||
@@ -2555,13 +2583,13 @@ namespace details
|
||||
}
|
||||
__WI_POP_WARNINGS
|
||||
|
||||
inline RESULT_NORETURN void __stdcall WilRaiseFailFastException(_In_ PEXCEPTION_RECORD er, _In_opt_ PCONTEXT cr, _In_ DWORD flags)
|
||||
inline RESULT_NORETURN void __stdcall WilRaiseFailFastException(_In_ PEXCEPTION_RECORD exr, _In_opt_ PCONTEXT ctxt, _In_ DWORD flags)
|
||||
{
|
||||
// if we managed to load the pointer either through WilDynamicRaiseFailFastException (PARTITION_DESKTOP etc.)
|
||||
// or via direct linkage (e.g. UWP apps), then use it.
|
||||
if (g_pfnRaiseFailFastException)
|
||||
{
|
||||
g_pfnRaiseFailFastException(er, cr, flags);
|
||||
g_pfnRaiseFailFastException(exr, ctxt, flags);
|
||||
}
|
||||
// if not, as a best effort, we are just going to call the intrinsic.
|
||||
__fastfail(FAST_FAIL_FATAL_APP_EXIT);
|
||||
@@ -2624,7 +2652,7 @@ namespace details
|
||||
::DebugBreak();
|
||||
}
|
||||
|
||||
inline void __stdcall WilDynamicLoadRaiseFailFastException(_In_ PEXCEPTION_RECORD er, _In_ PCONTEXT cr, _In_ DWORD flags)
|
||||
inline void __stdcall WilDynamicLoadRaiseFailFastException(_In_ PEXCEPTION_RECORD exr, _In_ PCONTEXT ctxt, _In_ DWORD flags)
|
||||
{
|
||||
auto k32handle = GetModuleHandleW(L"kernelbase.dll");
|
||||
_Analysis_assume_(k32handle != nullptr);
|
||||
@@ -2632,7 +2660,7 @@ namespace details
|
||||
details::GetProcAddress<decltype(WilDynamicLoadRaiseFailFastException)*>(k32handle, "RaiseFailFastException");
|
||||
if (pfnRaiseFailFastException)
|
||||
{
|
||||
pfnRaiseFailFastException(er, cr, flags);
|
||||
pfnRaiseFailFastException(exr, ctxt, flags);
|
||||
}
|
||||
}
|
||||
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
|
||||
@@ -2688,24 +2716,24 @@ namespace details
|
||||
__declspec(noinline) inline NTSTATUS HrToNtStatus(HRESULT hr) WI_NOEXCEPT
|
||||
{
|
||||
// Constants taken from ntstatus.h
|
||||
static constexpr NTSTATUS WIL_STATUS_INVALID_PARAMETER = 0xC000000D;
|
||||
static constexpr NTSTATUS WIL_STATUS_INTERNAL_ERROR = 0xC00000E5;
|
||||
static constexpr NTSTATUS WIL_STATUS_INTEGER_OVERFLOW = 0xC0000095;
|
||||
static constexpr NTSTATUS WIL_STATUS_OBJECT_PATH_NOT_FOUND = 0xC000003A;
|
||||
static constexpr NTSTATUS WIL_STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034;
|
||||
static constexpr NTSTATUS WIL_STATUS_NOT_IMPLEMENTED = 0xC0000002;
|
||||
static constexpr NTSTATUS WIL_STATUS_BUFFER_OVERFLOW = 0x80000005;
|
||||
static constexpr NTSTATUS WIL_STATUS_IMPLEMENTATION_LIMIT = 0xC000042B;
|
||||
static constexpr NTSTATUS WIL_STATUS_NO_MORE_MATCHES = 0xC0000273;
|
||||
static constexpr NTSTATUS WIL_STATUS_ILLEGAL_CHARACTER = 0xC0000161;
|
||||
static constexpr NTSTATUS WIL_STATUS_UNDEFINED_CHARACTER = 0xC0000163;
|
||||
static constexpr NTSTATUS WIL_STATUS_BUFFER_TOO_SMALL = 0xC0000023;
|
||||
static constexpr NTSTATUS WIL_STATUS_DISK_FULL = 0xC000007F;
|
||||
static constexpr NTSTATUS WIL_STATUS_OBJECT_NAME_INVALID = 0xC0000033;
|
||||
static constexpr NTSTATUS WIL_STATUS_DLL_NOT_FOUND = 0xC0000135;
|
||||
static constexpr NTSTATUS WIL_STATUS_REVISION_MISMATCH = 0xC0000059;
|
||||
static constexpr NTSTATUS WIL_STATUS_XML_PARSE_ERROR = 0xC000A083;
|
||||
static constexpr HRESULT WIL_E_FAIL = 0x80004005;
|
||||
static constexpr NTSTATUS WIL_STATUS_INVALID_PARAMETER = static_cast<NTSTATUS>(0xC000000D);
|
||||
static constexpr NTSTATUS WIL_STATUS_INTERNAL_ERROR = static_cast<NTSTATUS>(0xC00000E5);
|
||||
static constexpr NTSTATUS WIL_STATUS_INTEGER_OVERFLOW = static_cast<NTSTATUS>(0xC0000095);
|
||||
static constexpr NTSTATUS WIL_STATUS_OBJECT_PATH_NOT_FOUND = static_cast<NTSTATUS>(0xC000003A);
|
||||
static constexpr NTSTATUS WIL_STATUS_OBJECT_NAME_NOT_FOUND = static_cast<NTSTATUS>(0xC0000034);
|
||||
static constexpr NTSTATUS WIL_STATUS_NOT_IMPLEMENTED = static_cast<NTSTATUS>(0xC0000002);
|
||||
static constexpr NTSTATUS WIL_STATUS_BUFFER_OVERFLOW = static_cast<NTSTATUS>(0x80000005);
|
||||
static constexpr NTSTATUS WIL_STATUS_IMPLEMENTATION_LIMIT = static_cast<NTSTATUS>(0xC000042B);
|
||||
static constexpr NTSTATUS WIL_STATUS_NO_MORE_MATCHES = static_cast<NTSTATUS>(0xC0000273);
|
||||
static constexpr NTSTATUS WIL_STATUS_ILLEGAL_CHARACTER = static_cast<NTSTATUS>(0xC0000161);
|
||||
static constexpr NTSTATUS WIL_STATUS_UNDEFINED_CHARACTER = static_cast<NTSTATUS>(0xC0000163);
|
||||
static constexpr NTSTATUS WIL_STATUS_BUFFER_TOO_SMALL = static_cast<NTSTATUS>(0xC0000023);
|
||||
static constexpr NTSTATUS WIL_STATUS_DISK_FULL = static_cast<NTSTATUS>(0xC000007F);
|
||||
static constexpr NTSTATUS WIL_STATUS_OBJECT_NAME_INVALID = static_cast<NTSTATUS>(0xC0000033);
|
||||
static constexpr NTSTATUS WIL_STATUS_DLL_NOT_FOUND = static_cast<NTSTATUS>(0xC0000135);
|
||||
static constexpr NTSTATUS WIL_STATUS_REVISION_MISMATCH = static_cast<NTSTATUS>(0xC0000059);
|
||||
static constexpr NTSTATUS WIL_STATUS_XML_PARSE_ERROR = static_cast<NTSTATUS>(0xC000A083);
|
||||
static constexpr HRESULT WIL_E_FAIL = static_cast<HRESULT>(0x80004005);
|
||||
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
@@ -3030,7 +3058,7 @@ namespace details
|
||||
_Pre_satisfies_(pStart <= pEnd) _When_((pStart == pEnd) || (pszString == nullptr) || (pszString[0] == 0), _In_opt_) _When_(
|
||||
(pStart != pEnd) && (pszString != nullptr) && (pszString[0] != 0),
|
||||
_Out_writes_bytes_opt_(_String_length_(pszString) * sizeof(pszString[0]))) unsigned char* pStart,
|
||||
_Pre_satisfies_(pEnd >= pStart) unsigned char* pEnd,
|
||||
_Pre_satisfies_(pEnd >= pStart) unsigned char* pEnd, // NOLINT(readability-non-const-parameter): For consistency with pStart
|
||||
_In_opt_z_ TString pszString,
|
||||
_Outptr_result_maybenull_z_ TString* ppszBufferString)
|
||||
{
|
||||
@@ -3409,7 +3437,7 @@ public:
|
||||
|
||||
// Relies upon generated copy constructor and assignment operator
|
||||
|
||||
protected:
|
||||
private:
|
||||
FailureInfo m_failureInfo;
|
||||
details::shared_buffer m_spStrings;
|
||||
};
|
||||
@@ -3464,7 +3492,7 @@ public:
|
||||
}
|
||||
|
||||
//! Provides a string representing the FailureInfo from this exception.
|
||||
WI_NODISCARD inline const char* __CLR_OR_THIS_CALL what() const WI_NOEXCEPT override
|
||||
WI_NODISCARD const char* __CLR_OR_THIS_CALL what() const WI_NOEXCEPT override
|
||||
{
|
||||
#if !defined(NONLS) && !defined(NOAPISET)
|
||||
if (!m_what)
|
||||
@@ -3498,16 +3526,18 @@ public:
|
||||
|
||||
// Relies upon auto-generated copy constructor and assignment operator
|
||||
protected:
|
||||
// NOLINTBEGIN(misc-non-private-member-variables-in-classes): Historically part of API and too risky to change
|
||||
StoredFailureInfo m_failure; //!< The failure information for this exception
|
||||
mutable details::shared_buffer m_what; //!< The on-demand generated what() string
|
||||
// NOLINTEND(misc-non-private-member-variables-in-classes)
|
||||
|
||||
//! Use to produce a custom FailureInfo from an HRESULT (use only when constructing custom exception types).
|
||||
static FailureInfo CustomExceptionFailureInfo(HRESULT hr) WI_NOEXCEPT
|
||||
{
|
||||
FailureInfo fi = {};
|
||||
fi.type = FailureType::Exception;
|
||||
fi.hr = hr;
|
||||
return fi;
|
||||
FailureInfo info = {};
|
||||
info.type = FailureType::Exception;
|
||||
info.hr = hr;
|
||||
return info;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@@ -4112,15 +4142,19 @@ namespace details
|
||||
inline HRESULT ResultFromExceptionSeh(
|
||||
const DiagnosticsInfo& diagnostics, void* returnAddress, SupportedExceptions supported, IFunctor& functor) WI_NOEXCEPT
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
__try
|
||||
#endif
|
||||
{
|
||||
return wil::details::ResultFromKnownExceptions(diagnostics, returnAddress, supported, functor);
|
||||
}
|
||||
#if defined(_MSC_VER)
|
||||
__except (wil::details::TerminateAndReportError(GetExceptionInformation()), EXCEPTION_CONTINUE_SEARCH)
|
||||
{
|
||||
WI_ASSERT(false);
|
||||
RESULT_NORETURN_RESULT(HRESULT_FROM_WIN32(ERROR_UNHANDLED_EXCEPTION));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
__declspec(noinline) inline HRESULT ResultFromException(const DiagnosticsInfo& diagnostics, SupportedExceptions supported, IFunctor& functor) WI_NOEXCEPT
|
||||
@@ -4517,28 +4551,29 @@ namespace details
|
||||
}
|
||||
|
||||
// parameter 0 is the !analyze code (FAST_FAIL_FATAL_APP_EXIT)
|
||||
EXCEPTION_RECORD er{};
|
||||
er.NumberParameters = 1; // default to be safe, see below
|
||||
er.ExceptionCode = static_cast<DWORD>(STATUS_STACK_BUFFER_OVERRUN); // 0xC0000409
|
||||
er.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||
er.ExceptionInformation[0] = FAST_FAIL_FATAL_APP_EXIT; // see winnt.h, generated from minkernel\published\base\ntrtl_x.w
|
||||
EXCEPTION_RECORD exr{};
|
||||
exr.NumberParameters = 1; // default to be safe, see below
|
||||
// NOLINTNEXTLINE(readability-redundant-casting): STATUS_ macros inconsistently defined in Windows headers
|
||||
exr.ExceptionCode = static_cast<DWORD>(STATUS_STACK_BUFFER_OVERRUN); // 0xC0000409
|
||||
exr.ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||
exr.ExceptionInformation[0] = FAST_FAIL_FATAL_APP_EXIT; // see winnt.h, generated from minkernel\published\base\ntrtl_x.w
|
||||
if (failure.returnAddress == nullptr) // FailureInfo does not have _ReturnAddress, have RaiseFailFastException generate it
|
||||
{
|
||||
// passing ExceptionCode 0xC0000409 and one param with FAST_FAIL_APP_EXIT will use existing
|
||||
// !analyze functionality to crawl the stack looking for the HRESULT
|
||||
// don't pass a 0 HRESULT in param 1 because that will result in worse bucketing.
|
||||
WilRaiseFailFastException(&er, nullptr, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
|
||||
WilRaiseFailFastException(&exr, nullptr, FAIL_FAST_GENERATE_EXCEPTION_ADDRESS);
|
||||
}
|
||||
else // use FailureInfo caller address
|
||||
{
|
||||
// parameter 1 is the failing HRESULT
|
||||
// parameter 2 is the line number. This is never used for bucketing (due to code churn causing re-bucketing) but is available in the dump's
|
||||
// exception record to aid in failure locality. Putting it here prevents it from being poisoned in triage dumps.
|
||||
er.NumberParameters = 3;
|
||||
er.ExceptionInformation[1] = failure.hr;
|
||||
er.ExceptionInformation[2] = failure.uLineNumber;
|
||||
er.ExceptionAddress = failure.returnAddress;
|
||||
WilRaiseFailFastException(&er, nullptr, 0 /* do not generate exception address */);
|
||||
exr.NumberParameters = 3;
|
||||
exr.ExceptionInformation[1] = failure.hr;
|
||||
exr.ExceptionInformation[2] = failure.uLineNumber;
|
||||
exr.ExceptionAddress = failure.returnAddress;
|
||||
WilRaiseFailFastException(&exr, nullptr, 0 /* do not generate exception address */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4609,7 +4644,7 @@ namespace details
|
||||
__WI_SUPPRESS_BREAKING_WARNINGS_S
|
||||
if ((T == FailureType::FailFast) || WI_IsFlagSet(failure.flags, FailureFlags::RequestFailFast))
|
||||
{
|
||||
WilFailFast(const_cast<FailureInfo&>(failure));
|
||||
WilFailFast(failure);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4626,7 +4661,7 @@ namespace details
|
||||
ThrowResultException(failure);
|
||||
|
||||
// Wil was instructed to throw, but doesn't have any capability to do so (global function pointers are not setup)
|
||||
WilFailFast(const_cast<FailureInfo&>(failure));
|
||||
WilFailFast(failure);
|
||||
}
|
||||
__WI_SUPPRESS_BREAKING_WARNINGS_E
|
||||
}
|
||||
@@ -5185,7 +5220,7 @@ namespace details
|
||||
|
||||
inline void SetFailureInfo(_In_ FailureInfo const& failure, _Inout_ ResultException& exception) WI_NOEXCEPT
|
||||
{
|
||||
return exception.SetFailureInfo(failure);
|
||||
exception.SetFailureInfo(failure);
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
@@ -7226,10 +7261,10 @@ struct err_returncode_policy
|
||||
RETURN_IF_WIN32_BOOL_FALSE_EXPECTED(fReturn);
|
||||
return S_OK;
|
||||
}
|
||||
__forceinline static HRESULT Win32Handle(HANDLE h, _Out_ HANDLE* ph)
|
||||
__forceinline static HRESULT Win32Handle(HANDLE handleIn, _Out_ HANDLE* handleOut)
|
||||
{
|
||||
*ph = h;
|
||||
RETURN_LAST_ERROR_IF_NULL_EXPECTED(h);
|
||||
*handleOut = handleIn;
|
||||
RETURN_LAST_ERROR_IF_NULL_EXPECTED(handleIn);
|
||||
return S_OK;
|
||||
}
|
||||
_Post_satisfies_(return == hr) __forceinline static HRESULT HResult(HRESULT hr)
|
||||
@@ -7259,10 +7294,10 @@ struct err_failfast_policy
|
||||
{
|
||||
FAIL_FAST_IF_WIN32_BOOL_FALSE(fReturn);
|
||||
}
|
||||
__forceinline static result Win32Handle(HANDLE h, _Out_ HANDLE* ph)
|
||||
__forceinline static result Win32Handle(HANDLE handleIn, _Out_ HANDLE* handleOut)
|
||||
{
|
||||
*ph = h;
|
||||
FAIL_FAST_LAST_ERROR_IF_NULL(h);
|
||||
*handleOut = handleIn;
|
||||
FAIL_FAST_LAST_ERROR_IF_NULL(handleIn);
|
||||
}
|
||||
_When_(FAILED(hr), _Analysis_noreturn_)
|
||||
__forceinline static result HResult(HRESULT hr)
|
||||
@@ -7294,10 +7329,10 @@ struct err_exception_policy
|
||||
{
|
||||
THROW_IF_WIN32_BOOL_FALSE(fReturn);
|
||||
}
|
||||
__forceinline static result Win32Handle(HANDLE h, _Out_ HANDLE* ph)
|
||||
__forceinline static result Win32Handle(HANDLE handleIn, _Out_ HANDLE* handleOut)
|
||||
{
|
||||
*ph = h;
|
||||
THROW_LAST_ERROR_IF_NULL(h);
|
||||
*handleOut = handleIn;
|
||||
THROW_LAST_ERROR_IF_NULL(handleIn);
|
||||
}
|
||||
_When_(FAILED(hr), _Analysis_noreturn_)
|
||||
__forceinline static result HResult(HRESULT hr)
|
||||
|
||||
@@ -121,11 +121,13 @@ namespace details
|
||||
/// @endcond
|
||||
} // namespace wil
|
||||
|
||||
#ifndef RESULT_SUPPRESS_STATIC_INITIALIZERS
|
||||
// Automatically call RoOriginateError upon error origination by including this file
|
||||
WI_HEADER_INITIALIZATION_FUNCTION(ResultStowedExceptionInitialize, [] {
|
||||
::wil::SetOriginateErrorCallback(::wil::details::RaiseRoOriginateOnWilExceptions);
|
||||
::wil::SetFailfastWithContextCallback(::wil::details::FailfastWithContextCallback);
|
||||
return 1;
|
||||
})
|
||||
#endif // RESULT_SUPPRESS_STATIC_INITIALIZERS
|
||||
|
||||
#endif // __WIL_RESULT_ORIGINATE_INCLUDED
|
||||
|
||||
Vendored
+98
-2
@@ -133,6 +133,7 @@ inline PCWSTR str_raw_ptr(const std::wstring& str)
|
||||
}
|
||||
|
||||
#if __cpp_lib_string_view >= 201606L
|
||||
|
||||
/**
|
||||
zstring_view. A zstring_view is identical to a std::string_view except it is always nul-terminated (unless empty).
|
||||
* zstring_view can be used for storing string literals without "forgetting" the length or that it is nul-terminated.
|
||||
@@ -145,6 +146,26 @@ class basic_zstring_view : public std::basic_string_view<TChar>
|
||||
{
|
||||
using size_type = typename std::basic_string_view<TChar>::size_type;
|
||||
|
||||
template <typename T>
|
||||
struct has_c_str
|
||||
{
|
||||
template <typename U>
|
||||
static auto test(int) -> decltype(std::declval<U>().c_str(), std::true_type());
|
||||
template <typename U>
|
||||
static std::false_type test(...);
|
||||
static constexpr bool value = decltype(test<T>(0))::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct has_size
|
||||
{
|
||||
template <typename U>
|
||||
static auto test(int) -> decltype(std::declval<U>().size() == 1, std::true_type());
|
||||
template <typename U>
|
||||
static std::false_type test(...);
|
||||
static constexpr bool value = decltype(test<T>(0))::value;
|
||||
};
|
||||
|
||||
public:
|
||||
constexpr basic_zstring_view() noexcept = default;
|
||||
constexpr basic_zstring_view(const basic_zstring_view&) noexcept = default;
|
||||
@@ -177,6 +198,16 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
template <typename TSrc, std::enable_if_t<has_c_str<TSrc>::value && has_size<TSrc>::value && std::is_same_v<typename TSrc::value_type, TChar>>* = nullptr>
|
||||
constexpr basic_zstring_view(TSrc const& src) noexcept : std::basic_string_view<TChar>(src.c_str(), src.size())
|
||||
{
|
||||
}
|
||||
|
||||
template <typename TSrc, std::enable_if_t<has_c_str<TSrc>::value && !has_size<TSrc>::value && std::is_same_v<typename TSrc::value_type, TChar>>* = nullptr>
|
||||
constexpr basic_zstring_view(TSrc const& src) noexcept : std::basic_string_view<TChar>(src.c_str())
|
||||
{
|
||||
}
|
||||
|
||||
// basic_string_view [] precondition won't let us read view[view.size()]; so we define our own.
|
||||
WI_NODISCARD constexpr const TChar& operator[](size_type idx) const noexcept
|
||||
{
|
||||
@@ -211,23 +242,88 @@ private:
|
||||
using zstring_view = basic_zstring_view<char>;
|
||||
using zwstring_view = basic_zstring_view<wchar_t>;
|
||||
|
||||
// str_raw_ptr is an overloaded function that retrieves a const pointer to the first character in a string's buffer.
|
||||
// This is the overload for std::wstring. Other overloads available in resource.h.
|
||||
template <typename TChar>
|
||||
inline auto str_raw_ptr(basic_zstring_view<TChar> str)
|
||||
{
|
||||
return str.c_str();
|
||||
}
|
||||
|
||||
inline namespace literals
|
||||
{
|
||||
constexpr zstring_view operator""_zv(const char* str, std::size_t len) noexcept
|
||||
{
|
||||
return zstring_view(str, len);
|
||||
return {str, len};
|
||||
}
|
||||
|
||||
constexpr zwstring_view operator""_zv(const wchar_t* str, std::size_t len) noexcept
|
||||
{
|
||||
return zwstring_view(str, len);
|
||||
return {str, len};
|
||||
}
|
||||
} // namespace literals
|
||||
|
||||
#endif // __cpp_lib_string_view >= 201606L
|
||||
|
||||
#if __WI_LIBCPP_STD_VER >= 17
|
||||
// This is a helper that allows one to construct a functor that has an overloaded operator()
|
||||
// composed from the operator()s of multiple lambdas. It is most useful as the "visitor" for a
|
||||
// std::visit call on a std::variant. A lambda for each type in the variant, and optionally one
|
||||
// generic lambda, can be provided to perform compile time visitation of the std::variant.
|
||||
//
|
||||
// Example:
|
||||
// std::variant<int, bool, double, void*> theVariant;
|
||||
// std::visit(wil::overloaded{
|
||||
// [](int theInt)
|
||||
// {
|
||||
// // Handle int.
|
||||
// },
|
||||
// [](double theDouble)
|
||||
// {
|
||||
// // Handle double.
|
||||
// },
|
||||
// [](auto boolOrVoidPtr)
|
||||
// {
|
||||
// // This will receive all the remaining types. Alternatively, handle each type with
|
||||
// // a lambda that accepts that type. If all types are not handled, you get a
|
||||
// // compile-time error, which makes std::visit superior to an if-else ladder that
|
||||
// // tries to handle each type in the variant.
|
||||
// }},
|
||||
// theVariant);
|
||||
//
|
||||
template <typename... T>
|
||||
struct overloaded final : T...
|
||||
{
|
||||
using T::operator()...;
|
||||
|
||||
// This allows one to use the () syntax to construct the visitor, instead of {}. Both are
|
||||
// equivalent, and the choice ultimately boils down to preference of style.
|
||||
template <typename... Fs>
|
||||
constexpr explicit overloaded(Fs&&... fs) : T{std::forward<Fs>(fs)}...
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// Deduction guide to aid CTAD.
|
||||
template <typename... T>
|
||||
overloaded(T...) -> overloaded<T...>;
|
||||
|
||||
#endif // __WI_LIBCPP_STD_VER >= 17
|
||||
|
||||
} // namespace wil
|
||||
|
||||
// This suppression is a temporary workaround to allow libraries built with C++20 to link into binaries built with
|
||||
// earlier standard versions such as C++17. This appears to be an issue even when this specialization goes unused
|
||||
#ifndef WIL_SUPPRESS_STD_FORMAT_USE
|
||||
#if (__WI_LIBCPP_STD_VER >= 20) && WI_HAS_INCLUDE(<format>, 1) // Assume present if C++20
|
||||
#include <format>
|
||||
template <typename TChar>
|
||||
struct std::formatter<wil::basic_zstring_view<TChar>, TChar> : std::formatter<std::basic_string_view<TChar>, TChar>
|
||||
{
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
#endif // __WIL_STL_INCLUDED
|
||||
|
||||
+187
-80
@@ -38,10 +38,10 @@
|
||||
#endif
|
||||
|
||||
/// @cond
|
||||
#if __cpp_lib_bit_cast >= 201806L
|
||||
#if WIL_USE_STL && (__cpp_lib_bit_cast >= 201806L)
|
||||
#define __WI_CONSTEXPR_BIT_CAST constexpr
|
||||
#else
|
||||
#define __WI_CONSTEXPR_BIT_CAST inline
|
||||
#define __WI_CONSTEXPR_BIT_CAST // All uses are templates, which is implicitly inline
|
||||
#endif
|
||||
/// @endcond
|
||||
|
||||
@@ -130,9 +130,9 @@ struct weak_ordering
|
||||
signed char m_value;
|
||||
};
|
||||
|
||||
inline constexpr weak_ordering weak_ordering::less{static_cast<signed char>(-1)};
|
||||
inline constexpr weak_ordering weak_ordering::equivalent{static_cast<signed char>(0)};
|
||||
inline constexpr weak_ordering weak_ordering::greater{static_cast<signed char>(1)};
|
||||
__WI_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::less{static_cast<signed char>(-1)};
|
||||
__WI_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::equivalent{static_cast<signed char>(0)};
|
||||
__WI_LIBCPP_INLINE_VAR constexpr weak_ordering weak_ordering::greater{static_cast<signed char>(1)};
|
||||
|
||||
#endif
|
||||
} // namespace wistd
|
||||
@@ -207,43 +207,56 @@ namespace filetime_duration
|
||||
|
||||
namespace filetime
|
||||
{
|
||||
constexpr unsigned long long to_int64(const FILETIME& ft) WI_NOEXCEPT
|
||||
template <typename Int64 = unsigned long long, wistd::enable_if_t<wistd::is_integral_v<Int64> && (sizeof(Int64) == sizeof(FILETIME)), int> = 0>
|
||||
constexpr Int64 to_int64(const FILETIME& val) WI_NOEXCEPT
|
||||
{
|
||||
#if __cpp_lib_bit_cast >= 201806L
|
||||
return std::bit_cast<unsigned long long>(ft);
|
||||
#if WIL_USE_STL && (__cpp_lib_bit_cast >= 201806L)
|
||||
return std::bit_cast<Int64>(val);
|
||||
#else
|
||||
// Cannot reinterpret_cast FILETIME* to unsigned long long*
|
||||
// due to alignment differences.
|
||||
return (static_cast<unsigned long long>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
|
||||
// Cannot reinterpret_cast FILETIME* to Int64* due to alignment differences.
|
||||
return (static_cast<Int64>(val.dwHighDateTime) << 32) + val.dwLowDateTime;
|
||||
#endif
|
||||
}
|
||||
|
||||
__WI_CONSTEXPR_BIT_CAST FILETIME from_int64(unsigned long long i64) WI_NOEXCEPT
|
||||
namespace details
|
||||
{
|
||||
#if __cpp_lib_bit_cast >= 201806L
|
||||
template <typename Int>
|
||||
using select_int64 =
|
||||
wistd::conditional_t<sizeof(Int) == 8, Int, wistd::conditional_t<wistd::is_signed_v<Int>, long long, unsigned long long>>;
|
||||
}
|
||||
|
||||
template <typename Int, wistd::enable_if_t<wistd::is_integral_v<Int> && (sizeof(Int) <= sizeof(FILETIME)), int> = 0>
|
||||
__WI_CONSTEXPR_BIT_CAST FILETIME from_int64(Int val) WI_NOEXCEPT
|
||||
{
|
||||
using Int64 = details::select_int64<Int>;
|
||||
auto i64 = static_cast<Int64>(val);
|
||||
|
||||
#if WIL_USE_STL && (__cpp_lib_bit_cast >= 201806L)
|
||||
return std::bit_cast<FILETIME>(i64);
|
||||
#else
|
||||
static_assert(sizeof(i64) == sizeof(FILETIME), "sizes don't match");
|
||||
static_assert(__alignof(unsigned long long) >= __alignof(FILETIME), "alignment not compatible with type pun");
|
||||
static_assert(__alignof(Int64) >= __alignof(FILETIME), "alignment not compatible with type pun");
|
||||
return *reinterpret_cast<FILETIME*>(&i64);
|
||||
#endif
|
||||
}
|
||||
|
||||
__WI_CONSTEXPR_BIT_CAST FILETIME add(_In_ FILETIME const& ft, long long delta100ns) WI_NOEXCEPT
|
||||
template <typename Int, wistd::enable_if_t<wistd::is_integral_v<Int> && (sizeof(Int) <= sizeof(FILETIME)), int> = 0>
|
||||
__WI_CONSTEXPR_BIT_CAST FILETIME add(FILETIME const& baseTime, Int delta100ns) WI_NOEXCEPT
|
||||
{
|
||||
return from_int64(to_int64(ft) + delta100ns);
|
||||
using Int64 = details::select_int64<Int>;
|
||||
return from_int64(to_int64<Int64>(baseTime) + delta100ns);
|
||||
}
|
||||
|
||||
constexpr bool is_empty(const FILETIME& ft) WI_NOEXCEPT
|
||||
constexpr bool is_empty(const FILETIME& val) WI_NOEXCEPT
|
||||
{
|
||||
return (ft.dwHighDateTime == 0) && (ft.dwLowDateTime == 0);
|
||||
return (val.dwHighDateTime == 0) && (val.dwLowDateTime == 0);
|
||||
}
|
||||
|
||||
inline FILETIME get_system_time() WI_NOEXCEPT
|
||||
{
|
||||
FILETIME ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
return ft;
|
||||
FILETIME now;
|
||||
GetSystemTimeAsFileTime(&now);
|
||||
return now;
|
||||
}
|
||||
|
||||
/// Convert time as units of 100 nanoseconds to milliseconds. Fractional milliseconds are truncated.
|
||||
@@ -340,7 +353,7 @@ constexpr rect_type rect_from_size(length_type x, length_type y, length_type wid
|
||||
// Adjust stackBufferLength based on typical result sizes to optimize use and
|
||||
// to test the boundary cases.
|
||||
template <typename string_type, size_t stackBufferLength = 256>
|
||||
HRESULT AdaptFixedSizeToAllocatedResult(string_type& result, wistd::function<HRESULT(PWSTR, size_t, size_t*)> callback) WI_NOEXCEPT
|
||||
HRESULT AdaptFixedSizeToAllocatedResult(string_type& result, const wistd::function<HRESULT(PWSTR, size_t, size_t*)>& callback) WI_NOEXCEPT
|
||||
{
|
||||
details::string_maker<string_type> maker;
|
||||
|
||||
@@ -651,36 +664,72 @@ string_type QueryFullProcessImageNameW(HANDLE processHandle = GetCurrentProcess(
|
||||
THROW_IF_FAILED((wil::QueryFullProcessImageNameW<string_type, stackBufferLength>(processHandle, flags, result)));
|
||||
return result;
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
|
||||
|
||||
// Lookup a DWORD value under HKLM\...\Image File Execution Options\<current process name>
|
||||
namespace details
|
||||
{
|
||||
// Lookup a DWORD value under HKLM\...\Image File Execution Options\<current process name>
|
||||
inline HRESULT GetCurrentProcessExecutionOptionNoThrow(PCWSTR valueName, DWORD defaultValue, DWORD* result)
|
||||
{
|
||||
*result = defaultValue;
|
||||
|
||||
wil::unique_cotaskmem_string filePath;
|
||||
RETURN_IF_FAILED(wil::GetModuleFileNameW<wil::unique_cotaskmem_string>(nullptr, filePath));
|
||||
if (auto lastSlash = wcsrchr(filePath.get(), L'\\'))
|
||||
{
|
||||
const auto fileName = lastSlash + 1;
|
||||
wil::unique_cotaskmem_string keyPath;
|
||||
RETURN_IF_FAILED(wil::str_concat_nothrow<wil::unique_cotaskmem_string>(
|
||||
keyPath, LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\)", fileName));
|
||||
DWORD value{};
|
||||
DWORD sizeofValue = sizeof(value);
|
||||
if (::RegGetValueW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
keyPath.get(),
|
||||
valueName,
|
||||
#ifdef RRF_SUBKEY_WOW6464KEY
|
||||
RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY,
|
||||
#else
|
||||
RRF_RT_REG_DWORD,
|
||||
#endif
|
||||
nullptr,
|
||||
&value,
|
||||
&sizeofValue) == ERROR_SUCCESS)
|
||||
{
|
||||
*result = value;
|
||||
}
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
inline DWORD GetCurrentProcessExecutionOption(PCWSTR valueName, DWORD defaultValue = 0)
|
||||
{
|
||||
auto filePath = wil::GetModuleFileNameW<wil::unique_cotaskmem_string>();
|
||||
if (auto lastSlash = wcsrchr(filePath.get(), L'\\'))
|
||||
DWORD result{};
|
||||
THROW_IF_FAILED(details::GetCurrentProcessExecutionOptionNoThrow(valueName, defaultValue, &result));
|
||||
return result;
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
// No easy return mechanism for err_returncode_policy so skipping it.
|
||||
inline DWORD GetCurrentProcessExecutionOptionNoThrow(PCWSTR valueName, DWORD defaultValue = 0)
|
||||
{
|
||||
DWORD result{};
|
||||
if (FAILED(details::GetCurrentProcessExecutionOptionNoThrow(valueName, defaultValue, &result)))
|
||||
{
|
||||
const auto fileName = lastSlash + 1;
|
||||
auto keyPath = wil::str_concat<wil::unique_cotaskmem_string>(
|
||||
LR"(SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\)", fileName);
|
||||
DWORD value{}, sizeofValue = sizeof(value);
|
||||
if (::RegGetValueW(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
keyPath.get(),
|
||||
valueName,
|
||||
#ifdef RRF_SUBKEY_WOW6464KEY
|
||||
RRF_RT_REG_DWORD | RRF_SUBKEY_WOW6464KEY,
|
||||
#else
|
||||
RRF_RT_REG_DWORD,
|
||||
#endif
|
||||
nullptr,
|
||||
&value,
|
||||
&sizeofValue) == ERROR_SUCCESS)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
return defaultValue;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline DWORD GetCurrentProcessExecutionOptionFailFast(PCWSTR valueName, DWORD defaultValue = 0)
|
||||
{
|
||||
DWORD result{};
|
||||
FAIL_FAST_IF_FAILED(details::GetCurrentProcessExecutionOptionNoThrow(valueName, defaultValue, &result));
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef DebugBreak // Some code defines 'DebugBreak' to garbage to force build breaks in release builds
|
||||
@@ -694,31 +743,58 @@ inline DWORD GetCurrentProcessExecutionOption(PCWSTR valueName, DWORD defaultVal
|
||||
// missing or 0 -> don't break
|
||||
// 1 -> wait for the debugger, continue execution once it is attached
|
||||
// 2 -> wait for the debugger, break here once attached.
|
||||
namespace details
|
||||
{
|
||||
template <typename error_policy>
|
||||
inline void WaitForDebuggerPresent(bool checkRegistryConfig)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
DWORD configValue{1};
|
||||
if (checkRegistryConfig)
|
||||
{
|
||||
// err_returncode_policy will continue running after this line on failure. The default value of zero
|
||||
// will apply in that case so we will still behave reasonably.
|
||||
error_policy::HResult(details::GetCurrentProcessExecutionOptionNoThrow(L"WaitForDebuggerPresent", 0, &configValue));
|
||||
}
|
||||
|
||||
if (configValue == 0)
|
||||
{
|
||||
return; // not configured, don't wait
|
||||
}
|
||||
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
if (configValue == 2)
|
||||
{
|
||||
DebugBreak(); // debugger attached, SHIFT+F11 to return to the caller
|
||||
}
|
||||
return; // debugger now attached, continue executing
|
||||
}
|
||||
Sleep(500);
|
||||
}
|
||||
}
|
||||
} // namespace details
|
||||
|
||||
#ifdef WIL_ENABLE_EXCEPTIONS
|
||||
inline void WaitForDebuggerPresent(bool checkRegistryConfig = true)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
auto configValue = checkRegistryConfig ? GetCurrentProcessExecutionOption(L"WaitForDebuggerPresent") : 1;
|
||||
if (configValue == 0)
|
||||
{
|
||||
return; // not configured, don't wait
|
||||
}
|
||||
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
if (configValue == 2)
|
||||
{
|
||||
DebugBreak(); // debugger attached, SHIFT+F11 to return to the caller
|
||||
}
|
||||
return; // debugger now attached, continue executing
|
||||
}
|
||||
Sleep(500);
|
||||
}
|
||||
details::WaitForDebuggerPresent<err_exception_policy>(checkRegistryConfig);
|
||||
}
|
||||
#endif
|
||||
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
#endif
|
||||
inline void WaitForDebuggerPresentNoThrow(bool checkRegistryConfig = true)
|
||||
{
|
||||
details::WaitForDebuggerPresent<err_returncode_policy>(checkRegistryConfig);
|
||||
}
|
||||
|
||||
inline void WaitForDebuggerPresentFailFast(bool checkRegistryConfig = true)
|
||||
{
|
||||
details::WaitForDebuggerPresent<err_failfast_policy>(checkRegistryConfig);
|
||||
}
|
||||
|
||||
#endif // DebugBreak
|
||||
#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM)
|
||||
|
||||
/** Retrieve the HINSTANCE for the current DLL or EXE using this symbol that
|
||||
the linker provides for every module. This avoids the need for a global HINSTANCE variable
|
||||
@@ -886,10 +962,8 @@ bool init_once(_Inout_ INIT_ONCE& initOnce, T func)
|
||||
completion.success();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif // WIL_ENABLE_EXCEPTIONS
|
||||
|
||||
@@ -897,17 +971,40 @@ bool init_once(_Inout_ INIT_ONCE& initOnce, T func)
|
||||
/// @cond
|
||||
namespace details
|
||||
{
|
||||
// NOTE: We can't have a 'using std::begin' at class scope, hence the workaround for handling both 'begin' with ADL
|
||||
// and 'std::begin' separately. We want to handle both because there's no guarantee the type has a 'begin' method
|
||||
template <typename RangeT>
|
||||
struct deduce_char_type_from_string_range_traits
|
||||
{
|
||||
template <typename U>
|
||||
static std::true_type deduce_has_adl_begin(U&& range, std::void_t<decltype((*begin(range))[0])>*);
|
||||
template <typename U>
|
||||
static std::false_type deduce_has_adl_begin(U&&, ...);
|
||||
|
||||
template <typename U>
|
||||
static std::true_type deduce_has_std_begin(U&& range, std::void_t<decltype((*std::begin(range))[0])>*);
|
||||
template <typename U>
|
||||
static std::false_type deduce_has_std_begin(U&&, ...);
|
||||
|
||||
static constexpr bool has_adl_begin = decltype(deduce_has_adl_begin(std::declval<RangeT>(), nullptr))::value;
|
||||
static constexpr bool has_std_begin = decltype(deduce_has_std_begin(std::declval<RangeT>(), nullptr))::value;
|
||||
};
|
||||
|
||||
template <typename RangeT, bool hasAdlBegin = deduce_char_type_from_string_range_traits<RangeT>::has_adl_begin, bool hasStdBegin = deduce_char_type_from_string_range_traits<RangeT>::has_std_begin>
|
||||
struct deduce_char_type_from_string_range
|
||||
{
|
||||
template <typename T = RangeT>
|
||||
static auto deduce(T& range)
|
||||
{
|
||||
using std::begin;
|
||||
return (*begin(range))[0];
|
||||
}
|
||||
};
|
||||
|
||||
using type = decltype(deduce(wistd::declval<RangeT&>()));
|
||||
template <typename RangeT, bool hasStdBegin>
|
||||
struct deduce_char_type_from_string_range<RangeT, true, hasStdBegin>
|
||||
{
|
||||
using type = std::decay_t<decltype((*begin(std::declval<RangeT>()))[0])>;
|
||||
};
|
||||
|
||||
template <typename RangeT>
|
||||
struct deduce_char_type_from_string_range<RangeT, false, true>
|
||||
{
|
||||
using type = std::decay_t<decltype((*std::begin(std::declval<RangeT>()))[0])>;
|
||||
};
|
||||
|
||||
template <typename RangeT>
|
||||
@@ -979,6 +1076,7 @@ inline std::basic_string<CharT> ArgvToCommandLine(RangeT&& range, ArgvToCommandL
|
||||
// Somewhat of a hack to avoid the fact that we can't conditionalize a string literal on a template
|
||||
static constexpr const CharT empty_string[] = {'\0'};
|
||||
static constexpr const CharT single_quote_string[] = {'"', '\0'};
|
||||
static constexpr const CharT double_quote_string[] = {'"', '"', '\0'};
|
||||
static constexpr const CharT space_string[] = {' ', '\0'};
|
||||
static constexpr const CharT quoted_space_string[] = {'"', ' ', '"', '\0'};
|
||||
|
||||
@@ -996,6 +1094,7 @@ inline std::basic_string<CharT> ArgvToCommandLine(RangeT&& range, ArgvToCommandL
|
||||
{
|
||||
auto currentIndex = index++;
|
||||
result += prefix;
|
||||
prefix = nextPrefix;
|
||||
|
||||
const CharT* searchString = initialSearchString;
|
||||
|
||||
@@ -1005,6 +1104,14 @@ inline std::basic_string<CharT> ArgvToCommandLine(RangeT&& range, ArgvToCommandL
|
||||
|
||||
// We need to escape any quotes and CONDITIONALLY any backslashes
|
||||
string_view_type str(strRaw);
|
||||
if (str.empty() && !forceQuotes)
|
||||
{
|
||||
// The argument is empty. If we want to preserve it in the command line string, we need to manually insert
|
||||
// a pair of quotes since normal parsing won't handle this case
|
||||
result.append(double_quote_string);
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t pos = 0;
|
||||
while (pos < str.size())
|
||||
{
|
||||
@@ -1023,7 +1130,9 @@ inline std::basic_string<CharT> ArgvToCommandLine(RangeT&& range, ArgvToCommandL
|
||||
result.append(str, pos, nextPos - pos);
|
||||
pos = nextPos;
|
||||
if (pos == str.npos)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (str[pos] == '"')
|
||||
{
|
||||
@@ -1102,8 +1211,6 @@ inline std::basic_string<CharT> ArgvToCommandLine(RangeT&& range, ArgvToCommandL
|
||||
{
|
||||
result.push_back('"');
|
||||
}
|
||||
|
||||
prefix = nextPrefix;
|
||||
}
|
||||
|
||||
// NOTE: We optimize the force quotes case by including them in the prefix string. We're not appending a prefix
|
||||
@@ -1137,6 +1244,6 @@ inline std::basic_string<wistd::remove_cv_t<CharT>> ArgvToCommandLine(
|
||||
// sendMail(0, 0, pmm, MAPI_USE_DEFAULT, 0);
|
||||
// }
|
||||
// Declaration
|
||||
#define GetProcAddressByFunctionDeclaration(hinst, fn) reinterpret_cast<decltype(::fn)*>(GetProcAddress(hinst, #fn))
|
||||
#define GetProcAddressByFunctionDeclaration(hinst, fn) (reinterpret_cast<decltype(::fn)*>(GetProcAddress(hinst, #fn)))
|
||||
|
||||
#endif // __WIL_WIN32_HELPERS_INCLUDED
|
||||
|
||||
+39
-4
@@ -115,8 +115,8 @@
|
||||
#define __WI_PUSH_WARNINGS __pragma(warning(push))
|
||||
#define __WI_POP_WARNINGS __pragma(warning(pop))
|
||||
#elif defined(__WI_LIBCPP_COMPILER_CLANG)
|
||||
#define __WI_PUSH_WARNINGS __pragma(clang diagnostic push)
|
||||
#define __WI_POP_WARNINGS __pragma(clang diagnostic pop)
|
||||
#define __WI_PUSH_WARNINGS _Pragma("clang diagnostic push")
|
||||
#define __WI_POP_WARNINGS _Pragma("clang diagnostic pop")
|
||||
#else
|
||||
#define __WI_PUSH_WARNINGS
|
||||
#define __WI_POP_WARNINGS
|
||||
@@ -129,7 +129,8 @@
|
||||
#endif
|
||||
|
||||
#ifdef __WI_LIBCPP_COMPILER_CLANG
|
||||
#define __WI_CLANG_DISABLE_WARNING(warning) __pragma(clang diagnostic ignored #warning)
|
||||
#define __WI_CLANG_DISABLE_WARNING_AUX(x) _Pragma(#x)
|
||||
#define __WI_CLANG_DISABLE_WARNING(w) __WI_CLANG_DISABLE_WARNING_AUX(clang diagnostic ignored #w)
|
||||
#else
|
||||
#define __WI_CLANG_DISABLE_WARNING(warning)
|
||||
#endif
|
||||
@@ -203,7 +204,11 @@
|
||||
#define __WI_HAS_FEATURE_IS_UNION __has_feature(is_union)
|
||||
#define __WI_HAS_FEATURE_IS_CLASS __has_feature(is_class)
|
||||
#define __WI_HAS_FEATURE_IS_ENUM __has_feature(is_enum)
|
||||
#ifdef __WI_LIBCPP_COMPILER_GCC
|
||||
#define __WI_HAS_FEATURE_IS_CONVERTIBLE_TO 0
|
||||
#else
|
||||
#define __WI_HAS_FEATURE_IS_CONVERTIBLE_TO __has_feature(is_convertible_to)
|
||||
#endif
|
||||
#define __WI_HAS_FEATURE_IS_EMPTY __has_feature(is_empty)
|
||||
#define __WI_HAS_FEATURE_IS_POLYMORPHIC __has_feature(is_polymorphic)
|
||||
#define __WI_HAS_FEATURE_HAS_VIRTUAL_DESTRUCTOR __has_feature(has_virtual_destructor)
|
||||
@@ -222,19 +227,33 @@
|
||||
#define __WI_HAS_FEATURE_HAS_NOTHROW_COPY __has_feature(has_nothrow_copy) || (__WI_GNUC_VER >= 403)
|
||||
#define __WI_HAS_FEATURE_HAS_NOTHROW_ASSIGN __has_feature(has_nothrow_assign) || (__WI_GNUC_VER >= 403)
|
||||
|
||||
#ifdef __clang__
|
||||
#if !(__has_feature(cxx_noexcept))
|
||||
#define __WI_LIBCPP_HAS_NO_NOEXCEPT
|
||||
#endif
|
||||
#else
|
||||
#if __cplusplus < 201103L
|
||||
#define __WI_LIBCPP_HAS_NO_NOEXCEPT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !__is_identifier(__has_unique_object_representations) || __WI_GNUC_VER >= 700
|
||||
#define __WI_LIBCPP_HAS_UNIQUE_OBJECT_REPRESENTATIONS
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#if !(__has_feature(cxx_variadic_templates))
|
||||
#define __WI_LIBCPP_HAS_NO_VARIADICS
|
||||
#endif
|
||||
#else
|
||||
#if __cplusplus < 201103L
|
||||
#define __WI_LIBCPP_HAS_NO_VARIADICS
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __has_feature(is_literal) || __WI_GNUC_VER >= 407
|
||||
#if defined(__MINGW32__)
|
||||
#define __WI_LIBCPP_IS_LITERAL(T) __is_literal_type(T)
|
||||
#elif __has_feature(is_literal) || __WI_GNUC_VER >= 407
|
||||
#define __WI_LIBCPP_IS_LITERAL(T) __is_literal(T)
|
||||
#endif
|
||||
|
||||
@@ -258,13 +277,25 @@
|
||||
#define __WI_LIBCPP_NO_RTTI
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#if !(__has_feature(cxx_variable_templates))
|
||||
#define __WI_LIBCPP_HAS_NO_VARIABLE_TEMPLATES
|
||||
#endif
|
||||
#else
|
||||
#if __cplusplus < 201103L
|
||||
#define __WI_LIBCPP_HAS_NO_VARIABLE_TEMPLATES
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#if !(__has_feature(cxx_relaxed_constexpr))
|
||||
#define __WI_LIBCPP_HAS_NO_CXX14_CONSTEXPR
|
||||
#endif
|
||||
#else
|
||||
#if __cplusplus < 201103L
|
||||
#define __WI_LIBCPP_HAS_NO_CXX14_CONSTEXPR
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if !__has_builtin(__builtin_addressof) && _GNUC_VER < 700
|
||||
#define __WI_LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
|
||||
@@ -473,7 +504,11 @@
|
||||
|
||||
namespace wistd // ("Windows Implementation" std)
|
||||
{
|
||||
#ifdef __MINGW32__
|
||||
using nullptr_t = decltype(nullptr);
|
||||
#else
|
||||
using nullptr_t = decltype(__nullptr);
|
||||
#endif
|
||||
|
||||
template <class _T1, class _T2 = _T1>
|
||||
struct __less
|
||||
|
||||
+83
-50
@@ -388,23 +388,27 @@ __WI_LIBCPP_INLINE_VAR __WI_LIBCPP_CONSTEXPR bool is_void_v = is_void<_Tp>::valu
|
||||
|
||||
// __is_nullptr_t
|
||||
|
||||
template <class _Tp>
|
||||
struct __is_nullptr_t_impl : public false_type
|
||||
namespace details
|
||||
{
|
||||
};
|
||||
template <>
|
||||
struct __is_nullptr_t_impl<nullptr_t> : public true_type
|
||||
{
|
||||
};
|
||||
template <class _Tp>
|
||||
struct is_nullptr_t_impl : false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <>
|
||||
struct is_nullptr_t_impl<nullptr_t> : true_type
|
||||
{
|
||||
};
|
||||
} // namespace details
|
||||
|
||||
template <class _Tp>
|
||||
struct __WI_LIBCPP_TEMPLATE_VIS __is_nullptr_t : public __is_nullptr_t_impl<typename remove_cv<_Tp>::type>
|
||||
struct __WI_LIBCPP_TEMPLATE_VIS __is_nullptr_t : details::is_nullptr_t_impl<typename remove_cv<_Tp>::type>
|
||||
{
|
||||
};
|
||||
|
||||
#if __WI_LIBCPP_STD_VER > 11
|
||||
template <class _Tp>
|
||||
struct __WI_LIBCPP_TEMPLATE_VIS is_null_pointer : public __is_nullptr_t_impl<typename remove_cv<_Tp>::type>
|
||||
struct __WI_LIBCPP_TEMPLATE_VIS is_null_pointer : details::is_nullptr_t_impl<typename remove_cv<_Tp>::type>
|
||||
{
|
||||
};
|
||||
|
||||
@@ -1189,9 +1193,14 @@ using type_identity_t = typename type_identity<_Tp>::type;
|
||||
|
||||
// is_signed
|
||||
|
||||
__WI_PUSH_WARNINGS
|
||||
__WI_MSVC_DISABLE_WARNING(4296) // error C4296: '<': expression is always false
|
||||
|
||||
template <class _Tp, bool = is_integral<_Tp>::value>
|
||||
struct __libcpp_is_signed_impl : public __WI_LIBCPP_BOOL_CONSTANT(_Tp(-1) < _Tp(0)){};
|
||||
|
||||
__WI_POP_WARNINGS
|
||||
|
||||
template <class _Tp>
|
||||
struct __libcpp_is_signed_impl<_Tp, false> : public true_type
|
||||
{
|
||||
@@ -1488,18 +1497,18 @@ struct __WI_LIBCPP_TEMPLATE_VIS is_convertible
|
||||
|
||||
#else // __WI_HAS_FEATURE_IS_CONVERTIBLE_TO
|
||||
|
||||
namespace __is_convertible_imp
|
||||
namespace wi_is_convertible_imp
|
||||
{
|
||||
template <class _Tp>
|
||||
void __test_convert(_Tp);
|
||||
|
||||
template <class _From, class _To, class = void>
|
||||
struct __is_convertible_test : public false_type
|
||||
struct wi_is_convertible_test : public false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class _From, class _To>
|
||||
struct __is_convertible_test<_From, _To, decltype(__is_convertible_imp::__test_convert<_To>(declval<_From>()))> : public true_type
|
||||
struct wi_is_convertible_test<_From, _To, decltype(wi_is_convertible_imp::__test_convert<_To>(declval<_From>()))> : public true_type
|
||||
{
|
||||
};
|
||||
|
||||
@@ -1535,16 +1544,16 @@ namespace __is_convertible_imp
|
||||
value = 3
|
||||
};
|
||||
};
|
||||
} // namespace __is_convertible_imp
|
||||
} // namespace wi_is_convertible_imp
|
||||
|
||||
template <class _Tp, unsigned = __is_convertible_imp::__is_array_function_or_void<typename remove_reference<_Tp>::type>::value>
|
||||
struct __is_convertible_check
|
||||
template <class _Tp, unsigned = wi_is_convertible_imp::__is_array_function_or_void<typename remove_reference<_Tp>::type>::value>
|
||||
struct wi_is_convertible_check
|
||||
{
|
||||
static const size_t __v = 0;
|
||||
};
|
||||
|
||||
template <class _Tp>
|
||||
struct __is_convertible_check<_Tp, 0>
|
||||
struct wi_is_convertible_check<_Tp, 0>
|
||||
{
|
||||
static const size_t __v = sizeof(_Tp);
|
||||
};
|
||||
@@ -1552,12 +1561,12 @@ struct __is_convertible_check<_Tp, 0>
|
||||
template <
|
||||
class _T1,
|
||||
class _T2,
|
||||
unsigned _T1_is_array_function_or_void = __is_convertible_imp::__is_array_function_or_void<_T1>::value,
|
||||
unsigned _T2_is_array_function_or_void = __is_convertible_imp::__is_array_function_or_void<_T2>::value>
|
||||
struct __is_convertible
|
||||
unsigned _T1_is_array_function_or_void = wi_is_convertible_imp::__is_array_function_or_void<_T1>::value,
|
||||
unsigned _T2_is_array_function_or_void = wi_is_convertible_imp::__is_array_function_or_void<_T2>::value>
|
||||
struct wi_is_convertible
|
||||
: public integral_constant<
|
||||
bool,
|
||||
__is_convertible_imp::__is_convertible_test<_T1, _T2>::value
|
||||
wi_is_convertible_imp::wi_is_convertible_test<_T1, _T2>::value
|
||||
#if defined(__WI_LIBCPP_HAS_NO_RVALUE_REFERENCES)
|
||||
&& !(!is_function<_T1>::value && !is_reference<_T1>::value && is_reference<_T2>::value &&
|
||||
(!is_const<typename remove_reference<_T2>::type>::value || is_volatile<typename remove_reference<_T2>::type>::value) &&
|
||||
@@ -1567,37 +1576,61 @@ struct __is_convertible
|
||||
>{};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 0, 1> : public false_type{};
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 1, 1> : public false_type{};
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 2, 1> : public false_type{};
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 3, 1> : public false_type{};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 0, 2> : public false_type{};
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 1, 2> : public false_type{};
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 2, 2> : public false_type{};
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 3, 2> : public false_type{};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 0, 3> : public false_type{};
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 1, 3> : public false_type{};
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 2, 3> : public false_type{};
|
||||
template <class _T1, class _T2>
|
||||
struct __is_convertible<_T1, _T2, 3, 3> : public true_type{};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct __WI_LIBCPP_TEMPLATE_VIS is_convertible : public __is_convertible<_T1, _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 0, 1> : public false_type
|
||||
{
|
||||
static const size_t __complete_check1 = __is_convertible_check<_T1>::__v;
|
||||
static const size_t __complete_check2 = __is_convertible_check<_T2>::__v;
|
||||
};
|
||||
template <class _T1, class _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 1, 1> : public false_type
|
||||
{
|
||||
};
|
||||
template <class _T1, class _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 2, 1> : public false_type
|
||||
{
|
||||
};
|
||||
template <class _T1, class _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 3, 1> : public false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 0, 2> : public false_type
|
||||
{
|
||||
};
|
||||
template <class _T1, class _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 1, 2> : public false_type
|
||||
{
|
||||
};
|
||||
template <class _T1, class _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 2, 2> : public false_type
|
||||
{
|
||||
};
|
||||
template <class _T1, class _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 3, 2> : public false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 0, 3> : public false_type
|
||||
{
|
||||
};
|
||||
template <class _T1, class _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 1, 3> : public false_type
|
||||
{
|
||||
};
|
||||
template <class _T1, class _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 2, 3> : public false_type
|
||||
{
|
||||
};
|
||||
template <class _T1, class _T2>
|
||||
struct wi_is_convertible<_T1, _T2, 3, 3> : public true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <class _T1, class _T2>
|
||||
struct __WI_LIBCPP_TEMPLATE_VIS is_convertible : public wi_is_convertible<_T1, _T2>
|
||||
{
|
||||
static const size_t __complete_check1 = wi_is_convertible_check<_T1>::__v;
|
||||
static const size_t __complete_check2 = wi_is_convertible_check<_T2>::__v;
|
||||
};
|
||||
|
||||
#endif // __WI_HAS_FEATURE_IS_CONVERTIBLE_TO
|
||||
|
||||
Vendored
+80
-27
@@ -37,8 +37,19 @@
|
||||
#define XBYAK_GNUC_PREREQ(major, minor) 0
|
||||
#endif
|
||||
|
||||
// User defined (must define all 3)
|
||||
#if defined(XBYAK_STD_UNORDERED_SET) || defined(XBYAK_STD_UNORDERED_MAP) || defined(XBYAK_STD_UNORDERED_MULTIMAP)
|
||||
#ifndef XBYAK_STD_UNORDERED_SET
|
||||
#error "Define XBYAK_STD_UNORDERED_SET"
|
||||
#endif
|
||||
#ifndef XBYAK_STD_UNORDERED_MAP
|
||||
#error "Define XBYAK_STD_UNORDERED_MAP"
|
||||
#endif
|
||||
#ifndef XBYAK_STD_UNORDERED_MULTIMAP
|
||||
#error "Define XBYAK_STD_UNORDERED_MULTIMAP"
|
||||
#endif
|
||||
// This covers -std=(gnu|c)++(0x|11|1y), -stdlib=libc++, and modern Microsoft.
|
||||
#if ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\
|
||||
#elif ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\
|
||||
((__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)))
|
||||
#include <unordered_set>
|
||||
#define XBYAK_STD_UNORDERED_SET std::unordered_set
|
||||
@@ -163,7 +174,7 @@ namespace Xbyak {
|
||||
|
||||
enum {
|
||||
DEFAULT_MAX_CODE_SIZE = 4096,
|
||||
VERSION = 0x7300 /* 0xABCD = A.BC(.D) */
|
||||
VERSION = 0x7352 /* 0xABCD = A.BC(.D) */
|
||||
};
|
||||
|
||||
#ifndef MIE_INTEGER_TYPE_DEFINED
|
||||
@@ -242,6 +253,8 @@ enum {
|
||||
ERR_INVALID_REG_IDX,
|
||||
ERR_BAD_ENCODING_MODE,
|
||||
ERR_CANT_USE_ABCDH,
|
||||
ERR_CANT_INIT_CPUTOPOLOGY,
|
||||
ERR_INVALID_CPUMASK_INDEX,
|
||||
ERR_INTERNAL // Put it at last.
|
||||
};
|
||||
|
||||
@@ -302,6 +315,8 @@ inline const char *ConvertErrorToString(int err)
|
||||
"invalid reg index",
|
||||
"bad encoding mode",
|
||||
"can't use [abcd]h with rex",
|
||||
"can't init CpuTopology",
|
||||
"invalid cpumask index",
|
||||
"internal error"
|
||||
};
|
||||
assert(ERR_INTERNAL + 1 == sizeof(errTbl) / sizeof(*errTbl));
|
||||
@@ -518,7 +533,13 @@ public:
|
||||
}
|
||||
}
|
||||
#endif
|
||||
void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, mode, fd, 0);
|
||||
int prot = PROT_READ | PROT_WRITE;
|
||||
#ifdef PROT_MPROTECT
|
||||
// Some NetBSD systems have this protection turned on by default
|
||||
// https://man.netbsd.org/mprotect.2
|
||||
prot |= PROT_MPROTECT(PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
#endif
|
||||
void *p = mmap(NULL, size, prot, mode, fd, 0);
|
||||
if (p == MAP_FAILED) {
|
||||
if (fd != -1) close(fd);
|
||||
XBYAK_THROW_RET(ERR_CANT_ALLOC, 0)
|
||||
@@ -984,14 +1005,14 @@ public:
|
||||
#else
|
||||
enum { i32e = 32 };
|
||||
#endif
|
||||
XBYAK_CONSTEXPR RegExp() : scale_(0), disp_(0), label_(0), rip_(false), setLabel_(false) { }
|
||||
XBYAK_CONSTEXPR RegExp(size_t disp) : scale_(0), disp_(disp), label_(0), rip_(false), setLabel_(false) { }
|
||||
XBYAK_CONSTEXPR RegExp() : scale_(0), disp_(0), label_(0), rip_(false), asPtr_(false) { }
|
||||
XBYAK_CONSTEXPR RegExp(size_t disp) : scale_(0), disp_(disp), label_(0), rip_(false), asPtr_(false) { }
|
||||
XBYAK_CONSTEXPR RegExp(const Reg& r, int scale = 1)
|
||||
: scale_(scale)
|
||||
, disp_(0)
|
||||
, label_(0)
|
||||
, rip_(false)
|
||||
, setLabel_(false)
|
||||
, asPtr_(false)
|
||||
{
|
||||
if (!r.isREG(i32e) && !r.is(Reg::XMM|Reg::YMM|Reg::ZMM|Reg::TMM)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER)
|
||||
if (scale == 0) return;
|
||||
@@ -1004,21 +1025,22 @@ public:
|
||||
}
|
||||
RegExp(Label& label);
|
||||
|
||||
RegExp(const void *addr)
|
||||
: scale_(1)
|
||||
// can't use constexpr to const void *
|
||||
explicit RegExp(const void *addr)
|
||||
: scale_(0)
|
||||
, disp_(size_t(addr))
|
||||
, label_(0)
|
||||
, rip_(false)
|
||||
, setLabel_(true)
|
||||
, asPtr_(true)
|
||||
{
|
||||
}
|
||||
#ifdef XBYAK64
|
||||
RegExp(const RegRip& /*rip*/)
|
||||
XBYAK_CONSTEXPR RegExp(const RegRip& /*rip*/)
|
||||
: scale_(0)
|
||||
, disp_(0)
|
||||
, label_(0)
|
||||
, rip_(true)
|
||||
, setLabel_(false)
|
||||
, asPtr_(false)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
@@ -1052,6 +1074,7 @@ public:
|
||||
}
|
||||
}
|
||||
friend RegExp operator+(const RegExp& a, const RegExp& b);
|
||||
friend RegExp operator+(const RegExp& e, size_t disp);
|
||||
friend RegExp operator-(const RegExp& e, size_t disp);
|
||||
private:
|
||||
/*
|
||||
@@ -1064,7 +1087,7 @@ private:
|
||||
size_t disp_; // absolute address
|
||||
Label *label_;
|
||||
bool rip_;
|
||||
bool setLabel_; // disp_ contains the address of label
|
||||
bool asPtr_; // disp_ contains a pointer
|
||||
};
|
||||
|
||||
inline RegExp operator+(const RegExp& a, const RegExp& b)
|
||||
@@ -1073,10 +1096,10 @@ inline RegExp operator+(const RegExp& a, const RegExp& b)
|
||||
if (a.label_ && b.label_) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegExp())
|
||||
if (b.rip_) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegExp())
|
||||
if (a.rip_ && !b.isOnlyDisp()) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegExp())
|
||||
if (a.setLabel_ && b.setLabel_) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegExp())
|
||||
if (a.asPtr_ && b.asPtr_) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegExp())
|
||||
RegExp ret = a;
|
||||
if (ret.label_ == 0) ret.label_ = b.label_;
|
||||
if (ret.setLabel_ == 0) ret.setLabel_ = b.setLabel_;
|
||||
if (ret.asPtr_ == 0) ret.asPtr_ = b.asPtr_;
|
||||
if (!ret.index_.getBit()) { ret.index_ = b.index_; ret.scale_ = b.scale_; }
|
||||
if (b.base_.getBit()) {
|
||||
if (ret.base_.getBit()) {
|
||||
@@ -1101,8 +1124,19 @@ inline RegExp operator*(int scale, const Reg& r)
|
||||
{
|
||||
return r * scale;
|
||||
}
|
||||
// backward compatibility for eax+0
|
||||
inline RegExp operator+(const RegExp& a, size_t b) { return a + RegExp(b); }
|
||||
|
||||
// backward compatibility for eax+&x (pointer address)
|
||||
inline RegExp operator+(const RegExp& a, const void* b) { return a + RegExp(b); }
|
||||
|
||||
// overload for integer literals (e.g. eax+0) to avoid ambiguity with the void* overload
|
||||
inline RegExp operator+(const RegExp& e, int disp) { return e + size_t(disp); }
|
||||
|
||||
inline RegExp operator+(const RegExp& e, size_t disp)
|
||||
{
|
||||
RegExp ret = e;
|
||||
ret.disp_ += disp;
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline RegExp operator-(const RegExp& e, size_t disp)
|
||||
{
|
||||
@@ -1351,11 +1385,15 @@ public:
|
||||
|
||||
class Address : public Operand {
|
||||
public:
|
||||
XBYAK_CONSTEXPR Address()
|
||||
: Operand(0, MEM, 0), e_(), label_(NULL), mode_(inner::M_ModRM), immSize(0),
|
||||
disp8N(0), permitVsib(false), broadcast_(false), optimize_(true) { }
|
||||
XBYAK_CONSTEXPR Address(uint32_t sizeBit, bool broadcast, const RegExp& e)
|
||||
: Operand(0, MEM, sizeBit), e_(e), label_(e.label_), mode_(), immSize(0), disp8N(0), permitVsib(false), broadcast_(broadcast), optimize_(true)
|
||||
: Operand(0, MEM, sizeBit), e_(e), label_(e.label_), mode_(), immSize(0),
|
||||
disp8N(0), permitVsib(false), broadcast_(broadcast), optimize_(true)
|
||||
{
|
||||
if (e.rip_) {
|
||||
mode_ = (e.label_ || e.setLabel_) ? inner::M_ripAddr : inner::M_rip;
|
||||
mode_ = (e.label_ || e.asPtr_) ? inner::M_ripAddr : inner::M_rip;
|
||||
} else {
|
||||
#ifdef XBYAK64
|
||||
uint64_t disp = e.getDisp();
|
||||
@@ -1435,6 +1473,10 @@ public:
|
||||
{
|
||||
return Address(bit_, broadcast_, e);
|
||||
}
|
||||
Address operator[](const void *addr) const
|
||||
{
|
||||
return operator[](RegExp(addr));
|
||||
}
|
||||
};
|
||||
|
||||
struct JmpLabel {
|
||||
@@ -1483,7 +1525,7 @@ inline RegExp::RegExp(Label& label)
|
||||
, disp_(0)
|
||||
, label_(0)
|
||||
, rip_(false)
|
||||
, setLabel_(true)
|
||||
, asPtr_(true)
|
||||
{
|
||||
const uint8_t *addr = label.getAddress();
|
||||
if (addr) {
|
||||
@@ -2253,6 +2295,7 @@ private:
|
||||
size_t disp = addr.getDisp();
|
||||
if (addr.getMode() == inner::M_ripAddr) {
|
||||
if (isAutoGrow()) XBYAK_THROW(ERR_INVALID_RIP_IN_AUTO_GROW)
|
||||
// compute the relative offset to the pointer address
|
||||
disp -= (size_t)getCurr() + 4 + addr.immSize;
|
||||
}
|
||||
dd(inner::VerifyInInt32(disp));
|
||||
@@ -3353,11 +3396,14 @@ public:
|
||||
opAVX10ZeroExt(op1, op2, typeTbl, codeTbl, enc, 16|32|64);
|
||||
}
|
||||
/*
|
||||
use single byte nop if useMultiByteNop = false
|
||||
useMultiByteNop
|
||||
= 0: use only single byte nop
|
||||
= 1: recommended multi-byte
|
||||
= 2: better for newer CPUs
|
||||
*/
|
||||
void nop(size_t size = 1, bool useMultiByteNop = true)
|
||||
void nop(size_t size = 1, int useMultiByteNop = 2)
|
||||
{
|
||||
if (!useMultiByteNop) {
|
||||
if (useMultiByteNop == 0) {
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
db(0x90);
|
||||
}
|
||||
@@ -3368,8 +3414,9 @@ public:
|
||||
recommended multi-byte sequence of NOP instruction
|
||||
AMD and Intel seem to agree on the same sequences for up to 9 bytes:
|
||||
https://support.amd.com/TechDocs/55723_SOG_Fam_17h_Processors_3.00.pdf
|
||||
10~15 byte nop in Software Optimization Guide for the AMD Zen4 Microarchitecture No. 57647
|
||||
*/
|
||||
static const uint8_t nopTbl[9][9] = {
|
||||
static const uint8_t nopTbl[][15] = {
|
||||
{0x90},
|
||||
{0x66, 0x90},
|
||||
{0x0F, 0x1F, 0x00},
|
||||
@@ -3378,9 +3425,15 @@ public:
|
||||
{0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
|
||||
{0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, // 9
|
||||
{0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, // 11
|
||||
{0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
};
|
||||
const size_t n = sizeof(nopTbl) / sizeof(nopTbl[0]);
|
||||
const size_t n = useMultiByteNop == 2 ? sizeof(nopTbl) / sizeof(nopTbl[0]) : 9;
|
||||
while (size > 0) {
|
||||
size_t len = (std::min)(n, size);
|
||||
const uint8_t *seq = nopTbl[len - 1];
|
||||
@@ -3391,9 +3444,9 @@ public:
|
||||
#ifndef XBYAK_DONT_READ_LIST
|
||||
#include "xbyak_mnemonic.h"
|
||||
/*
|
||||
use single byte nop if useMultiByteNop = false
|
||||
use single byte nop if useMultiByteNop = 0
|
||||
*/
|
||||
void align(size_t x = 16, bool useMultiByteNop = true)
|
||||
void align(size_t x = 16, int useMultiByteNop = 2)
|
||||
{
|
||||
if (x == 1) return;
|
||||
if (x < 1 || (x & (x - 1))) XBYAK_THROW(ERR_BAD_ALIGN)
|
||||
|
||||
+3
-18
@@ -1,4 +1,4 @@
|
||||
const char *getVersionString() const { return "7.30"; }
|
||||
const char *getVersionString() const { return "7.35.2"; }
|
||||
void aadd(const Address& addr, const Reg32e ®) { opMR(addr, reg, T_0F38, 0x0FC, T_APX); }
|
||||
void aand(const Address& addr, const Reg32e ®) { opMR(addr, reg, T_0F38|T_66, 0x0FC, T_APX|T_66); }
|
||||
void adc(const Operand& op, uint32_t imm) { opOI(op, imm, 0x10, 2); }
|
||||
@@ -848,6 +848,7 @@ void por(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEB); }
|
||||
void prefetchit0(const Address& addr) { opMR(addr, Reg32(7), T_0F, 0x18); }
|
||||
void prefetchit1(const Address& addr) { opMR(addr, Reg32(6), T_0F, 0x18); }
|
||||
void prefetchnta(const Address& addr) { opMR(addr, Reg32(0), T_0F, 0x18); }
|
||||
void prefetchrst2(const Address& addr) { opMR(addr, Reg32(4), T_0F, 0x18); }
|
||||
void prefetcht0(const Address& addr) { opMR(addr, Reg32(1), T_0F, 0x18); }
|
||||
void prefetcht1(const Address& addr) { opMR(addr, Reg32(2), T_0F, 0x18); }
|
||||
void prefetcht2(const Address& addr) { opMR(addr, Reg32(3), T_0F, 0x18); }
|
||||
@@ -1874,7 +1875,7 @@ void clui() { db(0xF3); db(0x0F); db(0x01); db(0xEE); }
|
||||
void stui() { db(0xF3); db(0x0F); db(0x01); db(0xEF); }
|
||||
void testui() { db(0xF3); db(0x0F); db(0x01); db(0xED); }
|
||||
void uiret() { db(0xF3); db(0x0F); db(0x01); db(0xEC); }
|
||||
void cmpxchg16b(const Address& addr) { opMR(addr, Reg64(1), T_0F, 0xC7); }
|
||||
void cmpxchg16b(const Address& addr) { opMR(addr, Reg64(1), T_0F|T_ALLOW_DIFF_SIZE, 0xC7); }
|
||||
void fxrstor64(const Address& addr) { opMR(addr, Reg64(1), T_0F, 0xAE); }
|
||||
void movq(const Reg64& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opSSE(mmx, reg, T_0F, 0x7E); }
|
||||
void movq(const Mmx& mmx, const Reg64& reg) { if (mmx.isXMM()) db(0x66); opSSE(mmx, reg, T_0F, 0x6E); }
|
||||
@@ -1937,31 +1938,15 @@ void tdphf8ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2,
|
||||
void tmmultf32ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_66|T_0F38|T_W0, 0x48); }
|
||||
void tcmmimfp16ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_66|T_0F38|T_W0, 0x6C); }
|
||||
void tcmmrlfp16ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_0F38|T_W0, 0x6C); }
|
||||
void tconjtcmmimfp16ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_0F38|T_W0, 0x6B); }
|
||||
void ttcmmimfp16ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F2|T_0F38|T_W0, 0x6B); }
|
||||
void ttcmmrlfp16ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F3|T_0F38|T_W0, 0x6B); }
|
||||
void ttdpbf16ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F3|T_0F38|T_W0, 0x6C); }
|
||||
void ttdpfp16ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F2|T_0F38|T_W0, 0x6C); }
|
||||
void ttmmultf32ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_0F38|T_W0, 0x48); }
|
||||
void tileloadd(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_F2|T_0F38|T_W0, 0x4B); }
|
||||
void tileloaddt1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_66|T_0F38|T_W0, 0x4B); }
|
||||
void tileloaddrs(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_F2|T_0F38|T_W0, 0x4A); }
|
||||
void tileloaddrst1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_66|T_0F38|T_W0, 0x4A); }
|
||||
void t2rpntlvwz0(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_0F38|T_W0, 0x6E); }
|
||||
void t2rpntlvwz0t1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_0F38|T_W0, 0x6F); }
|
||||
void t2rpntlvwz1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_66|T_0F38|T_W0, 0x6E); }
|
||||
void t2rpntlvwz1t1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_66|T_0F38|T_W0, 0x6F); }
|
||||
void t2rpntlvwz0rs(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_MAP5|T_W0, 0xF8); }
|
||||
void t2rpntlvwz0rst1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_MAP5|T_W0, 0xF9); }
|
||||
void t2rpntlvwz1rs(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_66|T_MAP5|T_W0, 0xF8); }
|
||||
void t2rpntlvwz1rst1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_66|T_MAP5|T_W0, 0xF9); }
|
||||
void ldtilecfg(const Address& addr) { opAMX(tmm0, addr, T_0F38|T_W0, 0x49); }
|
||||
void sttilecfg(const Address& addr) { opAMX(tmm0, addr, T_66|T_0F38|T_W0, 0x49); }
|
||||
void tilestored(const Address& addr, const Tmm& tm) { opAMX(tm, addr, T_F3|T_0F38|T_W0, 0x4B); }
|
||||
void tilerelease() { db(0xc4); db(0xe2); db(0x78); db(0x49); db(0xc0); }
|
||||
void tilezero(const Tmm& t) { opVex(t, &tmm0, tmm0, T_F2|T_0F38|T_W0, 0x49); }
|
||||
void tconjtfp16(const Tmm& t1, const Tmm& t2) { opVex(t1, 0, t2, T_66|T_0F38|T_W0, 0x6B); }
|
||||
void ttransposed(const Tmm& t1, const Tmm& t2) { opVex(t1, 0, t2, T_F3|T_0F38|T_W0, 0x5F); }
|
||||
#else
|
||||
void jcxz(std::string label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
||||
void jcxz(const Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); }
|
||||
|
||||
Vendored
+860
-1
@@ -15,9 +15,11 @@
|
||||
#else
|
||||
#define XBYAK_CONSTEXPR
|
||||
#endif
|
||||
#define XBYAK_CPUMASK_COMPACT 0
|
||||
#endif
|
||||
#else
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/**
|
||||
utility class and functions for Xbyak
|
||||
@@ -86,6 +88,32 @@
|
||||
#define XBYAK_USE_PERF
|
||||
#endif
|
||||
|
||||
#ifndef XBYAK_CPU_CACHE
|
||||
#define XBYAK_CPU_CACHE 1
|
||||
#endif
|
||||
#if XBYAK_CPU_CACHE == 1
|
||||
#include <vector>
|
||||
#ifndef XBYAK_CPUMASK_COMPACT
|
||||
#define XBYAK_CPUMASK_COMPACT 1
|
||||
#endif
|
||||
#if XBYAK_CPUMASK_COMPACT == 0
|
||||
#include <set>
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
namespace Xbyak { namespace util {
|
||||
class CpuTopology;
|
||||
class Cpu;
|
||||
namespace impl {
|
||||
|
||||
bool initCpuTopology(CpuTopology& cpuTopo);
|
||||
|
||||
} // Xbyak::util::impl
|
||||
} } // Xbyak::util
|
||||
#endif // XBYAK_CPU_CACHE
|
||||
|
||||
|
||||
namespace Xbyak { namespace util {
|
||||
|
||||
typedef enum {
|
||||
@@ -421,7 +449,7 @@ public:
|
||||
static inline void getCpuidEx(uint32_t eaxIn, uint32_t ecxIn, uint32_t data[4])
|
||||
{
|
||||
#ifdef XBYAK_INTEL_CPU_SPECIFIC
|
||||
#ifdef _WIN32
|
||||
#ifdef _MSC_VER
|
||||
__cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn);
|
||||
#else
|
||||
__cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]);
|
||||
@@ -558,6 +586,7 @@ public:
|
||||
XBYAK_DEFINE_TYPE(94, tAMX_MOVRS);
|
||||
XBYAK_DEFINE_TYPE(95, tAMX_FP8);
|
||||
XBYAK_DEFINE_TYPE(96, tMOVRS);
|
||||
XBYAK_DEFINE_TYPE(97, tHYBRID);
|
||||
|
||||
#undef XBYAK_SPLIT_ID
|
||||
#undef XBYAK_DEFINE_TYPE
|
||||
@@ -695,6 +724,7 @@ public:
|
||||
if (ecx & (1U << 28)) type_ |= tMOVDIR64B;
|
||||
if (edx & (1U << 5)) type_ |= tUINTR;
|
||||
if (edx & (1U << 14)) type_ |= tSERIALIZE;
|
||||
if (edx & (1U << 15)) type_ |= tHYBRID;
|
||||
if (edx & (1U << 16)) type_ |= tTSXLDTRK;
|
||||
if (edx & (1U << 22)) type_ |= tAMX_BF16;
|
||||
if (edx & (1U << 24)) type_ |= tAMX_TILE;
|
||||
@@ -761,6 +791,820 @@ public:
|
||||
#endif
|
||||
|
||||
#ifndef XBYAK_ONLY_CLASS_CPU
|
||||
#if XBYAK_CPU_CACHE == 1
|
||||
|
||||
enum CoreType {
|
||||
Unknown,
|
||||
Performance, // P-core (Intel)
|
||||
Efficient, // E-core (Intel)
|
||||
Standard // Non-hybrid
|
||||
};
|
||||
|
||||
inline const char *getCoreTypeStr(int coreType)
|
||||
{
|
||||
switch (coreType) {
|
||||
case Performance: return "P-core";
|
||||
case Efficient: return "E-core";
|
||||
case Standard: return "Standard";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
enum CacheType {
|
||||
L1i,
|
||||
L1d,
|
||||
L2,
|
||||
L3,
|
||||
CACHE_UNKNOWN,
|
||||
CACHE_TYPE_NUM = CACHE_UNKNOWN
|
||||
};
|
||||
|
||||
inline const char* getCacheTypeStr(int type)
|
||||
{
|
||||
switch (type) {
|
||||
case L1i: return "L1i";
|
||||
case L1d: return "L1d";
|
||||
case L2: return "L2";
|
||||
case L3: return "L3";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
|
||||
inline void appendStr(std::string& s, uint32_t v)
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
s += std::to_string(v);
|
||||
#else
|
||||
char buf[16];
|
||||
snprintf(buf, sizeof(buf), "%u", v);
|
||||
s += buf;
|
||||
#endif
|
||||
}
|
||||
|
||||
// str = "(int|range)[,(int|range)]*"
|
||||
// range = int-int
|
||||
// e.g. "1,3,5", "0-3,5-7", ""
|
||||
template<class T>
|
||||
bool setStr(T& x, const char *str)
|
||||
{
|
||||
const char *p = str;
|
||||
while (*p) {
|
||||
if (p != str) {
|
||||
if (*p != ',') return false;
|
||||
p++;
|
||||
}
|
||||
char *endp;
|
||||
uint32_t v = uint32_t(strtoul(p, &endp, 10));
|
||||
if (endp == p) return false;
|
||||
if (*endp == '-') {
|
||||
const char *rangeStart = endp + 1;
|
||||
uint32_t next = uint32_t(strtoul(rangeStart, &endp, 10));
|
||||
if (endp == rangeStart) return false;
|
||||
if (!x.appendRange(v, next)) return false;
|
||||
} else {
|
||||
if (!x.append(v)) return false;
|
||||
}
|
||||
if (*endp == '\0') return true;
|
||||
p = endp;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // impl
|
||||
|
||||
#ifndef XBYAK_CPUMASK_N
|
||||
#define XBYAK_CPUMASK_N 6
|
||||
#endif
|
||||
#ifndef XBYAK_CPUMASK_BITN
|
||||
#define XBYAK_CPUMASK_BITN 10 // max number of logical cpu = 1024
|
||||
#endif
|
||||
#if XBYAK_CPUMASK_COMPACT == 1
|
||||
/*
|
||||
a_ is treated as an array of N elements, each being bitN bits
|
||||
a_ = 1<<bitN and n_ = 0 and range_ = 0 means empty set
|
||||
n_ is length of a_[] - 1
|
||||
When range_ is false (discrete values):
|
||||
Values satisfy a_[i] + 1 < a_[i+1] for all 0 <= i <= n_
|
||||
When range_ is true (intervals):
|
||||
v = a_[i*2] is the start of the interval
|
||||
n = a_[i*2+1] is the interval length - 1
|
||||
Represents the interval [v, v+n]
|
||||
Max number of cpu = 2**bitN - 1
|
||||
Max value that can be stored = N
|
||||
Max interval length = N/2
|
||||
*/
|
||||
class CpuMask {
|
||||
static const uint32_t N = XBYAK_CPUMASK_N;
|
||||
static const uint32_t bitN = XBYAK_CPUMASK_BITN;
|
||||
static const uint64_t mask = (uint64_t(1) << bitN) - 1;
|
||||
uint64_t a_:N*bitN;
|
||||
uint64_t n_:3;
|
||||
uint64_t range_:1;
|
||||
|
||||
// Set a_[idx] = v
|
||||
void set_a(size_t idx, uint32_t v)
|
||||
{
|
||||
assert(idx < N);
|
||||
assert(v <= mask);
|
||||
a_ &= ~(mask << (idx*bitN));
|
||||
a_ |= (v & mask) << (idx*bitN);
|
||||
}
|
||||
// Get a_[idx]
|
||||
uint32_t get_a(size_t idx) const
|
||||
{
|
||||
assert(idx < N);
|
||||
return (a_ >> (idx*bitN)) & mask;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
// Return true if the idx-th value exists
|
||||
bool hasNext(uint32_t idx) const
|
||||
{
|
||||
if (empty()) return false;
|
||||
if (!range_) return idx <= n_;
|
||||
uint32_t n = 0;
|
||||
for (uint32_t i = 1; i <= n_; i += 2) {
|
||||
n += get_a(i) + 1;
|
||||
if (idx < n) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
public:
|
||||
CpuMask() { clear(); }
|
||||
class ConstIterator {
|
||||
const CpuMask& parent_;
|
||||
uint32_t idx_;
|
||||
uint32_t size_;
|
||||
friend class CpuMask;
|
||||
public:
|
||||
ConstIterator(const CpuMask& parent)
|
||||
: parent_(parent), idx_(0), size_(uint32_t(parent.size())) {}
|
||||
uint32_t operator*() const { return parent_.get(idx_); }
|
||||
ConstIterator& operator++() { idx_++; return *this; }
|
||||
bool operator==(const ConstIterator& rhs) const { return idx_ == rhs.idx_; }
|
||||
bool operator!=(const ConstIterator& rhs) const { return !operator==(rhs); }
|
||||
};
|
||||
ConstIterator begin() const { return ConstIterator(*this); }
|
||||
ConstIterator end() const {
|
||||
ConstIterator it(*this);
|
||||
it.idx_ = uint32_t(size());
|
||||
return it;
|
||||
}
|
||||
typedef ConstIterator iterator;
|
||||
typedef ConstIterator const_iterator;
|
||||
void clear() { a_ = 1 << bitN; n_ = 0; range_ = 0; }
|
||||
bool empty() const
|
||||
{
|
||||
return a_ == 1 << bitN && n_ == 0 && range_ == 0;
|
||||
}
|
||||
uint64_t to_u64() const { return a_ | (uint64_t(n_) << (N * bitN)) | (uint64_t(range_) << (N * bitN + 3)); }
|
||||
bool operator<(const CpuMask& rhs) const { return to_u64() < rhs.to_u64(); }
|
||||
bool operator>(const CpuMask& rhs) const { return to_u64() > rhs.to_u64(); }
|
||||
bool operator>=(const CpuMask& rhs) const { return !operator<(rhs); }
|
||||
bool operator<=(const CpuMask& rhs) const { return !operator>(rhs); }
|
||||
bool operator==(const CpuMask& rhs) const { return to_u64() == rhs.to_u64(); }
|
||||
bool operator!=(const CpuMask& rhs) const { return !operator==(rhs); }
|
||||
// Add element v
|
||||
// v should be monotonically increasing
|
||||
bool append(uint32_t v)
|
||||
{
|
||||
uint32_t prev = 0, n = 0;
|
||||
if (v > mask) goto ERR;
|
||||
// When adding for the first time, treat as discrete value
|
||||
if (empty()) {
|
||||
a_ = v;
|
||||
n_ = 0;
|
||||
return true;
|
||||
}
|
||||
if (!range_) {
|
||||
prev = get_a(n_);
|
||||
if (v <= prev) goto ERR;
|
||||
// If there's one discrete value and it forms an interval with the new value, switch to interval mode
|
||||
if (n_ == 0 && prev + 1 == v) {
|
||||
set_a(1, 1);
|
||||
range_ = 1;
|
||||
n_ = 1;
|
||||
return true;
|
||||
}
|
||||
if (n_ >= N - 1) goto ERR;
|
||||
// Add discrete value
|
||||
n_++;
|
||||
set_a(n_, v);
|
||||
return true;
|
||||
}
|
||||
// If the value to add is 1 greater than the end of the current interval
|
||||
n = get_a(n_);
|
||||
prev = get_a(n_ - 1) + n;
|
||||
if (prev >= v) goto ERR;
|
||||
if (prev + 1 == v) {
|
||||
// Increase the interval length by one
|
||||
set_a(n_, n + 1);
|
||||
return true;
|
||||
} else {
|
||||
if (n_ >= N - 1) goto ERR;
|
||||
// If not continuous with the previous interval
|
||||
// Add a new interval [v]
|
||||
set_a(n_ + 1, v);
|
||||
n_ += 2;
|
||||
return true;
|
||||
}
|
||||
ERR:
|
||||
XBYAK_THROW_RET(ERR_INVALID_CPUMASK_INDEX, false)
|
||||
}
|
||||
// add range [a, b] which means a, a+1, ..., b
|
||||
bool appendRange(uint32_t a, uint32_t b)
|
||||
{
|
||||
if ((empty() || (range_ && n_ < N - 1)) && (a <= b && b <= mask)) {
|
||||
range_ = true;
|
||||
n_ += n_ == 0 ? 1 : 2;
|
||||
set_a(n_ - 1, a);
|
||||
set_a(n_, b - a);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
// str = "(int|range)[,(int|range)]*"
|
||||
// range = int-int
|
||||
bool setStr(const char *str)
|
||||
{
|
||||
return impl::setStr(*this, str);
|
||||
}
|
||||
bool setStr(const std::string& str) { return setStr(str.c_str()); }
|
||||
std::string getStr() const
|
||||
{
|
||||
std::string s;
|
||||
if (empty()) return s;
|
||||
if (!range_) {
|
||||
for (uint32_t i = 0; i <= n_; i++) {
|
||||
if (!s.empty()) s += ",";
|
||||
impl::appendStr(s, get_a(i));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
for (uint32_t i = 0; i <= n_; i += 2) {
|
||||
uint32_t v = get_a(i);
|
||||
uint32_t len = get_a(i + 1);
|
||||
if (!s.empty()) s += ",";
|
||||
impl::appendStr(s, v);
|
||||
if (len > 0) {
|
||||
s += "-";
|
||||
impl::appendStr(s, v + len);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
size_t size() const
|
||||
{
|
||||
if (empty()) return 0;
|
||||
if (!range_) return n_ + 1;
|
||||
size_t n = 0;
|
||||
for (uint32_t i = 1; i <= n_; i += 2) {
|
||||
n += get_a(i) + 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
uint32_t get(uint32_t idx) const
|
||||
{
|
||||
assert(hasNext(idx));
|
||||
if (!range_) return get_a(idx);
|
||||
uint32_t n = 0;
|
||||
for (uint32_t i = 1; i <= n_; i += 2) {
|
||||
uint32_t range = get_a(i) + 1;
|
||||
if (idx < n + range) {
|
||||
return get_a(i - 1) + (idx - n);
|
||||
}
|
||||
n += range;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void dump() const
|
||||
{
|
||||
printf("a_:");
|
||||
for (int i = int(N) - 1; i >= 0; i--) {
|
||||
printf("%u ", uint32_t((a_ >> (i * bitN)) & mask));
|
||||
}
|
||||
printf("\n");
|
||||
printf("n_: %u\n", (uint32_t)n_);
|
||||
printf("range_: %u\n", (uint32_t)range_);
|
||||
}
|
||||
void put(const char *label = NULL) const
|
||||
{
|
||||
if (label) printf("%s: ", label);
|
||||
printf("%s\n", getStr().c_str());
|
||||
}
|
||||
};
|
||||
#else
|
||||
class CpuMask {
|
||||
typedef std::set<uint32_t> IntSet;
|
||||
IntSet indices_;
|
||||
public:
|
||||
CpuMask() : indices_() {}
|
||||
typedef IntSet::const_iterator const_iterator;
|
||||
typedef const_iterator iterator;
|
||||
const_iterator begin() const { return indices_.begin(); }
|
||||
const_iterator end() const { return indices_.end(); }
|
||||
|
||||
void clear() { indices_.clear(); }
|
||||
bool empty() const { return indices_.empty(); }
|
||||
bool operator<(const CpuMask& rhs) const { return indices_ < rhs.indices_; }
|
||||
bool operator>(const CpuMask& rhs) const { return indices_ > rhs.indices_; }
|
||||
bool operator>=(const CpuMask& rhs) const { return !operator<(rhs); }
|
||||
bool operator<=(const CpuMask& rhs) const { return !operator>(rhs); }
|
||||
bool operator==(const CpuMask& rhs) const { return indices_ == rhs.indices_; }
|
||||
bool operator!=(const CpuMask& rhs) const { return !operator==(rhs); }
|
||||
// idx should be monotonically increasing
|
||||
bool append(uint32_t idx)
|
||||
{
|
||||
if (idx >= (1u << XBYAK_CPUMASK_BITN)) return false;
|
||||
if (!indices_.empty() && *indices_.rbegin() >= idx) return false;
|
||||
indices_.insert(idx);
|
||||
return true;
|
||||
}
|
||||
// add range [a, b] which means a, a+1, ..., b
|
||||
bool appendRange(uint32_t a, uint32_t b)
|
||||
{
|
||||
if (a > b) return false;
|
||||
while (a <= b) {
|
||||
if (!append(a)) return false;
|
||||
a++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool setStr(const char *str)
|
||||
{
|
||||
return impl::setStr(*this, str);
|
||||
}
|
||||
bool setStr(const std::string& str) { return setStr(str.c_str()); }
|
||||
std::string getStr() const
|
||||
{
|
||||
std::string s;
|
||||
bool inRange = false;
|
||||
uint32_t prev = 0x80000000;
|
||||
for (const_iterator i = indices_.begin(); i != indices_.end(); ++i) {
|
||||
uint32_t v = *i;
|
||||
if (inRange) {
|
||||
if (prev + 1 != v) {
|
||||
impl::appendStr(s, prev);
|
||||
inRange = false;
|
||||
s += ',';
|
||||
impl::appendStr(s, v);
|
||||
}
|
||||
} else {
|
||||
if (prev + 1 == v) {
|
||||
// start range
|
||||
s += '-';
|
||||
inRange = true;
|
||||
} else {
|
||||
if (!s.empty()) s += ',';
|
||||
impl::appendStr(s, v);
|
||||
}
|
||||
}
|
||||
prev = v;
|
||||
}
|
||||
if (inRange) {
|
||||
impl::appendStr(s, prev);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
size_t size() const { return indices_.size(); }
|
||||
uint32_t get(uint32_t idx) const
|
||||
{
|
||||
assert(idx < size());
|
||||
const_iterator it = indices_.begin();
|
||||
std::advance(it, idx);
|
||||
return *it;
|
||||
}
|
||||
void put(const char *label = NULL) const
|
||||
{
|
||||
if (label) printf("%s: ", label);
|
||||
printf("%s\n", getStr().c_str());
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
class CpuCache {
|
||||
public:
|
||||
CpuCache() : size(0), associativity(0) {}
|
||||
|
||||
// Cache size in bytes
|
||||
uint32_t size;
|
||||
|
||||
// number of ways of associativity
|
||||
uint32_t associativity;
|
||||
|
||||
// Set of logical CPU indices sharing this cache
|
||||
CpuMask sharedCpuIndices;
|
||||
|
||||
// Whether this is a shared cache
|
||||
bool isShared() const { return sharedCpuIndices.size() > 1; }
|
||||
|
||||
// Number of logical CPUs sharing this cache
|
||||
size_t getSharedCpuNum() const { return sharedCpuIndices.size(); }
|
||||
|
||||
void put(const char *label = NULL) const
|
||||
{
|
||||
if (label) printf("%s: ", label);
|
||||
printf("%u KiB, assoc. %u, shared ", size / 1024, associativity);
|
||||
sharedCpuIndices.put();
|
||||
}
|
||||
};
|
||||
|
||||
struct LogicalCpu {
|
||||
LogicalCpu()
|
||||
: coreId(0)
|
||||
, coreType(Unknown)
|
||||
, cache()
|
||||
{
|
||||
}
|
||||
uint32_t coreId; // index of physical core
|
||||
CoreType coreType; // for hybrid systems
|
||||
CpuCache cache[CACHE_TYPE_NUM];
|
||||
const CpuMask& getSiblings() const { return cache[L1i].sharedCpuIndices; }
|
||||
|
||||
void put(const char *label = NULL) const
|
||||
{
|
||||
if (label) printf("%s: ", label);
|
||||
printf("coreId %u, type %s\n", coreId, getCoreTypeStr(coreType));
|
||||
for (int i = 0; i < CACHE_TYPE_NUM; i++) {
|
||||
cache[i].put(getCacheTypeStr(i));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class CpuTopology {
|
||||
public:
|
||||
explicit CpuTopology(const Cpu& cpu)
|
||||
: logicalCpus_()
|
||||
, physicalCoreNum_(0)
|
||||
, lineSize_(0)
|
||||
, isHybrid_(cpu.has(cpu.tHYBRID))
|
||||
{
|
||||
if (!impl::initCpuTopology(*this)) {
|
||||
XBYAK_THROW(ERR_CANT_INIT_CPUTOPOLOGY);
|
||||
}
|
||||
}
|
||||
|
||||
// Number of logical CPUs
|
||||
size_t getLogicalCpuNum() const { return logicalCpus_.size(); }
|
||||
|
||||
// Number of physical cores
|
||||
size_t getPhysicalCoreNum() const { return physicalCoreNum_; }
|
||||
|
||||
// Cache line size in bytes
|
||||
uint32_t getLineSize() const { return lineSize_; }
|
||||
|
||||
// Get logical CPU information
|
||||
const LogicalCpu& getLogicalCpu(size_t cpuIdx) const
|
||||
{
|
||||
return logicalCpus_[cpuIdx];
|
||||
}
|
||||
|
||||
// Get cache information for a specific logical CPU
|
||||
const CpuCache& getCache(size_t cpuIdx, CacheType type) const
|
||||
{
|
||||
return logicalCpus_[cpuIdx].cache[type];
|
||||
}
|
||||
|
||||
// Whether this is a hybrid system
|
||||
bool isHybrid() const { return isHybrid_; }
|
||||
private:
|
||||
friend bool impl::initCpuTopology(CpuTopology&);
|
||||
std::vector<LogicalCpu> logicalCpus_;
|
||||
size_t physicalCoreNum_;
|
||||
uint32_t lineSize_;
|
||||
bool isHybrid_;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
inline uint32_t popcnt(uint64_t mask)
|
||||
{
|
||||
#if defined(_M_X64) || defined(_M_AMD64)
|
||||
return (int)__popcnt64(mask);
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
return __builtin_popcountll(mask);
|
||||
#else
|
||||
uint32_t count = 0;
|
||||
while (mask) {
|
||||
count += (mask & 1);
|
||||
mask >>= 1;
|
||||
}
|
||||
return count;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
typedef std::vector<uint32_t> U32Vec;
|
||||
typedef SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX ProcInfo;
|
||||
|
||||
// return total logical cpus if sucessful, 0 if failed
|
||||
inline uint32_t getGroupAcc(U32Vec& v)
|
||||
{
|
||||
DWORD len = 0;
|
||||
GetLogicalProcessorInformationEx(RelationGroup, NULL, &len);
|
||||
std::vector<char> buf(len);
|
||||
if (!GetLogicalProcessorInformationEx(RelationGroup, reinterpret_cast<ProcInfo*>(buf.data()), &len)) {
|
||||
return 0;
|
||||
}
|
||||
const auto& entry = *reinterpret_cast<const ProcInfo*>(buf.data());
|
||||
const GROUP_RELATIONSHIP& gr = entry.Group;
|
||||
|
||||
const uint32_t n = gr.ActiveGroupCount;
|
||||
if (n == 0) return 0;
|
||||
|
||||
v.resize(n);
|
||||
|
||||
uint32_t acc = 0;
|
||||
for (uint32_t g = 0; g < n; g++) {
|
||||
v[g] = acc;
|
||||
acc += gr.GroupInfo[g].ActiveProcessorCount;
|
||||
}
|
||||
return acc;
|
||||
}
|
||||
|
||||
// return number of physical cores if successful, 0 if failed
|
||||
static inline uint32_t getCores(std::vector<LogicalCpu>& cpus, bool isHybrid, const U32Vec& groupAcc) {
|
||||
DWORD len = 0;
|
||||
GetLogicalProcessorInformationEx(RelationProcessorCore, NULL, &len);
|
||||
std::vector<char> buf(len);
|
||||
if (!GetLogicalProcessorInformationEx(RelationProcessorCore, reinterpret_cast<ProcInfo*>(buf.data()), &len)) return 0;
|
||||
|
||||
// get core indices
|
||||
const char *p = buf.data();
|
||||
const char *end = p + len;
|
||||
uint32_t coreIdx = 0;
|
||||
|
||||
while (p < end) {
|
||||
const auto& entry = *reinterpret_cast<const ProcInfo*>(p);
|
||||
if (entry.Relationship == RelationProcessorCore) {
|
||||
const PROCESSOR_RELATIONSHIP& core = entry.Processor;
|
||||
LogicalCpu cpu;
|
||||
cpu.coreId = coreIdx++;
|
||||
if (!isHybrid) {
|
||||
cpu.coreType = Standard;
|
||||
} else if (core.EfficiencyClass > 0) {
|
||||
cpu.coreType = Performance;
|
||||
} else {
|
||||
cpu.coreType = Efficient;
|
||||
}
|
||||
|
||||
const GROUP_AFFINITY* masks = core.GroupMask;
|
||||
for (WORD i = 0; i < core.GroupCount; i++) {
|
||||
const WORD group = masks[i].Group;
|
||||
const KAFFINITY m = masks[i].Mask;
|
||||
const uint32_t base = groupAcc[group];
|
||||
|
||||
for (uint32_t b = 0; b < sizeof(KAFFINITY) * 8; b++) {
|
||||
if (m & (KAFFINITY(1) << b)) {
|
||||
const uint32_t idx = base + b;
|
||||
if (idx >= cpus.size()) return 0;
|
||||
cpus[idx] = cpu;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p += entry.Size;
|
||||
}
|
||||
return coreIdx;
|
||||
}
|
||||
|
||||
inline bool convertMask(CpuMask& mask, const U32Vec& groupAcc, const CACHE_RELATIONSHIP& cache)
|
||||
{
|
||||
const GROUP_AFFINITY* masks = cache.GroupMasks;
|
||||
|
||||
for (WORD i = 0; i < cache.GroupCount; i++) {
|
||||
const WORD group = masks[i].Group;
|
||||
const KAFFINITY m = masks[i].Mask;
|
||||
const uint32_t base = groupAcc[group];
|
||||
|
||||
for (uint32_t b = 0; b < sizeof(KAFFINITY) * 8; b++) {
|
||||
if (m & (KAFFINITY(1) << b)) {
|
||||
if (!mask.append(base + b)) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool initCpuTopology(CpuTopology& cpuTopo)
|
||||
{
|
||||
U32Vec groupAcc;
|
||||
const uint32_t logicalCpuNum = getGroupAcc(groupAcc);
|
||||
if (logicalCpuNum == 0) return false;
|
||||
if (logicalCpuNum >= (1u << XBYAK_CPUMASK_BITN)) return false;
|
||||
|
||||
cpuTopo.logicalCpus_.resize(logicalCpuNum);
|
||||
cpuTopo.physicalCoreNum_ = getCores(cpuTopo.logicalCpus_, cpuTopo.isHybrid(), groupAcc);
|
||||
if (cpuTopo.physicalCoreNum_ == 0) return false;
|
||||
|
||||
DWORD len = 0;
|
||||
GetLogicalProcessorInformationEx(RelationCache, NULL, &len);
|
||||
std::vector<char> buf(len);
|
||||
if (!GetLogicalProcessorInformationEx(RelationCache, reinterpret_cast<ProcInfo*>(buf.data()), &len)) return false;
|
||||
|
||||
const char *p = buf.data();
|
||||
const char *end = p + len;
|
||||
|
||||
while (p < end) {
|
||||
const auto& entry = *reinterpret_cast<const ProcInfo*>(p);
|
||||
if (entry.Relationship == RelationCache) {
|
||||
const CACHE_RELATIONSHIP& cache = entry.Cache;
|
||||
uint32_t type = CACHE_UNKNOWN;
|
||||
if (cache.Level == 1) {
|
||||
if (cache.Type == CacheInstruction) {
|
||||
type = L1i;
|
||||
} else if (cache.Type == CacheData) {
|
||||
type = L1d;
|
||||
}
|
||||
} else if (cache.Level == 2) {
|
||||
type = L2;
|
||||
} else if (cache.Level == 3) {
|
||||
type = L3;
|
||||
}
|
||||
if (type != CACHE_UNKNOWN) {
|
||||
CpuMask mask;
|
||||
if (!convertMask(mask, groupAcc, cache)) return false;
|
||||
for (const auto& i : mask) {
|
||||
if (i >= cpuTopo.logicalCpus_.size()) return false;
|
||||
cpuTopo.logicalCpus_[i].cache[type].size = cache.CacheSize;
|
||||
if (cpuTopo.lineSize_ == 0) cpuTopo.lineSize_ = cache.LineSize;
|
||||
cpuTopo.logicalCpus_[i].cache[type].associativity = cache.Associativity;
|
||||
cpuTopo.logicalCpus_[i].cache[type].sharedCpuIndices = mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
p += entry.Size;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#elif defined(__linux__) // Linux
|
||||
|
||||
struct WrapFILE {
|
||||
FILE *f;
|
||||
explicit WrapFILE(const char *name)
|
||||
: f(fopen(name, "r"))
|
||||
{
|
||||
}
|
||||
~WrapFILE() { if (f) fclose(f); }
|
||||
};
|
||||
|
||||
inline uint32_t readIntFromFile(const char* path) {
|
||||
WrapFILE wf(path);
|
||||
if (!wf.f) return 0;
|
||||
uint32_t val = 0;
|
||||
int n = fscanf(wf.f, "%u", &val);
|
||||
return (n == 1) ? val : 0;
|
||||
}
|
||||
|
||||
inline bool parseCpuList(CpuMask& mask, const char* path) {
|
||||
WrapFILE wf(path);
|
||||
if (!wf.f) return false;
|
||||
char buf[1024];
|
||||
if (!fgets(buf, sizeof(buf), wf.f)) return false;
|
||||
size_t n = strlen(buf);
|
||||
if (n > 0 && buf[n - 1] == '\n') buf[n - 1] = '\0';
|
||||
return setStr(mask, buf);
|
||||
}
|
||||
|
||||
inline bool initCpuTopology(CpuTopology& cpuTopo)
|
||||
{
|
||||
const uint32_t logicalCpuNum = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
|
||||
if (logicalCpuNum == 0) return false;
|
||||
if (logicalCpuNum >= (1u << XBYAK_CPUMASK_BITN)) return false;
|
||||
|
||||
cpuTopo.logicalCpus_.resize(logicalCpuNum);
|
||||
uint32_t maxPhisicalIdx = 0;
|
||||
|
||||
for (uint32_t cpuIdx = 0; cpuIdx < logicalCpuNum; cpuIdx++) {
|
||||
char path[256];
|
||||
LogicalCpu& logCpu = cpuTopo.logicalCpus_[cpuIdx];
|
||||
|
||||
snprintf(path, sizeof(path),
|
||||
"/sys/devices/system/cpu/cpu%u/topology/core_id", cpuIdx);
|
||||
logCpu.coreId = readIntFromFile(path);
|
||||
maxPhisicalIdx = (std::max)(maxPhisicalIdx, logCpu.coreId);
|
||||
|
||||
logCpu.coreType = Standard;
|
||||
|
||||
for (uint32_t cacheIdx = 0; cacheIdx < CACHE_TYPE_NUM; cacheIdx++) {
|
||||
CacheType cacheType = CACHE_UNKNOWN;
|
||||
|
||||
// Map cache index to cache type
|
||||
{
|
||||
snprintf(path, sizeof(path),
|
||||
"/sys/devices/system/cpu/cpu%u/cache/index%u/type", cpuIdx, cacheIdx);
|
||||
char typeStr[32];
|
||||
WrapFILE wf(path);
|
||||
|
||||
if (wf.f && fgets(typeStr, sizeof(typeStr), wf.f)) {
|
||||
if (strncmp(typeStr, "Instruction", 11) == 0) {
|
||||
cacheType = L1i;
|
||||
} else if (strncmp(typeStr, "Data", 4) == 0) {
|
||||
// Determine level
|
||||
char path[256];
|
||||
snprintf(path, sizeof(path),
|
||||
"/sys/devices/system/cpu/cpu%u/cache/index%u/level", cpuIdx, cacheIdx);
|
||||
switch (readIntFromFile(path)) {
|
||||
case 1: cacheType = L1d; break;
|
||||
case 2: cacheType = L2; break;
|
||||
case 3: cacheType = L3; break;
|
||||
default: break;;
|
||||
}
|
||||
} else if (strncmp(typeStr, "Unified", 7) == 0) {
|
||||
snprintf(path, sizeof(path),
|
||||
"/sys/devices/system/cpu/cpu%u/cache/index%u/level", cpuIdx, cacheIdx);
|
||||
switch (readIntFromFile(path)) {
|
||||
case 2: cacheType = L2; break;
|
||||
case 3: cacheType = L3; break;
|
||||
default: break;;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cacheType == CACHE_UNKNOWN) continue;
|
||||
CpuCache& cache = logCpu.cache[cacheType];
|
||||
|
||||
// Read cache size
|
||||
{
|
||||
snprintf(path, sizeof(path),
|
||||
"/sys/devices/system/cpu/cpu%u/cache/index%u/size", cpuIdx, cacheIdx);
|
||||
char sizeStr[32];
|
||||
WrapFILE wf(path);
|
||||
if (wf.f && fgets(sizeStr, sizeof(sizeStr), wf.f)) {
|
||||
char *endp;
|
||||
uint32_t size = (uint32_t)strtoul(sizeStr, &endp, 10);
|
||||
switch (*endp) {
|
||||
case '\0': case '\n': cache.size = size; break;
|
||||
case 'K': case 'k': cache.size = size * 1024; break;
|
||||
case 'M': case 'm': cache.size = size * 1024 * 1024; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read ways of associativity
|
||||
snprintf(path, sizeof(path),
|
||||
"/sys/devices/system/cpu/cpu%u/cache/index%u/ways_of_associativity", cpuIdx, cacheIdx);
|
||||
cache.associativity = readIntFromFile(path);
|
||||
|
||||
// Read shared CPU list
|
||||
snprintf(path, sizeof(path),
|
||||
"/sys/devices/system/cpu/cpu%u/cache/index%u/shared_cpu_list", cpuIdx, cacheIdx);
|
||||
parseCpuList(cache.sharedCpuIndices, path);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Assign core types for hybrid architectures
|
||||
const bool isHybrid = cpuTopo.isHybrid();
|
||||
if (isHybrid) {
|
||||
// For hybrid systems, read P-core and E-core lists from sysfs
|
||||
CpuMask pCoreMask;
|
||||
if (parseCpuList(pCoreMask, "/sys/devices/cpu_core/cpus")) {
|
||||
// Set Performance core types
|
||||
for (CpuMask::const_iterator it = pCoreMask.begin(); it != pCoreMask.end(); ++it) {
|
||||
uint32_t cpuIdx = *it;
|
||||
if (cpuIdx < logicalCpuNum) {
|
||||
cpuTopo.logicalCpus_[cpuIdx].coreType = Performance;
|
||||
}
|
||||
}
|
||||
}
|
||||
CpuMask eCoreMask;
|
||||
if (parseCpuList(eCoreMask, "/sys/devices/cpu_atom/cpus")) {
|
||||
// Set Efficient core types
|
||||
for (CpuMask::const_iterator it = eCoreMask.begin(); it != eCoreMask.end(); ++it) {
|
||||
uint32_t cpuIdx = *it;
|
||||
if (cpuIdx < logicalCpuNum) {
|
||||
cpuTopo.logicalCpus_[cpuIdx].coreType = Efficient;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read coherency line size
|
||||
cpuTopo.lineSize_ = readIntFromFile("/sys/devices/system/cpu/cpu0/cache/index0/coherency_line_size");
|
||||
|
||||
cpuTopo.physicalCoreNum_ = maxPhisicalIdx + 1;
|
||||
return true;
|
||||
}
|
||||
#else // Other OS (e.g., macOS)
|
||||
inline bool initCpuTopology(CpuTopology& cpuTopo)
|
||||
{
|
||||
// CPU topology detection not yet implemented
|
||||
(void)cpuTopo;
|
||||
return false;
|
||||
}
|
||||
#endif // _WIN32 / __linux__ / other OS
|
||||
|
||||
} // namespace impl
|
||||
#endif // XBYAK_CPU_CACHE
|
||||
|
||||
class Clock {
|
||||
public:
|
||||
static inline uint64_t getRdtsc()
|
||||
@@ -1170,4 +2014,19 @@ public:
|
||||
|
||||
} } // end of util
|
||||
|
||||
#if XBYAK_CPUMASK_COMPACT == 1 && __cplusplus >= 201103
|
||||
|
||||
namespace std {
|
||||
|
||||
template<>
|
||||
struct hash<Xbyak::util::CpuMask> {
|
||||
size_t operator()(const Xbyak::util::CpuMask& m) const noexcept {
|
||||
return std::hash<uint64_t>{}(m.to_u64());
|
||||
}
|
||||
};
|
||||
|
||||
} // std
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
+141
-10
@@ -1623,6 +1623,8 @@ SCAJ-20058:
|
||||
SCAJ-20059:
|
||||
name: "Minna no Golf 4"
|
||||
region: "NTSC-Unk"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCAJ-20060:
|
||||
name: "Time Crisis 3"
|
||||
region: "NTSC-Unk"
|
||||
@@ -1717,6 +1719,8 @@ SCAJ-20074:
|
||||
name: "The King of Fighters 2002"
|
||||
name-sort: "King of Fighters 2002, The"
|
||||
region: "NTSC-Unk"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SCAJ-20075:
|
||||
name: "Dragon Quest V - Bride of the Sky"
|
||||
region: "NTSC-Unk"
|
||||
@@ -1846,6 +1850,8 @@ SCAJ-20093:
|
||||
SCAJ-20094:
|
||||
name: "Minna no Golf 4 [PlayStation2 the Best]"
|
||||
region: "NTSC-Unk"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCAJ-20095:
|
||||
name: "Digital Devil Saga - Avatar Tuner"
|
||||
region: "NTSC-Unk"
|
||||
@@ -2523,6 +2529,8 @@ SCAJ-20193:
|
||||
SCAJ-20194:
|
||||
name: "Minna no Golf 4 [PlayStation2 the Best]"
|
||||
region: "NTSC-Unk"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCAJ-20195:
|
||||
name: "Ape Escape 3 [PlayStation2 the Best]"
|
||||
region: "NTSC-C"
|
||||
@@ -2625,7 +2633,7 @@ SCAJ-25047:
|
||||
gsHWFixes:
|
||||
minimumBlendingLevel: 2 # Fixes dark font to more bright like software mode.
|
||||
SCAJ-30001:
|
||||
name: "Xenosaga - Episode I - Der Wille zur Macht [PlayStation2 the Best]"
|
||||
name: "Xenosaga Episode I - Der Wille zur Macht [PlayStation2 the Best]"
|
||||
region: "NTSC-Unk"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
@@ -5842,8 +5850,10 @@ SCES-52566:
|
||||
name: "SingStar"
|
||||
region: "PAL-I"
|
||||
SCES-52582:
|
||||
name: "Everybody's Golf"
|
||||
name: "Everybody's Golf 4"
|
||||
region: "PAL-M5"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCES-52586:
|
||||
name: "Death by Degrees"
|
||||
region: "PAL-E-S"
|
||||
@@ -7630,6 +7640,8 @@ SCKA-20057:
|
||||
name: "모두의 골프 4"
|
||||
name-en: "Everybody's Golf 4"
|
||||
region: "NTSC-K"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCKA-20058:
|
||||
name: "액션 로망 범피 트롯"
|
||||
name-en: "Action Romance Bumpy Trot"
|
||||
@@ -7960,6 +7972,8 @@ SCKA-20096:
|
||||
name: "반야드"
|
||||
name-en: "Nickelodeon Barnyard"
|
||||
region: "NTSC-K"
|
||||
speedHacks:
|
||||
instantVU1: 0 # Significantly improves game speed.
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 2 # Fix text and post blur.
|
||||
autoFlush: 2 # Needed for recursive mipmap rendering.
|
||||
@@ -9122,6 +9136,8 @@ SCPS-15059:
|
||||
name-sort: "みんなのごるふ 4"
|
||||
name-en: "Minna no Golf 4"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCPS-15060:
|
||||
name: "幸福操作官"
|
||||
name-sort: "こうふくそうさかん"
|
||||
@@ -10025,6 +10041,8 @@ SCPS-19301:
|
||||
name-sort: "みんなのごるふ4 [PlayStation2 the Best]"
|
||||
name-en: "Minna no Golf 4 [PlayStation2 the Best]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCPS-19302:
|
||||
name: "ラチェット&クランク2 ガガガ!銀河のコマンドーっす [PlayStation2 the Best]"
|
||||
name-sort: "らちぇっとあんどくらんく2 ががが!ぎんがのこまんどーっす [PlayStation2 the Best]"
|
||||
@@ -10211,6 +10229,8 @@ SCPS-19319:
|
||||
name-sort: "みんなのごるふ 4 [PlayStation2 the Best]"
|
||||
name-en: "Minna no Golf 4 [PlayStation2 the Best]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCPS-19320:
|
||||
name: "ワンダと巨像 [PlayStation2 the Best]"
|
||||
name-sort: "わんだときょぞう [PlayStation2 the Best]"
|
||||
@@ -10580,6 +10600,7 @@ SCPS-55015:
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes incorrect blur effect.
|
||||
halfPixelOffset: 4 # Improves blur.
|
||||
limit24BitDepth: 2 # Fixes invisible menus and cursor.
|
||||
SCPS-55016:
|
||||
name: "ジェットでGO!2"
|
||||
name-sort: "じぇっとでGO!2"
|
||||
@@ -10934,6 +10955,7 @@ SCPS-56012:
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes incorrect blur effect.
|
||||
halfPixelOffset: 4 # Improves blur.
|
||||
limit24BitDepth: 2 # Fixes invisible menus and cursor.
|
||||
SCPS-56013:
|
||||
name: "This Is Football 세계최강축구 2003"
|
||||
name-sort: "This Is Football - Segye Choegang Chukgu 2003"
|
||||
@@ -12146,9 +12168,11 @@ SCUS-97400:
|
||||
name: "EyeToy - Groove"
|
||||
region: "NTSC-U"
|
||||
SCUS-97401:
|
||||
name: "Hot Shots Golf FORE!"
|
||||
name: "Hot Shots Golf Fore!"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCUS-97402:
|
||||
name: "Killzone"
|
||||
region: "NTSC-U"
|
||||
@@ -12269,8 +12293,10 @@ SCUS-97425:
|
||||
name: "Online Start-Up Disc v3.0"
|
||||
region: "NTSC-U"
|
||||
SCUS-97427:
|
||||
name: "Hot Shots Golf FORE! [Online Public Beta]"
|
||||
name: "Hot Shots Golf Fore! [Online Public Beta]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCUS-97428:
|
||||
name: "Kiosk Demo Disc Q3-Q4 2004"
|
||||
region: "NTSC-U"
|
||||
@@ -12291,8 +12317,10 @@ SCUS-97429:
|
||||
- "SCUS-97429"
|
||||
- "SCUS-97465"
|
||||
SCUS-97430:
|
||||
name: "Hot Shots Golf FORE! [Regular Demo]"
|
||||
name: "Hot Shots Golf Fore! [Regular Demo]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCUS-97431:
|
||||
name: "Killzone Public Beta V1.0"
|
||||
region: "NTSC-U"
|
||||
@@ -12745,8 +12773,10 @@ SCUS-97514:
|
||||
name: "ATV Offroad Fury 3 [Greatest Hits]"
|
||||
region: "NTSC-U"
|
||||
SCUS-97515:
|
||||
name: "Hot Shots Golf FORE! [Greatest Hits]"
|
||||
name: "Hot Shots Golf Fore! [Greatest Hits]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
SCUS-97516:
|
||||
name: "Jak 3 [Greatest Hits]"
|
||||
region: "NTSC-U"
|
||||
@@ -14038,6 +14068,8 @@ SLED-53097:
|
||||
region: "PAL-M5"
|
||||
gameFixes:
|
||||
- BlitInternalFPSHack # Fixes internal FPS detection.
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes z fighting in main menu and in game.
|
||||
SLED-53109:
|
||||
name: "Juiced [Demo]"
|
||||
region: "PAL-M5"
|
||||
@@ -14725,9 +14757,13 @@ SLES-50126:
|
||||
name: "Quake III - Revolution"
|
||||
region: "PAL-M3"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLES-50127:
|
||||
name: "Quake III - Revolution"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLES-50128:
|
||||
name: "Knockout Kings 2001"
|
||||
region: "PAL-E"
|
||||
@@ -17642,6 +17678,7 @@ SLES-51301:
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes incorrect blur effect.
|
||||
halfPixelOffset: 4 # Improves blur.
|
||||
limit24BitDepth: 2 # Fixes invisible menus and cursor.
|
||||
SLES-51302:
|
||||
name: "Bomberman Kart"
|
||||
region: "PAL-M3"
|
||||
@@ -18839,6 +18876,8 @@ SLES-51843:
|
||||
name: "Worms 3D"
|
||||
region: "PAL-M5"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes z fighting in main menu and in game.
|
||||
SLES-51845:
|
||||
name: "Barbie Horse Adventures - Wild Horse Rescue"
|
||||
region: "PAL-M6"
|
||||
@@ -20106,6 +20145,7 @@ SLES-52342:
|
||||
- BlitInternalFPSHack # Fixes internal FPS detection.
|
||||
gsHWFixes:
|
||||
PCRTCOverscan: 1 # Centers game output.
|
||||
limit24BitDepth: 2 # Fixes z fighting in main menu and in game.
|
||||
SLES-52343:
|
||||
name: "Midway Arcade Treasures"
|
||||
region: "PAL-E"
|
||||
@@ -21310,6 +21350,7 @@ SLES-52734:
|
||||
- BlitInternalFPSHack # Fixes internal FPS detection.
|
||||
gsHWFixes:
|
||||
PCRTCOverscan: 1 # Centers game output.
|
||||
limit24BitDepth: 2 # Fixes z fighting in main menu and in game.
|
||||
SLES-52737:
|
||||
name: "Obscure"
|
||||
region: "PAL-E"
|
||||
@@ -22501,6 +22542,8 @@ SLES-53096:
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- BlitInternalFPSHack # Fixes internal FPS detection.
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes z fighting in main menu and in game.
|
||||
SLES-53098:
|
||||
name: "Conspiracy - Weapons of Mass Destruction"
|
||||
region: "PAL-M5"
|
||||
@@ -23149,10 +23192,14 @@ SLES-53381:
|
||||
name: "The King of Fighters 2002"
|
||||
name-sort: "King of Fighters 2002, The"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLES-53382:
|
||||
name: "The King of Fighters 2003"
|
||||
name-sort: "King of Fighters 2003, The"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLES-53383:
|
||||
name: "Metal Slug 5"
|
||||
region: "PAL-E"
|
||||
@@ -25279,6 +25326,8 @@ SLES-53999:
|
||||
name: "The King of Fighters - Neo Wave"
|
||||
name-sort: "King of Fighters, The - Neo Wave"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLES-54002:
|
||||
name: "FlatOut 2"
|
||||
region: "PAL-M5"
|
||||
@@ -26428,6 +26477,8 @@ SLES-54374:
|
||||
SLES-54376:
|
||||
name: "Nickelodeon Barnyard"
|
||||
region: "PAL-E"
|
||||
speedHacks:
|
||||
instantVU1: 0 # Significantly improves game speed.
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 2 # Fix text and post blur.
|
||||
autoFlush: 2 # Needed for recursive mipmap rendering.
|
||||
@@ -26436,6 +26487,8 @@ SLES-54376:
|
||||
SLES-54377:
|
||||
name: "Nick - Der tierisch verrückte Bauernhof"
|
||||
region: "PAL-G"
|
||||
speedHacks:
|
||||
instantVU1: 0 # Significantly improves game speed.
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 2 # Fix text and post blur.
|
||||
autoFlush: 2 # Needed for recursive mipmap rendering.
|
||||
@@ -26444,6 +26497,8 @@ SLES-54377:
|
||||
SLES-54378:
|
||||
name: "Nickelodeon Barnyard"
|
||||
region: "PAL-M4"
|
||||
speedHacks:
|
||||
instantVU1: 0 # Significantly improves game speed.
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 2 # Fix text and post blur.
|
||||
autoFlush: 2 # Needed for recursive mipmap rendering.
|
||||
@@ -26523,6 +26578,8 @@ SLES-54394:
|
||||
SLES-54395:
|
||||
name: "NeoGeo Battle Coliseum"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLES-54396:
|
||||
name: "Cricket 07"
|
||||
region: "PAL-E"
|
||||
@@ -26633,6 +26690,8 @@ SLES-54437:
|
||||
name: "The King of Fighters XI"
|
||||
name-sort: "King of Fighters XI, The"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLES-54439:
|
||||
name: "Okami"
|
||||
region: "PAL-M3"
|
||||
@@ -27426,6 +27485,8 @@ SLES-54664:
|
||||
SLES-54665:
|
||||
name: "Paddington Bear"
|
||||
region: "PAL-M11"
|
||||
gsHWFixes:
|
||||
textureInsideRT: 1 # Fixes half right.
|
||||
SLES-54666:
|
||||
name: "Mr. Bean"
|
||||
region: "PAL-M11"
|
||||
@@ -29510,6 +29571,8 @@ SLES-55280:
|
||||
name: "The King of Fighters '98 - Ultimate Match"
|
||||
name-sort: "King of Fighters '98, The - Ultimate Match"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLES-55281:
|
||||
name: "Nickelodeon Dora the Explorer - Dora Saves the Snow Princess"
|
||||
region: "PAL-M3"
|
||||
@@ -31817,6 +31880,8 @@ SLKA-25167:
|
||||
name-sort: "King of Fighters XI, The"
|
||||
name-en: "The King of Fighters XI"
|
||||
region: "NTSC-K"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLKA-25168:
|
||||
name: "스맥다운 대 로우 2007"
|
||||
name-en: "WWE SmackDown! vs. RAW 2007"
|
||||
@@ -32411,11 +32476,15 @@ SLKA-25275:
|
||||
name-sort: "King of Fighters 2002, The"
|
||||
name-en: "The King of Fighters 2002"
|
||||
region: "NTSC-K"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLKA-25276:
|
||||
name: "더 킹 오브 파이터즈 2003"
|
||||
name-sort: "King of Fighters 2003, The"
|
||||
name-en: "The King of Fighters 2003"
|
||||
region: "NTSC-K"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLKA-25277:
|
||||
name: "브라더스 인 암스 - 30 고지를 향한 길"
|
||||
name-en: "Brothers in Arms - Road to Hill 30"
|
||||
@@ -35493,6 +35562,7 @@ SLPM-60174:
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes incorrect blur effect.
|
||||
halfPixelOffset: 4 # Improves blur.
|
||||
limit24BitDepth: 2 # Fixes invisible menus and cursor.
|
||||
SLPM-60175:
|
||||
name: "湾岸ミッドナイト [体験版]"
|
||||
name-sort: "わんがんみっどないと [たいけんばん]"
|
||||
@@ -55109,6 +55179,8 @@ SLPS-20108:
|
||||
name-sort: "くぇーく3 れぼりゅーしょん"
|
||||
name-en: "Quake III - Revolution"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-20109:
|
||||
name: "スター・ウォーズ - スターファイター -"
|
||||
name-sort: "すたーうぉーず すたーふぁいたー"
|
||||
@@ -57304,6 +57376,7 @@ SLPS-25034:
|
||||
name-en: "Flower, Sun, and Rain"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
minimumBlendingLevel: 4 # Fixes broken shading in some areas.
|
||||
textureInsideRT: 1 # Fixes some of the many graphical issues.
|
||||
SLPS-25035:
|
||||
name: "モンスターファーム"
|
||||
@@ -57790,6 +57863,7 @@ SLPS-25113:
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes incorrect blur effect.
|
||||
halfPixelOffset: 4 # Improves blur.
|
||||
limit24BitDepth: 2 # Fixes invisible menus and cursor.
|
||||
SLPS-25114:
|
||||
name: "機甲武装Gブレイカー 第三次クラウディア大戦"
|
||||
name-sort: "きこうぶそうGぶれいかー だいさんじくらうでぃあたいせん"
|
||||
@@ -58024,6 +58098,7 @@ SLPS-25154:
|
||||
name-en: "Flower, Sun, and Rain [Victor The Best]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
minimumBlendingLevel: 4 # Fixes broken shading in some areas.
|
||||
textureInsideRT: 1 # Fixes some of the many graphical issues.
|
||||
SLPS-25155:
|
||||
name: "ウルトラマン Fighting Evolution 2"
|
||||
@@ -59144,6 +59219,8 @@ SLPS-25347:
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーず2002"
|
||||
name-en: "King of Fighters 2002, The"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25348:
|
||||
name: "こころの扉 初回限定版 [コレクターズエディション]"
|
||||
name-sort: "こころのとびら しょかいげんていばん [これくたーずえでぃしょん]"
|
||||
@@ -59540,6 +59617,8 @@ SLPS-25407:
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーず2003"
|
||||
name-en: "King of Fighters 2003, The"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25408:
|
||||
name: "アーマード・コア ナインブレイカー"
|
||||
name-sort: "あーまーどこあ ないんぶれいかー"
|
||||
@@ -59792,11 +59871,15 @@ SLPS-25448:
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーず 94 RE-BOUT [すぺしゃるげんていばん]"
|
||||
name-en: "The King of Fighters '94 - Re-Bout [Special Pack]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25449:
|
||||
name: "THE KING OF FIGHTERS 94 RE-BOUT"
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーず 94 RE-BOUT"
|
||||
name-en: "King of Fighters '94, The - Re-Bout"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25450:
|
||||
name: "テイルズ オブ リバース"
|
||||
name-sort: "ているず おぶ りばーす"
|
||||
@@ -59813,6 +59896,7 @@ SLPS-25451:
|
||||
name-en: "Hana to Taiyou to Ame to [Super Best Collection]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
minimumBlendingLevel: 4 # Fixes broken shading in some areas.
|
||||
textureInsideRT: 1 # Fixes some of the many graphical issues.
|
||||
SLPS-25452:
|
||||
name: "キノの旅 -the Beautiful World- [電撃SP]"
|
||||
@@ -60233,6 +60317,8 @@ SLPS-25525:
|
||||
name-en: "King of Fighters, The - NeoWave"
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25526:
|
||||
name: "MEDICAL 91"
|
||||
name-sort: "めでぃかる 91"
|
||||
@@ -60426,6 +60512,8 @@ SLPS-25558:
|
||||
name-en: "NeoGeo Battle Coliseum"
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25559:
|
||||
name: "サムライスピリッツ 天下一剣客伝"
|
||||
name-sort: "さむらいすぴりっつ てんかいちけんかくでん"
|
||||
@@ -60514,6 +60602,8 @@ SLPS-25573:
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーず2002 [SNK Best Collection]"
|
||||
name-en: "King of Fighters 2002, The [SNK Best Collection]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25574:
|
||||
name: "パチパラ12 ~大海と夏のおもいで~"
|
||||
name-sort: "ぱちぱら12 おおうみとなつのおもいで"
|
||||
@@ -60919,6 +61009,8 @@ SLPS-25635:
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーず2003 [SNK BEST COLLECTION]"
|
||||
name-en: "King of Fighters 2003, The [SNK Best Collection]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25636:
|
||||
name: "KOF MAXIMUM IMPACT MANIAX"
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーず まきしまむ いんぱくと まにあっくす"
|
||||
@@ -61126,6 +61218,8 @@ SLPS-25660:
|
||||
name-en: "King of Fighters XI, The"
|
||||
region: "NTSC-J"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25661:
|
||||
name: "NEOGEOオンラインコレクション Vol.7 THE KING OF FIGHTERS ~ネスツ編~"
|
||||
name-sort: "ねおじおおんらいんこれくしょん Vol. 7 ざ きんぐ おぶ ふぁいたーず ねすつへん"
|
||||
@@ -61434,6 +61528,8 @@ SLPS-25712:
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーず ねお うぇーぶ [SNK BEST COLLECTION]"
|
||||
name-en: "King of Fighters Neowave [SNK Best Collection]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25713:
|
||||
name: "ティンクルスタースプライツーLa Petite Princesse- [SNK BEST COLLECTION]"
|
||||
name-sort: "てぃんくるすたーすぷらいつーLa Petite Princesse- [SNK BEST COLLECTION]"
|
||||
@@ -61589,6 +61685,8 @@ SLPS-25737:
|
||||
name-sort: "ねおじおばとるころしあむ [SNK BEST COLLECTION]"
|
||||
name-en: "Neo Geo Battle Coliseum [SNK Best]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25738:
|
||||
name: "SOUL CRADLE 世界を喰らう者 [初回限定版]"
|
||||
name-sort: "そうるくれいどる せかいをくらうもの [しょかいげんていばん]"
|
||||
@@ -61854,6 +61952,8 @@ SLPS-25783:
|
||||
name-sort: "ねおじおおんらいんこれくしょん Vol.10 ざ きんぐ おぶ ふぁいたーず98あるてぃめっとまっち"
|
||||
name-en: "King of Fighters '98, The - Ultimate Match"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25784:
|
||||
name: "Another Century's Episode 3 THE FINAL"
|
||||
name-sort: "あなざーせんちゅりーずえぴそーど 3 ざ ふぁいなる"
|
||||
@@ -61891,6 +61991,8 @@ SLPS-25789:
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーずⅪ [SNK BEST COLLECTION]"
|
||||
name-en: "King of Fighters XI, The [SNK Best Collection]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25790:
|
||||
name: "NEOGEOオンラインコレクション THE BEST 龍虎の拳 ~天・地・人~"
|
||||
name-sort: "ねおじおおんらいんこれくしょん THE BEST りゅうこのけん てんちじん"
|
||||
@@ -62663,6 +62765,8 @@ SLPS-25915:
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーず2002 UNLIMITED MATCH"
|
||||
name-en: "King of Fighters 2002, The - Unlimited Match"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25916:
|
||||
name: "新宿の狼"
|
||||
name-sort: "しんじゅくのおおかみ"
|
||||
@@ -62771,6 +62875,8 @@ SLPS-25935:
|
||||
name-sort: "ねおじおおんらいんこれくしょん THE BEST ざ きんぐ おぶ ふぁいたーず'98 あるてぃめっとまっち"
|
||||
name-en: "King of Fighters '98, The - Ultimate Match [NeoGeo Online Collection the Best]"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25936:
|
||||
name: "NEOGEOオンラインコレクション THE BEST サンソフトコレクション"
|
||||
name-sort: "ねおじおおんらいんこれくしょん THE BEST さんそふとこれくしょん"
|
||||
@@ -62984,6 +63090,8 @@ SLPS-25983:
|
||||
name-sort: "ざ きんぐ おぶ ふぁいたーず2002 UNLIMITED MATCH とうげきver."
|
||||
name-en: "King of Fighters 2002, The - Unlimited Match"
|
||||
region: "NTSC-J"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLPS-25986:
|
||||
name: "トゥームレイダー アンダーワールド [Spike The Best]"
|
||||
name-sort: "とぅーむれいだー あんだーわーるど [Spike The Best]"
|
||||
@@ -63277,6 +63385,7 @@ SLPS-73204:
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes incorrect blur effect.
|
||||
halfPixelOffset: 4 # Improves blur.
|
||||
limit24BitDepth: 2 # Fixes invisible menus and cursor.
|
||||
SLPS-73205:
|
||||
name: "エースコンバット04 シャッタードスカイ [PlayStation2 the Best]"
|
||||
name-sort: "えーすこんばっと04 しゃったーどすかい [PlayStation2 the Best]"
|
||||
@@ -64700,6 +64809,8 @@ SLUS-20167:
|
||||
name: "Quake III - Revolution"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLUS-20168:
|
||||
name: "Triple Play Baseball"
|
||||
region: "NTSC-U"
|
||||
@@ -66195,7 +66306,7 @@ SLUS-20468:
|
||||
name: "Dynasty Tactics"
|
||||
region: "NTSC-U"
|
||||
SLUS-20469:
|
||||
name: "Xenosaga - Episode I - Der Wille zur Macht"
|
||||
name: "Xenosaga Episode I - Der Wille zur Macht"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
@@ -66679,6 +66790,7 @@ SLUS-20561:
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes incorrect blur effect.
|
||||
halfPixelOffset: 4 # Improves blur.
|
||||
limit24BitDepth: 2 # Fixes invisible menus and cursor.
|
||||
SLUS-20562:
|
||||
name: ".hack Mutation Part 2"
|
||||
region: "NTSC-U"
|
||||
@@ -68494,7 +68606,7 @@ SLUS-20891:
|
||||
memcardFilters:
|
||||
- "SLUS-20488"
|
||||
SLUS-20892:
|
||||
name: "Xenosaga - Episode II - Jenseits von Gut und Böse [Disc 1 of 2]"
|
||||
name: "Xenosaga Episode II - Jenseits von Gut und Böse [Disc 1 of 2]"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
@@ -68513,6 +68625,8 @@ SLUS-20894:
|
||||
name: "Worms 3D"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes z fighting in main menu and in game.
|
||||
SLUS-20895:
|
||||
name: "Bujingai - The Forsaken City"
|
||||
region: "NTSC-U"
|
||||
@@ -69132,9 +69246,13 @@ SLUS-20994:
|
||||
SLUS-20995:
|
||||
name: "King of Fighters 2002 & 2003 [Disc 1 of 2]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLUS-20996:
|
||||
name: "King of Fighters 2002 & 2003 [Disc 2 of 2]"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLUS-20997:
|
||||
name: "Midway Arcade Treasures 2"
|
||||
region: "NTSC-U"
|
||||
@@ -69726,6 +69844,8 @@ SLUS-21093:
|
||||
compat: 5
|
||||
gameFixes:
|
||||
- BlitInternalFPSHack # Fixes internal FPS detection.
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes z fighting in main menu and in game.
|
||||
SLUS-21094:
|
||||
name: "Midway Arcade Treasures 3"
|
||||
region: "NTSC-U"
|
||||
@@ -69961,7 +70081,7 @@ SLUS-21132:
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
SLUS-21133:
|
||||
name: "Xenosaga - Episode II - Jenseits von Gut und Böse [Disc 2 of 2]"
|
||||
name: "Xenosaga Episode II - Jenseits von Gut und Böse [Disc 2 of 2]"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
@@ -70922,6 +71042,8 @@ SLUS-21277:
|
||||
name: "Nickelodeon Barnyard"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
speedHacks:
|
||||
instantVU1: 0 # Significantly improves game speed.
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 2 # Fix text and post blur.
|
||||
autoFlush: 2 # Needed for recursive mipmap rendering.
|
||||
@@ -73394,6 +73516,8 @@ SLUS-21687:
|
||||
name-sort: "King of Fighters XI, The"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLUS-21688:
|
||||
name: "MotoGP '07"
|
||||
region: "NTSC-U"
|
||||
@@ -73495,6 +73619,8 @@ SLUS-21707:
|
||||
SLUS-21708:
|
||||
name: "NeoGeo Battle Coliseum"
|
||||
region: "NTSC-U"
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLUS-21709:
|
||||
name: "Obscure - The Aftermath"
|
||||
region: "NTSC-U"
|
||||
@@ -74116,6 +74242,8 @@ SLUS-21816:
|
||||
name: "King Of Fighters 98 - Ultimate Match"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
limit24BitDepth: 2 # Fixes flickering and missing textures.
|
||||
SLUS-21817:
|
||||
name: "SBK Superbike World Championship"
|
||||
region: "NTSC-U"
|
||||
@@ -74833,6 +74961,7 @@ SLUS-28025:
|
||||
gsHWFixes:
|
||||
autoFlush: 1 # Fixes incorrect blur effect.
|
||||
halfPixelOffset: 4 # Improves blur.
|
||||
limit24BitDepth: 2 # Fixes invisible menus and cursor.
|
||||
SLUS-28026:
|
||||
name: "EverQuest Online Adventures [Beta Vol.3.0]"
|
||||
region: "NTSC-U"
|
||||
@@ -75882,8 +76011,10 @@ TCES-52456:
|
||||
nativeScaling: 1 # Fixes light blooms.
|
||||
autoFlush: 2 # Helps fix misaligned bloom.
|
||||
TCES-52582:
|
||||
name: "Everybody's Golf 4 Beta Trial Code"
|
||||
name: "Everybody's Golf 4 [Beta Trial Code]"
|
||||
region: "PAL-E"
|
||||
gsHWFixes:
|
||||
accurateAlphaTest: 1 # Fixes broken face and UI rendering.
|
||||
TCES-53033:
|
||||
name: "Formula One 05 Beta Trial Code"
|
||||
region: "PAL-E"
|
||||
|
||||
@@ -927,6 +927,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
|
||||
03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
|
||||
03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
|
||||
030000006a0e00001140000001000000,Atari CX Wireless Controller,a:b0,leftx:a0,lefty:a1,platform:Mac OS X,
|
||||
03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
|
||||
03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
|
||||
03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X,
|
||||
@@ -1265,7 +1266,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
03000000020500000913000010010000,Anbernic RG P01,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,
|
||||
03000000373500000710000010010000,Anbernic RG P01,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,
|
||||
05000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
19000000010000000100000000010000,Anbernic RG 35XX,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:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b11,rightx:a2,righty:a3,start:b7,x:b3,y:b2,platform:Linux,
|
||||
03000000190e00000110000010010000,Aquaplus Piece,a:b1,b:b0,back:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b2,platform:Linux,
|
||||
03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
|
||||
@@ -1274,6 +1274,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000050b00000045000040000000,ASUS Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b10,x:b2,y:b3,platform:Linux,
|
||||
03000000050b00000579000011010000,ASUS ROG Kunai 3,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:b36,paddle1:b52,paddle2:b53,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
05000000050b00000679000000010000,ASUS ROG Kunai 3,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:b21,paddle1:b22,paddle2:b23,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
030000006a0e00001140000010010000,Atari CX Wireless Controller,a:b0,leftx:a0,lefty:a1,platform:Linux,
|
||||
03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
|
||||
03000000503200000110000011010000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
|
||||
05000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b4,start:b3,platform:Linux,
|
||||
|
||||
@@ -214,6 +214,16 @@ float rgb5a1_to_depth16(float4 val)
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
float ps_convert_float32_depth_to_color(PS_INPUT input) : SV_Target0
|
||||
{
|
||||
return sample_c(input.t).r;
|
||||
}
|
||||
|
||||
float ps_convert_float32_color_to_depth(PS_INPUT input) : SV_Depth
|
||||
{
|
||||
return sample_c(input.t).r;
|
||||
}
|
||||
|
||||
float ps_convert_float32_float24(PS_INPUT input) : SV_Depth
|
||||
{
|
||||
// Truncates depth value to 24bits
|
||||
|
||||
@@ -21,6 +21,27 @@
|
||||
#define GS_FORWARD_PRIMID 0
|
||||
#endif
|
||||
|
||||
#ifndef ZTST_GEQUAL
|
||||
#define ZTST_GEQUAL 2
|
||||
#define ZTST_GREATER 3
|
||||
#endif
|
||||
|
||||
#ifndef AFAIL_KEEP
|
||||
#define AFAIL_KEEP 0
|
||||
#define AFAIL_FB_ONLY 1
|
||||
#define AFAIL_ZB_ONLY 2
|
||||
#define AFAIL_RGB_ONLY 3
|
||||
#define AFAIL_RGB_ONLY_DSB 4
|
||||
#endif
|
||||
|
||||
#ifndef PS_ATST_NONE
|
||||
#define PS_ATST_NONE 0
|
||||
#define PS_ATST_LEQUAL 1
|
||||
#define PS_ATST_GEQUAL 2
|
||||
#define PS_ATST_EQUAL 3
|
||||
#define PS_ATST_NOTEQUAL 4
|
||||
#endif
|
||||
|
||||
#ifndef PS_FST
|
||||
#define PS_IIP 0
|
||||
#define PS_FST 0
|
||||
@@ -72,6 +93,7 @@
|
||||
#define PS_DITHER_ADJUST 0
|
||||
#define PS_ZCLAMP 0
|
||||
#define PS_ZFLOOR 0
|
||||
#define PS_ZWRITE 0
|
||||
#define PS_SCANMSK 0
|
||||
#define PS_AUTOMATIC_LOD 0
|
||||
#define PS_MANUAL_LOD 0
|
||||
@@ -79,12 +101,16 @@
|
||||
#define PS_NO_COLOR 0
|
||||
#define PS_NO_COLOR1 0
|
||||
#define PS_DATE 0
|
||||
#define PS_TEX_IS_FB 0
|
||||
#define PS_COLOR_FEEDBACK 0
|
||||
#define PS_DEPTH_FEEDBACK 0
|
||||
#endif
|
||||
|
||||
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
|
||||
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
|
||||
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
|
||||
#define NEEDS_RT_FOR_AFAIL (PS_AFAIL == 3 && PS_NO_COLOR1)
|
||||
#define AFAIL_NEEDS_RT (PS_AFAIL == AFAIL_ZB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
|
||||
#define AFAIL_NEEDS_DEPTH (PS_AFAIL == AFAIL_FB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
|
||||
|
||||
struct VS_INPUT
|
||||
{
|
||||
@@ -129,29 +155,42 @@ struct PS_INPUT
|
||||
|
||||
struct PS_OUTPUT
|
||||
{
|
||||
#define NUM_RTS 0
|
||||
#if !PS_NO_COLOR
|
||||
#if PS_DATE == 1 || PS_DATE == 2
|
||||
float c : SV_Target;
|
||||
#else
|
||||
float4 c0 : SV_Target0;
|
||||
#undef NUM_RTS
|
||||
#define NUM_RTS 1
|
||||
#if !PS_NO_COLOR1
|
||||
float4 c1 : SV_Target1;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if (PS_ZFLOOR || PS_ZCLAMP)
|
||||
#if PS_HAS_CONSERVATIVE_DEPTH
|
||||
#if PS_ZWRITE
|
||||
// In DX12 we do depth feedback loops with a color copy.
|
||||
#if PS_DEPTH_FEEDBACK && PS_NO_COLOR1 && DX12
|
||||
#if NUM_RTS > 0
|
||||
float depth_color : SV_Target1;
|
||||
#else
|
||||
float depth_color : SV_Target0;
|
||||
#endif
|
||||
#endif
|
||||
#if PS_HAS_CONSERVATIVE_DEPTH && !PS_DEPTH_FEEDBACK
|
||||
float depth : SV_DepthLessEqual;
|
||||
#else
|
||||
float depth : SV_Depth;
|
||||
#endif
|
||||
#endif
|
||||
#undef NUM_RTS
|
||||
};
|
||||
|
||||
Texture2D<float4> Texture : register(t0);
|
||||
Texture2D<float4> Palette : register(t1);
|
||||
Texture2D<float4> RtTexture : register(t2);
|
||||
Texture2D<float> PrimMinTexture : register(t3);
|
||||
Texture2D<float> DepthTexture : register(t4);
|
||||
SamplerState TextureSampler : register(s0);
|
||||
|
||||
#ifdef DX12
|
||||
@@ -718,27 +757,27 @@ bool atst(float4 C)
|
||||
{
|
||||
float a = C.a;
|
||||
|
||||
if(PS_ATST == 1)
|
||||
{
|
||||
return (a <= AREF);
|
||||
}
|
||||
else if(PS_ATST == 2)
|
||||
{
|
||||
return (a >= AREF);
|
||||
}
|
||||
else if(PS_ATST == 3)
|
||||
{
|
||||
return (abs(a - AREF) <= 0.5f);
|
||||
}
|
||||
else if(PS_ATST == 4)
|
||||
{
|
||||
return (abs(a - AREF) >= 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// nothing to do
|
||||
return true;
|
||||
}
|
||||
#if PS_ATST == PS_ATST_LEQUAL
|
||||
|
||||
return (a <= AREF);
|
||||
|
||||
#elif PS_ATST == PS_ATST_GEQUAL
|
||||
|
||||
return (a >= AREF);
|
||||
|
||||
#elif PS_ATST == PS_ATST_EQUAL
|
||||
|
||||
return (abs(a - AREF) <= 0.5f);
|
||||
|
||||
#elif PS_ATST == PS_ATST_NOTEQUAL
|
||||
|
||||
return (abs(a - AREF) >= 0.5f);
|
||||
|
||||
#else
|
||||
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
float4 fog(float4 c, float f)
|
||||
@@ -1023,10 +1062,31 @@ void ps_blend(inout float4 Color, inout float4 As_rgba, float2 pos_xy)
|
||||
|
||||
PS_OUTPUT ps_main(PS_INPUT input)
|
||||
{
|
||||
// Must floor before depth testing.
|
||||
#if PS_ZFLOOR
|
||||
input.p.z = floor(input.p.z * exp2(32.0f)) * exp2(-32.0f);
|
||||
#endif
|
||||
|
||||
#if PS_DEPTH_FEEDBACK && (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
|
||||
#if PS_ZTST == ZTST_GEQUAL
|
||||
if (input.p.z < DepthTexture.Load(int3(input.p.xy, 0)).r)
|
||||
discard;
|
||||
#elif PS_ZTST == ZTST_GREATER
|
||||
if (input.p.z <= DepthTexture.Load(int3(input.p.xy, 0)).r)
|
||||
discard;
|
||||
#endif
|
||||
#endif // PS_ZTST
|
||||
|
||||
float4 C = ps_color(input);
|
||||
|
||||
#if PS_FIXED_ONE_A
|
||||
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||
C.a = 128.0f;
|
||||
#endif
|
||||
|
||||
bool atst_pass = atst(C);
|
||||
|
||||
#if PS_AFAIL == 0 // KEEP or ATST off
|
||||
#if PS_AFAIL == AFAIL_KEEP
|
||||
if (!atst_pass)
|
||||
discard;
|
||||
#endif
|
||||
@@ -1040,14 +1100,6 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
discard;
|
||||
}
|
||||
|
||||
// Must be done before alpha correction
|
||||
|
||||
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||
if (PS_FIXED_ONE_A)
|
||||
{
|
||||
C.a = 128.0f;
|
||||
}
|
||||
|
||||
float4 alpha_blend = (float4)0.0f;
|
||||
if (SW_AD_TO_HW)
|
||||
{
|
||||
@@ -1192,7 +1244,7 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
|
||||
ps_fbmask(C, input.p.xy);
|
||||
|
||||
#if PS_AFAIL == 3 && !PS_NO_COLOR1 // RGB_ONLY
|
||||
#if (PS_AFAIL == AFAIL_RGB_ONLY_DSB) && !PS_NO_COLOR1
|
||||
// Use alpha blend factor to determine whether to update A.
|
||||
alpha_blend.a = float(atst_pass);
|
||||
#endif
|
||||
@@ -1203,11 +1255,23 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
#if !PS_NO_COLOR1
|
||||
output.c1 = alpha_blend;
|
||||
#endif
|
||||
#if PS_AFAIL == 3 && PS_NO_COLOR1 // RGB_ONLY, no dual src blend
|
||||
|
||||
// Alpha test with feedback
|
||||
#if (PS_AFAIL == AFAIL_FB_ONLY) && PS_DEPTH_FEEDBACK && PS_ZWRITE
|
||||
if (!atst_pass)
|
||||
input.p.z = DepthTexture.Load(int3(input.p.xy, 0)).r;
|
||||
#elif (PS_AFAIL == AFAIL_ZB_ONLY) && PS_COLOR_FEEDBACK
|
||||
if (!atst_pass)
|
||||
output.c0 = RtTexture.Load(int3(input.p.xy, 0));
|
||||
#elif (PS_AFAIL == AFAIL_RGB_ONLY)
|
||||
if (!atst_pass)
|
||||
{
|
||||
float RTa = NEEDS_RT_FOR_AFAIL ? RtTexture.Load(int3(input.p.xy, 0)).a : 0.0f;
|
||||
output.c0.a = RTa;
|
||||
#if PS_COLOR_FEEDBACK
|
||||
output.c0.a = RtTexture.Load(int3(input.p.xy, 0)).a;
|
||||
#endif
|
||||
#if PS_DEPTH_FEEDBACK && PS_ZWRITE
|
||||
input.p.z = DepthTexture.Load(int3(input.p.xy, 0)).r;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1215,16 +1279,16 @@ PS_OUTPUT ps_main(PS_INPUT input)
|
||||
|
||||
#endif // PS_DATE != 1/2
|
||||
|
||||
#if PS_ZFLOOR
|
||||
float depth_value = floor(input.p.z * exp2(32.0f)) * exp2(-32.0f);
|
||||
#else
|
||||
float depth_value = input.p.z;
|
||||
#if PS_ZCLAMP
|
||||
input.p.z = min(input.p.z, MaxDepthPS);
|
||||
#endif
|
||||
|
||||
#if PS_ZCLAMP
|
||||
output.depth = min(depth_value, MaxDepthPS);
|
||||
#elif PS_ZFLOOR
|
||||
output.depth = depth_value;
|
||||
#if PS_ZWRITE
|
||||
#if PS_DEPTH_FEEDBACK && PS_NO_COLOR1 && DX12
|
||||
// Output color clone for feedback as well as real depth.
|
||||
output.depth_color = input.p.z;
|
||||
#endif
|
||||
output.depth = input.p.z;
|
||||
#endif
|
||||
|
||||
return output;
|
||||
|
||||
@@ -43,6 +43,8 @@ layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
// Give a different name so I remember there is a special case!
|
||||
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||
layout(location = 0) out uint SV_Target1;
|
||||
#elif defined(ps_convert_float32_depth_to_color)
|
||||
layout(location = 0) out float SV_Target0;
|
||||
#else
|
||||
layout(location = 0) out vec4 SV_Target0;
|
||||
#endif
|
||||
@@ -145,6 +147,20 @@ float rgb5a1_to_depth16(vec4 unorm)
|
||||
return float(((c.r & 0xF8u) >> 3) | ((c.g & 0xF8u) << 2) | ((c.b & 0xF8u) << 7) | ((c.a & 0x80u) << 8)) * exp2(-32.0f);
|
||||
}
|
||||
|
||||
#ifdef ps_convert_float32_depth_to_color
|
||||
void ps_convert_float32_depth_to_color()
|
||||
{
|
||||
SV_Target0 = sample_c().r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_color_to_depth
|
||||
void ps_convert_float32_color_to_depth()
|
||||
{
|
||||
gl_FragDepth = sample_c().r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_float24
|
||||
void ps_convert_float32_float24()
|
||||
{
|
||||
|
||||
@@ -11,6 +11,27 @@
|
||||
#define SHUFFLE_WRITE 2
|
||||
#define SHUFFLE_READWRITE 3
|
||||
|
||||
#ifndef ZTST_GEQUAL
|
||||
#define ZTST_GEQUAL 2
|
||||
#define ZTST_GREATER 3
|
||||
#endif
|
||||
|
||||
#ifndef AFAIL_KEEP
|
||||
#define AFAIL_KEEP 0
|
||||
#define AFAIL_FB_ONLY 1
|
||||
#define AFAIL_ZB_ONLY 2
|
||||
#define AFAIL_RGB_ONLY 3
|
||||
#define AFAIL_RGB_ONLY_DSB 4
|
||||
#endif
|
||||
|
||||
#ifndef PS_ATST_NONE
|
||||
#define PS_ATST_NONE 0
|
||||
#define PS_ATST_LEQUAL 1
|
||||
#define PS_ATST_GEQUAL 2
|
||||
#define PS_ATST_EQUAL 3
|
||||
#define PS_ATST_NOTEQUAL 4
|
||||
#endif
|
||||
|
||||
// TEX_COORD_DEBUG output the uv coordinate as color. It is useful
|
||||
// to detect bad sampling due to upscaling
|
||||
//#define TEX_COORD_DEBUG
|
||||
@@ -25,9 +46,13 @@
|
||||
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
|
||||
#define PS_PRIMID_INIT (PS_DATE == 1 || PS_DATE == 2)
|
||||
#define NEEDS_RT_EARLY (PS_TEX_IS_FB == 1 || PS_DATE >= 5)
|
||||
#define NEEDS_RT_FOR_AFAIL (PS_AFAIL == 3 && PS_NO_COLOR1)
|
||||
#define NEEDS_RT (NEEDS_RT_EARLY || NEEDS_RT_FOR_AFAIL || (!PS_PRIMID_INIT && (PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW)))
|
||||
#define NEEDS_RT_FOR_AFAIL (PS_AFAIL == PS_ZB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
|
||||
#define NEEDS_DEPTH_FOR_AFAIL (PS_AFAIL == AFAIL_FB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
|
||||
#define NEEDS_DEPTH_FOR_ZTST (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
|
||||
|
||||
#define NEEDS_RT (NEEDS_RT_EARLY || NEEDS_RT_FOR_AFAIL || (!PS_PRIMID_INIT && (PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW)) || PS_COLOR_FEEDBACK)
|
||||
#define NEEDS_TEX (PS_TFX != 4)
|
||||
#define NEEDS_DEPTH (PS_DEPTH_FEEDBACK && (NEEDS_DEPTH_FOR_AFAIL || NEEDS_DEPTH_FOR_ZTST))
|
||||
|
||||
layout(std140, binding = 0) uniform cb21
|
||||
{
|
||||
@@ -97,6 +122,16 @@ in SHADER
|
||||
layout(location = 0) TARGET_0_QUALIFIER vec4 SV_Target0;
|
||||
#endif
|
||||
|
||||
// Depth feedback mode 2 is for depth as color.
|
||||
// Use FB fetch for the feedback if it's available.
|
||||
#if NEEDS_DEPTH && PS_NO_COLOR1 && (DEPTH_FEEDBACK_SUPPORT == 2)
|
||||
#if HAS_FRAMEBUFFER_FETCH
|
||||
layout(location = 1) inout float SV_Target1;
|
||||
#else
|
||||
layout(location = 1) out float SV_Target1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if NEEDS_TEX
|
||||
layout(binding = 0) uniform sampler2D TextureSampler;
|
||||
layout(binding = 1) uniform sampler2D PaletteSampler;
|
||||
@@ -108,12 +143,16 @@ layout(binding = 2) uniform sampler2D RtSampler; // note 2 already use by the im
|
||||
|
||||
#if PS_DATE == 3
|
||||
layout(binding = 3) uniform sampler2D img_prim_min;
|
||||
|
||||
// I don't remember why I set this parameter but it is surely useless
|
||||
//layout(pixel_center_integer) in vec4 gl_FragCoord;
|
||||
#endif
|
||||
|
||||
#if (PS_ZFLOOR || PS_ZCLAMP) && PS_HAS_CONSERVATIVE_DEPTH
|
||||
// Depth feedback mode 1 binds depth buffer directly as a texture.
|
||||
// Depth feedback mode 2 (depth as color) can use FB fetch for the feedback,
|
||||
// in which case we don't need to explicitly bind depth as a texture.
|
||||
#if (DEPTH_FEEDBACK_SUPPORT == 1 || (DEPTH_FEEDBACK_SUPPORT == 2 && !HAS_FRAMEBUFFER_FETCH)) && NEEDS_DEPTH
|
||||
layout(binding = 4) uniform sampler2D DepthSampler;
|
||||
#endif
|
||||
|
||||
#if PS_ZWRITE && PS_HAS_CONSERVATIVE_DEPTH && !NEEDS_DEPTH
|
||||
layout(depth_less) out float gl_FragDepth;
|
||||
#endif
|
||||
|
||||
@@ -128,6 +167,17 @@ vec4 sample_from_rt()
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 sample_from_depth()
|
||||
{
|
||||
#if !NEEDS_DEPTH
|
||||
return vec4(0.0);
|
||||
#elif HAS_FRAMEBUFFER_FETCH && (DEPTH_FEEDBACK_SUPPORT == 2)
|
||||
return SV_Target1;
|
||||
#else
|
||||
return texelFetch(DepthSampler, ivec2(gl_FragCoord.xy), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if NEEDS_TEX
|
||||
|
||||
vec4 sample_c(vec2 uv)
|
||||
@@ -634,17 +684,26 @@ bool atst(vec4 C)
|
||||
{
|
||||
float a = C.a;
|
||||
|
||||
#if (PS_ATST == 1)
|
||||
#if PS_ATST == PS_ATST_LEQUAL
|
||||
|
||||
return (a <= AREF);
|
||||
#elif (PS_ATST == 2)
|
||||
|
||||
#elif PS_ATST == PS_ATST_GEQUAL
|
||||
|
||||
return (a >= AREF);
|
||||
#elif (PS_ATST == 3)
|
||||
|
||||
#elif PS_ATST == PS_ATST_EQUAL
|
||||
|
||||
return (abs(a - AREF) <= 0.5f);
|
||||
#elif (PS_ATST == 4)
|
||||
|
||||
#elif PS_ATST == PS_ATST_NOTEQUAL
|
||||
|
||||
return (abs(a - AREF) >= 0.5f);
|
||||
|
||||
#else
|
||||
// nothing to do
|
||||
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -974,6 +1033,23 @@ float As = As_rgba.a;
|
||||
|
||||
void ps_main()
|
||||
{
|
||||
float input_z = gl_FragCoord.z;
|
||||
|
||||
// Must floor before depth testing.
|
||||
#if PS_ZFLOOR
|
||||
input_z = floor(input_z * exp2(32.0f)) * exp2(-32.0f);
|
||||
#endif
|
||||
|
||||
#if NEEDS_DEPTH && (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
|
||||
#if PS_ZTST == ZTST_GEQUAL
|
||||
if (input_z < sample_from_depth().r)
|
||||
discard;
|
||||
#elif PS_ZTST == ZTST_GREATER
|
||||
if (input_z <= sample_from_depth().r)
|
||||
discard;
|
||||
#endif
|
||||
#endif // PS_ZTST
|
||||
|
||||
#if PS_SCANMSK & 2
|
||||
// fail depth test on prohibited lines
|
||||
if ((int(gl_FragCoord.y) & 1) == (PS_SCANMSK & 1))
|
||||
@@ -1022,18 +1098,17 @@ void ps_main()
|
||||
#endif
|
||||
|
||||
vec4 C = ps_color();
|
||||
bool atst_pass = atst(C);
|
||||
|
||||
#if PS_AFAIL == 0 // KEEP or ATST off
|
||||
if (!atst_pass)
|
||||
discard;
|
||||
#if PS_FIXED_ONE_A
|
||||
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||
C.a = 128.0f;
|
||||
#endif
|
||||
|
||||
// Must be done before alpha correction
|
||||
bool atst_pass = atst(C);
|
||||
|
||||
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||
#if PS_FIXED_ONE_A
|
||||
C.a = 128.0f;
|
||||
#if PS_AFAIL == AFAIL_KEEP
|
||||
if (!atst_pass)
|
||||
discard;
|
||||
#endif
|
||||
|
||||
#if SW_AD_TO_HW
|
||||
@@ -1071,7 +1146,6 @@ void ps_main()
|
||||
|
||||
ps_blend(C, alpha_blend);
|
||||
|
||||
|
||||
#if PS_SHUFFLE
|
||||
#if !PS_READ16_SRC && !PS_SHUFFLE_SAME && !(PS_PROCESS_BA == SHUFFLE_READWRITE && PS_PROCESS_RG == SHUFFLE_READWRITE)
|
||||
uvec4 denorm_c_after = uvec4(C);
|
||||
@@ -1123,41 +1197,64 @@ void ps_main()
|
||||
|
||||
ps_fbmask(C);
|
||||
|
||||
#if PS_AFAIL == 3 && !PS_NO_COLOR1 // RGB_ONLY
|
||||
#if (PS_AFAIL == AFAIL_RGB_ONLY_DSB) && !PS_NO_COLOR1
|
||||
// Use alpha blend factor to determine whether to update A.
|
||||
alpha_blend.a = float(atst_pass);
|
||||
#endif
|
||||
|
||||
#if !PS_NO_COLOR
|
||||
#if PS_RTA_CORRECTION
|
||||
SV_Target0.a = C.a / 128.0f;
|
||||
C.a = C.a / 128.0f;
|
||||
#else
|
||||
SV_Target0.a = C.a / 255.0f;
|
||||
C.a = C.a / 255.0f;
|
||||
#endif
|
||||
#if PS_COLCLIP_HW == 1
|
||||
SV_Target0.rgb = vec3(C.rgb / 65535.0f);
|
||||
C.rgb = vec3(C.rgb / 65535.0f);
|
||||
#else
|
||||
SV_Target0.rgb = C.rgb / 255.0f;
|
||||
C.rgb = C.rgb / 255.0f;
|
||||
#endif
|
||||
#if PS_AFAIL == 3 && PS_NO_COLOR1 // RGB_ONLY, no dual src blend
|
||||
|
||||
// Alpha test with feedback
|
||||
#if (PS_AFAIL == AFAIL_FB_ONLY) && NEEDS_DEPTH && PS_ZWRITE
|
||||
if (!atst_pass)
|
||||
SV_Target0.a = sample_from_rt().a;
|
||||
input_z = sample_from_depth().r;
|
||||
#elif (PS_AFAIL == AFAIL_ZB_ONLY) && NEEDS_RT
|
||||
if (!atst_pass)
|
||||
C = sample_from_rt();
|
||||
#elif (PS_AFAIL == AFAIL_RGB_ONLY)
|
||||
if (!atst_pass)
|
||||
{
|
||||
#if NEEDS_RT
|
||||
C.a = sample_from_rt().a;
|
||||
#endif
|
||||
#if NEEDS_DEPTH && PS_ZWRITE
|
||||
input_z = sample_from_depth().r;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// Warning: do not write SV_Target0 until the end since the value might be needed for
|
||||
// FB fetch in sample_from_rt().
|
||||
SV_Target0 = C;
|
||||
|
||||
#if !PS_NO_COLOR1
|
||||
SV_Target1 = alpha_blend;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PS_ZFLOOR
|
||||
float depth_value = floor(gl_FragCoord.z * exp2(32.0f)) * exp2(-32.0f);
|
||||
#else
|
||||
float depth_value = gl_FragCoord.z;
|
||||
#endif
|
||||
|
||||
#if PS_ZCLAMP
|
||||
gl_FragDepth = min(depth_value, MaxDepthPS);
|
||||
#elif PS_ZFLOOR
|
||||
gl_FragDepth = depth_value;
|
||||
input_z = min(input_z, MaxDepthPS);
|
||||
#endif
|
||||
|
||||
#if PS_ZWRITE
|
||||
#if NEEDS_DEPTH && PS_NO_COLOR1 && (DEPTH_FEEDBACK_SUPPORT == 2)
|
||||
// Depth as color write. For depth as color feedback we write to both
|
||||
// color copy and real depth to avoid having to copy back to real depth.
|
||||
// Warning: do not write SV_Target1 until the end since the value might
|
||||
// be needed for FB fetch in sample_from_depth().
|
||||
SV_Target1 = input_z;
|
||||
#endif
|
||||
// Standard depth write.
|
||||
gl_FragDepth = input_z;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ layout(location = 0) in vec2 v_tex;
|
||||
|
||||
#if defined(ps_convert_rgba8_16bits) || defined(ps_convert_float32_32bits)
|
||||
layout(location = 0) out uint o_col0;
|
||||
#elif defined(ps_convert_float32_depth_to_color)
|
||||
layout(location = 0) out float o_col0;
|
||||
#elif !defined(ps_datm1) && \
|
||||
!defined(ps_datm0) && \
|
||||
!defined(ps_datm1_rta_correction) && \
|
||||
@@ -166,6 +168,20 @@ void ps_colclip_resolve()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_depth_to_color
|
||||
void ps_convert_float32_depth_to_color()
|
||||
{
|
||||
o_col0 = sample_c(v_tex).r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_color_to_depth
|
||||
void ps_convert_float32_color_to_depth()
|
||||
{
|
||||
gl_FragDepth = sample_c(v_tex).r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ps_convert_float32_32bits
|
||||
void ps_convert_float32_32bits()
|
||||
{
|
||||
|
||||
@@ -245,6 +245,27 @@ void main()
|
||||
#define GS_LINE 0
|
||||
#endif
|
||||
|
||||
#ifndef ZTST_GEQUAL
|
||||
#define ZTST_GEQUAL 2
|
||||
#define ZTST_GREATER 3
|
||||
#endif
|
||||
|
||||
#ifndef AFAIL_KEEP
|
||||
#define AFAIL_KEEP 0
|
||||
#define AFAIL_FB_ONLY 1
|
||||
#define AFAIL_ZB_ONLY 2
|
||||
#define AFAIL_RGB_ONLY 3
|
||||
#define AFAIL_RGB_ONLY_DSB 4
|
||||
#endif
|
||||
|
||||
#ifndef PS_ATST_NONE
|
||||
#define PS_ATST_NONE 0
|
||||
#define PS_ATST_LEQUAL 1
|
||||
#define PS_ATST_GEQUAL 2
|
||||
#define PS_ATST_EQUAL 3
|
||||
#define PS_ATST_NOTEQUAL 4
|
||||
#endif
|
||||
|
||||
#ifndef PS_FST
|
||||
#define PS_FST 0
|
||||
#define PS_WMS 0
|
||||
@@ -289,16 +310,28 @@ void main()
|
||||
#define PS_DITHER_ADJUST 0
|
||||
#define PS_ZCLAMP 0
|
||||
#define PS_ZFLOOR 0
|
||||
#define PS_FEEDBACK_LOOP 0
|
||||
#define PS_ZWRITE 0
|
||||
#define PS_SCANMSK 0
|
||||
#define PS_AUTOMATIC_LOD 0
|
||||
#define PS_MANUAL_LOD 0
|
||||
#define PS_TEX_IS_FB 0
|
||||
#define PS_NO_COLOR 0
|
||||
#define PS_NO_COLOR1 0
|
||||
#define PS_DATE 0
|
||||
#define PS_TEX_IS_FB 0
|
||||
#define PS_COLOR_FEEDBACK 0
|
||||
#define PS_DEPTH_FEEDBACK 0
|
||||
#endif
|
||||
|
||||
#define SW_BLEND (PS_BLEND_A || PS_BLEND_B || PS_BLEND_D)
|
||||
#define SW_BLEND_NEEDS_RT (SW_BLEND && (PS_BLEND_A == 1 || PS_BLEND_B == 1 || PS_BLEND_C == 1 || PS_BLEND_D == 1))
|
||||
#define SW_AD_TO_HW (PS_BLEND_C == 1 && PS_A_MASKED)
|
||||
#define AFAIL_NEEDS_RT (PS_AFAIL == 3 && PS_NO_COLOR1)
|
||||
#define AFAIL_NEEDS_RT (PS_AFAIL == AFAIL_ZB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
|
||||
#define AFAIL_NEEDS_DEPTH (PS_AFAIL == AFAIL_FB_ONLY || PS_AFAIL == AFAIL_RGB_ONLY)
|
||||
#define ZTST_NEEDS_DEPTH (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
|
||||
|
||||
#define PS_FEEDBACK_LOOP_IS_NEEDED (PS_TEX_IS_FB == 1 || AFAIL_NEEDS_RT || PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW || (PS_DATE >= 5))
|
||||
#define PS_FEEDBACK_LOOP_IS_NEEDED_RT (PS_TEX_IS_FB == 1 || AFAIL_NEEDS_RT || PS_FBMASK || SW_BLEND_NEEDS_RT || SW_AD_TO_HW || (PS_DATE >= 5) || PS_COLOR_FEEDBACK)
|
||||
#define PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH (PS_DEPTH_FEEDBACK && (AFAIL_NEEDS_DEPTH || ZTST_NEEDS_DEPTH))
|
||||
|
||||
#define NEEDS_TEX (PS_TFX != 4)
|
||||
|
||||
@@ -347,13 +380,30 @@ layout(set = 1, binding = 0) uniform sampler2D Texture;
|
||||
layout(set = 1, binding = 1) uniform texture2D Palette;
|
||||
#endif
|
||||
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_RT || PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH
|
||||
#if defined(DISABLE_TEXTURE_BARRIER) || defined(HAS_FEEDBACK_LOOP_LAYOUT)
|
||||
layout(set = 1, binding = 2) uniform texture2D RtSampler;
|
||||
vec4 sample_from_rt() { return texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0); }
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_RT
|
||||
layout(set = 1, binding = 2) uniform texture2D RtSampler;
|
||||
vec4 sample_from_rt() { return texelFetch(RtSampler, ivec2(gl_FragCoord.xy), 0); }
|
||||
#endif
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH
|
||||
layout(set = 1, binding = 4) uniform texture2D DepthSampler;
|
||||
vec4 sample_from_depth() { return texelFetch(DepthSampler, ivec2(gl_FragCoord.xy), 0); }
|
||||
#endif
|
||||
#else
|
||||
layout(input_attachment_index = 0, set = 1, binding = 2) uniform subpassInput RtSampler;
|
||||
vec4 sample_from_rt() { return subpassLoad(RtSampler); }
|
||||
// Must consider each case separately since the input attachment indices must be consecutive.
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_RT && PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH
|
||||
layout(input_attachment_index = 0, set = 1, binding = 2) uniform subpassInput RtSampler;
|
||||
layout(input_attachment_index = 1, set = 1, binding = 4) uniform subpassInput DepthSampler;
|
||||
vec4 sample_from_rt() { return subpassLoad(RtSampler); }
|
||||
vec4 sample_from_depth() { return subpassLoad(DepthSampler); }
|
||||
#elif PS_FEEDBACK_LOOP_IS_NEEDED_RT
|
||||
layout(input_attachment_index = 0, set = 1, binding = 2) uniform subpassInput RtSampler;
|
||||
vec4 sample_from_rt() { return subpassLoad(RtSampler); }
|
||||
#elif PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH
|
||||
layout(input_attachment_index = 0, set = 1, binding = 4) uniform subpassInput DepthSampler;
|
||||
vec4 sample_from_depth() { return subpassLoad(DepthSampler); }
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -361,7 +411,7 @@ layout(set = 1, binding = 1) uniform texture2D Palette;
|
||||
layout(set = 1, binding = 3) uniform texture2D PrimMinTexture;
|
||||
#endif
|
||||
|
||||
#if PS_ZFLOOR || PS_ZCLAMP
|
||||
#if PS_ZWRITE && !PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH
|
||||
layout(depth_less) out float gl_FragDepth;
|
||||
#endif
|
||||
|
||||
@@ -885,28 +935,27 @@ bool atst(vec4 C)
|
||||
{
|
||||
float a = C.a;
|
||||
|
||||
#if (PS_ATST == 1)
|
||||
{
|
||||
return (a <= AREF);
|
||||
}
|
||||
#elif (PS_ATST == 2)
|
||||
{
|
||||
return (a >= AREF);
|
||||
}
|
||||
#elif (PS_ATST == 3)
|
||||
{
|
||||
return (abs(a - AREF) <= 0.5f);
|
||||
}
|
||||
#elif (PS_ATST == 4)
|
||||
{
|
||||
return (abs(a - AREF) >= 0.5f);
|
||||
}
|
||||
#else
|
||||
{
|
||||
// nothing to do
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#if PS_ATST == PS_ATST_LEQUAL
|
||||
|
||||
return (a <= AREF);
|
||||
|
||||
#elif PS_ATST == PS_ATST_GEQUAL
|
||||
|
||||
return (a >= AREF);
|
||||
|
||||
#elif PS_ATST == PS_ATST_EQUAL
|
||||
|
||||
return (abs(a - AREF) <= 0.5f);
|
||||
|
||||
#elif PS_ATST == PS_ATST_NOTEQUAL
|
||||
|
||||
return (abs(a - AREF) >= 0.5f);
|
||||
|
||||
#else
|
||||
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 fog(vec4 c, float f)
|
||||
@@ -975,7 +1024,6 @@ vec4 ps_color()
|
||||
void ps_fbmask(inout vec4 C)
|
||||
{
|
||||
#if PS_FBMASK
|
||||
|
||||
#if PS_COLCLIP_HW == 1
|
||||
vec4 RT = trunc(sample_from_rt() * 65535.0f);
|
||||
#else
|
||||
@@ -1071,7 +1119,7 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
|
||||
As_rgba.rgb = vec3(1.0f);
|
||||
#endif
|
||||
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_RT
|
||||
vec4 RT = sample_from_rt();
|
||||
#else
|
||||
// Not used, but we define it to make the selection below simpler.
|
||||
@@ -1084,7 +1132,7 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
|
||||
float Ad = trunc(RT.a * 255.0f + 0.1f) / 128.0f;
|
||||
#endif
|
||||
|
||||
#if PS_SHUFFLE && PS_FEEDBACK_LOOP_IS_NEEDED
|
||||
#if PS_SHUFFLE && PS_FEEDBACK_LOOP_IS_NEEDED_RT
|
||||
uvec4 denorm_rt = uvec4(RT);
|
||||
#if (PS_PROCESS_BA & SHUFFLE_WRITE)
|
||||
RT.r = float((denorm_rt.b << 3) & 0xF8u);
|
||||
@@ -1236,6 +1284,23 @@ void ps_blend(inout vec4 Color, inout vec4 As_rgba)
|
||||
|
||||
void main()
|
||||
{
|
||||
float input_z = gl_FragCoord.z;
|
||||
|
||||
// Must floor before depth testing.
|
||||
#if PS_ZFLOOR
|
||||
input_z = floor(input_z * exp2(32.0f)) * exp2(-32.0f);
|
||||
#endif
|
||||
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH && (PS_ZTST == ZTST_GEQUAL || PS_ZTST == ZTST_GREATER)
|
||||
#if PS_ZTST == ZTST_GEQUAL
|
||||
if (input_z < sample_from_depth().r)
|
||||
discard;
|
||||
#elif PS_ZTST == ZTST_GREATER
|
||||
if (input_z <= sample_from_depth().r)
|
||||
discard;
|
||||
#endif
|
||||
#endif // PS_ZTST
|
||||
|
||||
#if PS_SCANMSK & 2
|
||||
// fail depth test on prohibited lines
|
||||
if ((int(gl_FragCoord.y) & 1) == (PS_SCANMSK & 1))
|
||||
@@ -1283,18 +1348,17 @@ void main()
|
||||
#endif
|
||||
|
||||
vec4 C = ps_color();
|
||||
bool atst_pass = atst(C);
|
||||
|
||||
#if PS_AFAIL == 0 // KEEP or ATST off
|
||||
if (!atst_pass)
|
||||
discard;
|
||||
#if PS_FIXED_ONE_A
|
||||
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||
C.a = 128.0f;
|
||||
#endif
|
||||
|
||||
// Must be done before alpha correction
|
||||
bool atst_pass = atst(C);
|
||||
|
||||
// AA (Fixed one) will output a coverage of 1.0 as alpha
|
||||
#if PS_FIXED_ONE_A
|
||||
C.a = 128.0f;
|
||||
#if PS_AFAIL == AFAIL_KEEP
|
||||
if (!atst_pass)
|
||||
discard;
|
||||
#endif
|
||||
|
||||
#if SW_AD_TO_HW
|
||||
@@ -1333,7 +1397,7 @@ void main()
|
||||
#else
|
||||
ps_blend(C, alpha_blend);
|
||||
|
||||
#if PS_SHUFFLE
|
||||
#if PS_SHUFFLE
|
||||
#if !PS_READ16_SRC && !PS_SHUFFLE_SAME && !(PS_PROCESS_BA == SHUFFLE_READWRITE && PS_PROCESS_RG == SHUFFLE_READWRITE)
|
||||
uvec4 denorm_c_after = uvec4(C);
|
||||
#if (PS_PROCESS_BA & SHUFFLE_READ)
|
||||
@@ -1381,7 +1445,7 @@ void main()
|
||||
|
||||
ps_fbmask(C);
|
||||
|
||||
#if PS_AFAIL == 3 && !PS_NO_COLOR1 // RGB_ONLY
|
||||
#if (PS_AFAIL == AFAIL_RGB_ONLY_DSB) && !PS_NO_COLOR1
|
||||
// Use alpha blend factor to determine whether to update A.
|
||||
alpha_blend.a = float(atst_pass);
|
||||
#endif
|
||||
@@ -1400,24 +1464,34 @@ void main()
|
||||
#if !PS_NO_COLOR1
|
||||
o_col1 = alpha_blend;
|
||||
#endif
|
||||
#if PS_AFAIL == 3 && PS_NO_COLOR1 // RGB_ONLY, no dual src blend
|
||||
|
||||
// Alpha test with feedback
|
||||
#if (PS_AFAIL == AFAIL_FB_ONLY) && PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH && PS_ZWRITE
|
||||
if (!atst_pass)
|
||||
input_z = sample_from_depth().r;
|
||||
#elif (PS_AFAIL == AFAIL_ZB_ONLY) && PS_FEEDBACK_LOOP_IS_NEEDED_RT
|
||||
if (!atst_pass)
|
||||
o_col0 = sample_from_rt();
|
||||
#elif (PS_AFAIL == AFAIL_RGB_ONLY)
|
||||
if (!atst_pass)
|
||||
{
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_RT
|
||||
o_col0.a = sample_from_rt().a;
|
||||
#endif
|
||||
#if PS_FEEDBACK_LOOP_IS_NEEDED_DEPTH && PS_ZWRITE
|
||||
input_z = sample_from_depth().r;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if PS_ZFLOOR
|
||||
float depth_value = floor(gl_FragCoord.z * exp2(32.0f)) * exp2(-32.0f);;
|
||||
#else
|
||||
float depth_value = gl_FragCoord.z;
|
||||
#if PS_ZCLAMP
|
||||
input_z = min(input_z, MaxDepthPS);
|
||||
#endif
|
||||
|
||||
#if PS_ZCLAMP
|
||||
gl_FragDepth = min(gl_FragCoord.z, MaxDepthPS);
|
||||
#elif PS_ZFLOOR
|
||||
gl_FragDepth = depth_value;
|
||||
#if PS_ZWRITE
|
||||
gl_FragDepth = input_z;
|
||||
#endif
|
||||
|
||||
#endif // PS_DATE
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ option(LTO_PCSX2_CORE "Enable LTO/IPO/LTCG on the subset of pcsx2 that benefits
|
||||
option(USE_VTUNE "Plug VTUNE to profile GS JIT.")
|
||||
option(PACKAGE_MODE "Use this option to ease packaging of PCSX2 (developer/distribution option)")
|
||||
option(BUNDLE_EMOJI_FONT "Bundles Noto Color Emoji for systems whose system emoji font isn't usable by freetype" ON)
|
||||
option(POSITION_INDEPENDENT_CODE "Generate position-independent code. It is recommended that you leave this on." ON)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Graphical option
|
||||
@@ -270,6 +271,34 @@ endif()
|
||||
|
||||
set(PCSX2_WARNINGS ${DEFAULT_WARNINGS})
|
||||
|
||||
if(POSITION_INDEPENDENT_CODE)
|
||||
# Make sure position-independent code is enabled properly.
|
||||
# Without this check, on some platforms (e.g. Fedora 43) the right flags
|
||||
# won't be passed to the linker, resulting in a broken build when link time
|
||||
# optimization is enabled (even with a cmake version >= 3.14).
|
||||
if(NOT MSVC)
|
||||
include(CheckPIESupported)
|
||||
check_pie_supported(OUTPUT_VARIABLE PIE_SUPPORTED_OUTPUT LANGUAGES C CXX)
|
||||
|
||||
if((NOT CMAKE_C_LINK_PIE_SUPPORTED) OR (NOT CMAKE_CXX_LINK_PIE_SUPPORTED))
|
||||
message(WARNING
|
||||
"The POSITION_INDEPENDENT_CODE option is enabled but is not "
|
||||
"supported at link time:\n${PIE_SUPPORTED_OUTPUT}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
else()
|
||||
if(CMAKE_INTERPROCEDURAL_OPTIMIZATION)
|
||||
message(WARNING
|
||||
"The CMAKE_INTERPROCEDURAL_OPTIMIZATION option is enabled but the "
|
||||
"CMAKE_POSITION_INDEPENDENT_CODE option is disabled. This has been "
|
||||
"found to result in broken builds on certain platforms.")
|
||||
endif()
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE OFF)
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# MacOS-specific things
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@@ -19,6 +19,7 @@ target_sources(common PRIVATE
|
||||
HostSys.cpp
|
||||
Image.cpp
|
||||
HTTPDownloader.cpp
|
||||
MemoryInterface.cpp
|
||||
MemorySettingsInterface.cpp
|
||||
MD5Digest.cpp
|
||||
PrecompiledHeader.cpp
|
||||
@@ -58,6 +59,7 @@ target_sources(common PRIVATE
|
||||
LRUCache.h
|
||||
HeapArray.h
|
||||
HTTPDownloader.h
|
||||
MemoryInterface.h
|
||||
MemorySettingsInterface.h
|
||||
MD5Digest.h
|
||||
MRCHelpers.h
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user