Compare commits

...
63 Commits
Author SHA1 Message Date
SternXD 37a8be7b42 MSBuild: Replace .sln with new .slnx format 2026-09-11 08:52:16 -04:00
dependabot[bot] 4cdda8d99b Deps/gha: Bump the ci-deps group with 2 updates
Bumps the ci-deps group with 2 updates: [flatpak/flatpak-github-actions/flatpak-builder](https://github.com/flatpak/flatpak-github-actions) and [flatpak/flatpak-github-actions/flat-manager](https://github.com/flatpak/flatpak-github-actions).


Updates `flatpak/flatpak-github-actions/flatpak-builder` from 6.7 to 6.8
- [Release notes](https://github.com/flatpak/flatpak-github-actions/releases)
- [Commits](https://github.com/flatpak/flatpak-github-actions/compare/401fe28a8384095fc1531b9d320b292f0ee45adb...79327416609af08178ad73b352877e51450790b3)

Updates `flatpak/flatpak-github-actions/flat-manager` from 6.7 to 6.8
- [Release notes](https://github.com/flatpak/flatpak-github-actions/releases)
- [Commits](https://github.com/flatpak/flatpak-github-actions/compare/401fe28a8384095fc1531b9d320b292f0ee45adb...79327416609af08178ad73b352877e51450790b3)

---
updated-dependencies:
- dependency-name: flatpak/flatpak-github-actions/flatpak-builder
  dependency-version: '6.8'
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci-deps
- dependency-name: flatpak/flatpak-github-actions/flat-manager
  dependency-version: '6.8'
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: ci-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-09-11 11:41:56 +02:00
lightningterror a5fc5aefc9 GS/DX12: Enable dx12 support on haswell/broadwell if supported.
Could be useful for testing, also there's no need to lock it out even if it has issues as it can come in handy similar to Fermi.
2026-09-11 03:13:30 +02:00
lightningterror e6a88bccff GS/HW: Purge Ultraman Fighting Evolution crc.
Not needed anymore.
2026-09-11 03:12:17 +02:00
PCSX2 Bot 0caaa2cb49 [ci skip] Qt: Update Base Translation. 2026-09-11 03:10:53 +02:00
TJnotJT 4a4cbb875e GS: Allow logging frame timings stats using hotkey. 2026-09-10 06:47:15 +02:00
TJnotJT 6a0d3011ab GS: Add options to dump replay frame range.
Also allow dumping stats from the GUI after running a dump.
2026-09-10 06:47:15 +02:00
TJnotJT d3cc62f37e GS:VK:DX12: Code cleanup for GPU timing. 2026-09-10 06:47:15 +02:00
PCSX2 Bot 32c19d94fa [ci skip] Qt: Update Base Translation. 2026-09-09 20:12:43 -04:00
JordanTheToaster 1810140d1d Core: Split frame limiter in to two wait points 2026-09-09 04:14:30 +02:00
JordanTheToaster 7676b1f73e Counters: Add new Advanced Frame Display setting 2026-09-09 04:14:30 +02:00
TJnotJT bbc57ec622 GS:HW: Fix bpp assertion in GetConvertShader(). 2026-09-09 03:08:21 +02:00
PCSX2 Bot 98697735f1 [ci skip] PAD: Update to latest controller database. 2026-09-07 18:09:09 +02:00
refractionpcsx2 4102a0bd2c VU-JIT: Correct mask for ignoring mac flags on non exact matches 2026-09-07 02:35:34 +02:00
refractionpcsx2 cb3c60557e Build: add hyphens to commit checker 2026-09-07 02:35:34 +02:00
PCSX2 Bot c62d29e6a1 [ci skip] Qt: Update Base Translation. 2026-09-06 20:23:41 -04:00
TJnotJT ac24959c4a GS: Use "coords" in rewrite large ST hack for clarity. 2026-09-07 01:06:22 +02:00
TellowKrinkle 236f67a82f CMake: Minimum Qt is 6.10 2026-09-05 23:14:42 -04:00
JordanTheToaster 4e9c5dcc88 Flatpak: Update KDE runtime to 6.11 2026-09-05 19:53:07 +02:00
PCSX2 Bot 450a39a37c [ci skip] Qt: Update Base Translation. 2026-09-05 02:08:01 +02:00
Tundrak ca0145e6aa InputRecording: Reset controller state after input playback 2026-09-04 11:20:01 -04:00
Tundrak 20c51dd80e Pad: Add functions to reset controller inputs 2026-09-04 11:20:01 -04:00
lightningterror aaf03c18b6 GS/TC: Fix -Wsign-compare warning. 2026-09-04 13:35:32 +02:00
TJnotJT 77bec5e0f5 GS/HW: Rewrite vertices if large ST.
Adds vertex rewriting functionality to both HW/SW. Aggressive version is user hack. Adds a GameDB hack for Ridge Racer V and Destruction Derby Arena. For SW, a less aggressive version is used if the hack is not enabled.
2026-09-04 12:05:30 +02:00
refractionpcsx2 f0cd834ed2 GS/HW: Improve source channel requirements for source lookups 2026-09-04 11:44:35 +02:00
TJnotJT 77cfac7dbe GS:HW: Do ROV channel masking with FBMask. 2026-09-04 11:39:30 +02:00
refractionpcsx2 ca5942151a Counters: Remove some magic numbers and use default framerates 2026-09-04 11:10:37 +02:00
refractionpcsx2 0be8947a33 Counters: Make sure uninitialized blank calculations use correct timing 2026-09-04 11:10:37 +02:00
refractionpcsx2 33127ad0df Core: Init video mode based on disc, bios or default NTSC, where available 2026-09-04 11:10:37 +02:00
PCSX2 Bot c475c752bf [ci skip] Qt: Update Base Translation. 2026-09-04 02:04:37 +02:00
TJnotJT bd9b6daaad GS:HW: Reduce primid max value.
Large values may cause errors in primid DATE on Mesa OpenGL.
2026-09-04 01:37:00 +02:00
TJnotJT 9120e6fb6a GS:HW: Allow dumping PrimID texture with RT dumping. 2026-09-04 01:37:00 +02:00
TellowKrinkle 65dc286e9b GS:VK: Use swizzle value compatible with MoltenVK on older GPUs 2026-09-03 19:20:31 +02:00
TellowKrinkle 4545e24f7d GHActions:MacOS: Add MoltenVK patch for older GPUs 2026-09-03 19:20:31 +02:00
Mrlinkwii deb6edc076 Github : update issue types
[ci skip]
2026-09-03 17:51:34 +02:00
Brian Degenhardt 969c3b54b8 EE:Rec: remove superfluous clamp in recRAMCopy check 2026-09-03 11:42:51 -04:00
Brian Degenhardt d9dcb0abd7 EE:Rec: Fix recRAMCopy block compression
Once upon a time recRAMCopy was an array of words and stored a copy of compiled
blocks to verify if a new block overwrote the old blocks by straddling them.
However it was changed to an array of u8 and the /4 was never fixed.

It still kinda works, copying blocks into a quarter-sized compressed space,
it just thinks that blocks overlap way more than they do, causing recompilation
storms in some situations.

This PR fixes it to use the whole space.
2026-09-03 11:42:51 -04:00
SternXD d53b89a848 3rdparty/imgui: Update to v1.92.9b
Signed-off-by: SternXD <stern@sidestore.io>
2026-09-03 17:38:04 +02:00
refractionpcsx2 3d9fea596d GS/HW: Update depth conversion shader to floor value 2026-09-03 17:25:12 +02:00
refractionpcsx2 e1a2faf5c2 GS/HW: Fix regression where target updates ignored bilinear 2026-09-03 17:25:12 +02:00
JordanTheToaster 5c622f5da2 Deps: Update SDL3 to v3.4.16 2026-09-03 15:55:19 +02:00
JordanTheToaster a27da45e42 Deps: Update Qt to 6.11.2 2026-09-03 14:49:04 +02:00
refractionpcsx2 5b97290458 GS/TC: Update alpha channel of 24bit target is alpha is dirty 2026-09-03 14:41:45 +02:00
refractionpcsx2 14f06312d1 GS/TC: Disallow badly misaligned GPU CLUT textures 2026-09-03 14:41:45 +02:00
refractionpcsx2 73d21a3612 GS/TC: Detect alpha channel source width mismatches 2026-09-03 14:41:45 +02:00
refractionpcsx2 86dc3189c7 GS/HW: Consider FBMSK combos when using CSBW 2026-09-03 14:41:45 +02:00
SternXD eb3fc0dbea EE/Rec: Move opcode defs to common header
Signed-off-by: SternXD <stern@sidestore.io>
2026-09-03 14:24:07 +02:00
Ziemas b67a81f6e7 DEV9: Fix DMA size weirdness 2026-09-03 14:16:13 +02:00
Ziemas e35bdddab2 IOP: Clear jit cache on DEV9 DMA 2026-09-03 14:16:13 +02:00
refractionpcsx2 d55f21a4b5 GS/HW: Improve Native Scaling recursive draw check 2026-09-03 14:14:47 +02:00
refractionpcsx2 bccd50df39 GS/HW/NS: Detect fake bilinear jiggle effect 2026-09-03 14:14:47 +02:00
refractionpcsx2 0710693150 GameDB: Add required GameDB Entries
S.L.A.I. - Steel Lancer Arena International
Syphon Filter - Logan's Shadow
2026-09-03 14:14:47 +02:00
refractionpcsx2 01ad055f25 GS/HW: Improve "jiggle" blur effect detection and handling 2026-09-03 14:14:47 +02:00
refractionpcsx2 c2b4bc217e GS/HW: Native Scaling detection of mild downscale and write back 2026-09-03 14:14:47 +02:00
SternXD 1c04aeb160 Achievements: Fix deadlock when enabling achievements in FullscreenUI 2026-09-03 14:12:06 +02:00
mahoneyt944 67aadac40c GameDB: Fit EA login into naming format 2026-09-01 21:20:05 +02:00
mahoneyt944 e37f8ad236 GameDB: add more burnout 3 serials - online login 2026-09-01 21:20:05 +02:00
mahoneyt944 6199c0de13 GameDB: use correct names to filter EA network account folders, pal / ntsc 2026-09-01 21:20:05 +02:00
lightningterror 2bbb92de16 GS/DX11: DS as RT/UAV binding fixes.
Properly unbind state in BeginPresent.
Properly update state in OMSetRenderTargets.
Also use ds as rt size for Viewport.
2026-09-01 21:09:57 +02:00
SternXD 3f794a9c9d Deps: Fetch make for Windows FFmpeg builds
Signed-off-by: SternXD <stern@sidestore.io>
2026-09-01 15:08:59 +02:00
SternXD 5939027d10 Deps: Always build FFmpeg on Windows
Signed-off-by: SternXD <stern@sidestore.io>
2026-09-01 15:08:59 +02:00
PCSX2 Bot 00482e8ada [ci skip] Qt: Update Base Translation. 2026-09-01 02:04:16 +02:00
SternXD 77236c5949 GS: Output BGCOLOR when both display circuits are disabled
Signed-off-by: SternXD <stern@sidestore.io>
2026-08-31 20:46:29 +02:00
133 changed files with 7915 additions and 5516 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
* text=auto
# Declare files that will always have CRLF line endings on checkout.
*.sln text eol=crlf
*.slnx text eol=crlf
*.props text eol=crlf
*.vcxproj text eol=crlf
*.vcxproj.filters text eol=crlf
@@ -3,6 +3,7 @@ name: Application Bug Report
description: Found a problem with the application itself (ie. bad file path handling, UX issue)? Help us improve it.
title: "[BUG]: "
labels: [Bug]
type: Bug
# assignees:
# - octocat
body:
@@ -3,6 +3,7 @@ name: Emulation Bug Report
description: Problem in a game (ie. graphical artifacts, crashes)? Help us improve it.
title: "[BUG]: "
labels: [Bug]
type: Bug
# assignees:
# - octocat
body:
@@ -3,6 +3,7 @@ name: Feature request
description: Suggest a new feature or improve an existing one
title: "[Feature Request]: "
labels: ["Enhancement / Feature Request", "FR: Awaiting Consideration"]
type: Feature Request
# assignees:
# - octocat
body:
+2 -2
View File
@@ -6,8 +6,8 @@
- any-glob-to-any-file:
- '.github/*'
- '.github/**/*'
- '*.sln'
- '**/*.sln'
- '*.slnx'
- '**/*.slnx'
- '*.vcxproj*'
- '**/*.vcxproj*'
- 'cmake/*'
+1 -1
View File
@@ -16,7 +16,7 @@ jobs:
uses: gsactions/commit-message-checker@16fa2d5de096ae0d35626443bcd24f1e756cafee
with:
accessToken: ${{ secrets.GITHUB_TOKEN }}
pattern: '^[A-Z0-9][A-Za-z0-9 \["\/\\]+:.+'
pattern: '^[A-Z0-9][A-Za-z0-9 \["\/\\-]+:.+'
excludeTitle: true
excludeDescription: true
checkAllCommitMessages: true
+5 -5
View File
@@ -45,7 +45,7 @@ jobs:
name: ${{ inputs.jobName }}
runs-on: ${{ inputs.os }}
container:
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.9
image: ghcr.io/flathub-infra/flatpak-github-actions:kde-6.10
options: --privileged
timeout-minutes: 60
@@ -93,7 +93,7 @@ jobs:
- name: Build Flatpak (beta)
if: ${{ inputs.stableBuild == false || inputs.stableBuild == 'false' }}
uses: flatpak/flatpak-github-actions/flatpak-builder@401fe28a8384095fc1531b9d320b292f0ee45adb
uses: flatpak/flatpak-github-actions/flatpak-builder@79327416609af08178ad73b352877e51450790b3
with:
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
upload-artifact: false
@@ -109,7 +109,7 @@ jobs:
- name: Build Flatpak (stable)
if: ${{ inputs.stableBuild == true || inputs.stableBuild == 'true' }}
uses: flatpak/flatpak-github-actions/flatpak-builder@401fe28a8384095fc1531b9d320b292f0ee45adb
uses: flatpak/flatpak-github-actions/flatpak-builder@79327416609af08178ad73b352877e51450790b3
with:
bundle: ${{ steps.artifact-metadata.outputs.artifact-name }}.flatpak
upload-artifact: false
@@ -129,7 +129,7 @@ jobs:
- name: Push to Flathub (beta)
if: ${{ inputs.publish == true && (inputs.stableBuild == false || inputs.stableBuild == 'false') }}
uses: flatpak/flatpak-github-actions/flat-manager@401fe28a8384095fc1531b9d320b292f0ee45adb
uses: flatpak/flatpak-github-actions/flat-manager@79327416609af08178ad73b352877e51450790b3
with:
flat-manager-url: https://hub.flathub.org/
repository: beta
@@ -138,7 +138,7 @@ jobs:
- name: Push to Flathub (stable)
if: ${{ inputs.publish == true && (inputs.stableBuild == true || inputs.stableBuild == 'true') }}
uses: flatpak/flatpak-github-actions/flat-manager@401fe28a8384095fc1531b9d320b292f0ee45adb
uses: flatpak/flatpak-github-actions/flat-manager@79327416609af08178ad73b352877e51450790b3
with:
flat-manager-url: https://hub.flathub.org/
repository: stable
@@ -18,7 +18,7 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
INSTALLDIR="$PWD/$INSTALLDIR"
fi
QT=6.11.1
QT=6.11.2
QTAPNG=1.3.0
FFMPEG=9.0.1
@@ -27,7 +27,7 @@ LIBJPEGTURBO=3.2.0
LIBPNG=1.6.58
LIBWEBP=1.6.0
NVENC=13.0.19.0
SDL=SDL3-3.4.12
SDL=SDL3-3.4.16
LZ4=1.10.0
VULKAN=1.4.328.1
ZSTD=1.5.7
@@ -47,12 +47,12 @@ cd deps-build
export PKG_CONFIG_PATH="$INSTALLDIR/lib/pkgconfig:$PKG_CONFIG_PATH"
grep . > SHASUMS <<EOF
d9594a31228aa23ad6b531719a29b45f0f3989fe6c136d45767ea179f233c1ac qtbase-everywhere-src-$QT.tar.xz
b2bf6c6845ac175ed7f819145483ba4676f617aaa6a5012c8efee63c8bbac413 qtimageformats-everywhere-src-$QT.tar.xz
7f3cf02f4824bf03c2c5859ea6db173bf1482a1daf24e6cdf7bc78cfa26a8a94 qtsvg-everywhere-src-$QT.tar.xz
8e61835a679c93fa9c6065b142353c2071ba68e297898937c32a03777fcaf50d qttools-everywhere-src-$QT.tar.xz
37c02c81206594c7bb4edca85ac93e8e55a9836b70c960fde6cb0f8623ec5677 qttranslations-everywhere-src-$QT.tar.xz
95788aa502f75441d4edf65932b235f76523084e13dbbb7b9ee2d207b32bd9b3 qtwayland-everywhere-src-$QT.tar.xz
5b2e00eccaf5a4d8c14134ffa0ea8dfd0a35ae1ffc7f8d87fa4305a1ed23cf22 qtbase-everywhere-src-$QT.tar.xz
cecd8900f34b6550076309bc94f62f828008b633a4239e0a08c86788f41001f8 qtimageformats-everywhere-src-$QT.tar.xz
d594337feca84c26fb67fe87b85e6a5c12fda404b611d905f9d138210c311876 qtsvg-everywhere-src-$QT.tar.xz
9ea75af35c512f7e09e61c8c3af3997f13b4d43bb099cf43fcec470126b4041e qttools-everywhere-src-$QT.tar.xz
021684c1a7937a9fabc3b056a6698ad5978794caf9ac190fd6cc11399e67c014 qttranslations-everywhere-src-$QT.tar.xz
8eb7615e39332a10f506e8dd70f02d5954bb5949ff54f6dcbf8bd6168222f9df qtwayland-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
cf38e0e28c7e5605942c4a77755349b0145804a397af37eb1fb4c77cb237f635 ffmpeg-$FFMPEG.tar.xz
@@ -60,7 +60,7 @@ cf38e0e28c7e5605942c4a77755349b0145804a397af37eb1fb4c77cb237f635 ffmpeg-$FFMPEG
6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e libjpeg-turbo-$LIBJPEGTURBO.tar.gz
28eb403f51f0f7405249132cecfe82ea5c0ef97f1b32c5a65828814ae0d34775 libpng-$LIBPNG.tar.xz
e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWEBP.tar.gz
f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7 $SDL.tar.gz
7322236cd12090c3eb40b9728be4d49c76f66ad17d04369584d4ecad5cf77c68 $SDL.tar.gz
eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
13da39edb3a40ed9713ae390ca89faa2f1202c9dda869ef306a8d4383e242bee nv-codec-headers-$NVENC.tar.gz
@@ -14,8 +14,8 @@
"sources": [
{
"type": "archive",
"url": "https://libsdl.org/release/SDL3-3.4.12.tar.gz",
"sha256": "f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7"
"url": "https://libsdl.org/release/SDL3-3.4.16.tar.gz",
"sha256": "7322236cd12090c3eb40b9728be4d49c76f66ad17d04369584d4ecad5cf77c68"
}
],
"cleanup": [
@@ -1,15 +1,15 @@
{
"app-id": "net.pcsx2.PCSX2",
"runtime": "org.kde.Platform",
"runtime-version": "6.10",
"runtime-version": "6.11",
"sdk": "org.kde.Sdk",
"sdk-extensions": [
"org.freedesktop.Sdk.Extension.llvm20"
"org.freedesktop.Sdk.Extension.llvm22"
],
"add-extensions": {
"org.freedesktop.Platform.ffmpeg-full": {
"directory": "lib/ffmpeg",
"version": "25.08",
"version": "26.08",
"add-ld-path": ".",
"autodownload": true
}
@@ -52,8 +52,8 @@
"-DCMAKE_PREFIX_PATH=\"${FLATPAK_DEST}\"",
"-DCMAKE_BUILD_TYPE=Release",
"-DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON",
"-DCMAKE_C_COMPILER=/usr/lib/sdk/llvm20/bin/clang",
"-DCMAKE_CXX_COMPILER=/usr/lib/sdk/llvm20/bin/clang++",
"-DCMAKE_C_COMPILER=/usr/lib/sdk/llvm22/bin/clang",
"-DCMAKE_CXX_COMPILER=/usr/lib/sdk/llvm22/bin/clang++",
"-DCMAKE_EXE_LINKER_FLAGS_INIT=-fuse-ld=lld",
"-DCMAKE_MODULE_LINKER_FLAGS_INIT=-fuse-ld=lld",
"-DCMAKE_SHARED_LINKER_FLAGS_INIT=-fuse-ld=lld",
@@ -0,0 +1,159 @@
From 4cf93f0f16b1503580cdb7ffdedb056321446677 Mon Sep 17 00:00:00 2001
From: squidbus <175574877+squidbus@users.noreply.github.com>
Date: Sat, 9 May 2026 16:53:22 -0700
Subject: [PATCH] Restore some checks for Mac1 GPUs.
---
MoltenVK/MoltenVK/GPUObjects/MVKDevice.h | 1 +
MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 34 +++++++++++--------
MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 2 +-
.../MoltenVK/GPUObjects/MVKPixelFormats.mm | 2 +-
4 files changed, 23 insertions(+), 16 deletions(-)
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
index ba3914de5..8923d23f0 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
@@ -112,6 +112,7 @@ typedef struct MVKMTLDeviceCapabilities {
bool supportsApple8;
bool supportsApple9;
bool supportsApple10;
+ bool supportsMac1;
bool supportsMac2;
bool supportsMetal3;
bool supportsMetal4;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index 2c930b004..2e212645a 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -110,7 +110,8 @@
#if MVK_XCODE_26
supportsApple10 = supportsGPUFam(Apple10, mtlDev);
#endif
- supportsMac2 = MVK_MACOS; // Incl Mac2 & MacCatalyst2
+ supportsMac1 = MVK_MACOS;
+ supportsMac2 = supportsGPUFam(Mac2, mtlDev) || supportsGPUFam(MacCatalyst2, mtlDev);
isAppleGPU = supportsApple1;
@@ -1547,7 +1548,7 @@
const auto placementHeapFlags = VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT |
VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT |
VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
- if (!getMVKConfig().useMTLHeap && mvkIsAnyFlagEnabled(flags, placementHeapFlags)) {
+ if (!_metalFeatures.placementHeaps && mvkIsAnyFlagEnabled(flags, placementHeapFlags)) {
return VK_ERROR_FORMAT_NOT_SUPPORTED;
}
@@ -2456,9 +2457,10 @@
// AMD support for MTLHeap is buggy.
auto cfgUseMTLHeap = getMVKConfig().useMTLHeap;
- _metalFeatures.placementHeaps = (_properties.vendorID == kAMDVendorId
- ? cfgUseMTLHeap == MVK_CONFIG_USE_MTLHEAP_ALWAYS
- : cfgUseMTLHeap != MVK_CONFIG_USE_MTLHEAP_NEVER);
+ auto allowMTLHeap = (_properties.vendorID == kAMDVendorId
+ ? cfgUseMTLHeap == MVK_CONFIG_USE_MTLHEAP_ALWAYS
+ : cfgUseMTLHeap != MVK_CONFIG_USE_MTLHEAP_NEVER);
+ _metalFeatures.placementHeaps = allowMTLHeap && (supportsMTLGPUFamily(Apple2) || supportsMTLGPUFamily(Mac2));
_metalFeatures.multisampleArrayTextures = !MVK_TVOS || mvkOSVersionIsAtLeast(16.0);
// Dynamic vertex stride needs to have everything aligned - compiled with support for vertex stride calls, and supported by both runtime OS and GPU.
@@ -2467,7 +2469,7 @@
_metalFeatures.renderLinearTextures = _gpuCapabilities.supportsRenderLinearTextures;
- if (supportsMTLGPUFamily(Mac2)) {
+ if (supportsMTLGPUFamily(Mac1)) {
_metalFeatures.mtlBufferAlignment = 256;
_metalFeatures.mtlConstantBufferAlignment = 32;
_metalFeatures.mtlCopyBufferAlignment = 4;
@@ -2489,15 +2491,18 @@
_metalFeatures.presentModeImmediate = true;
_metalFeatures.nonUniformThreadgroups = true;
_metalFeatures.native3DCompressedTextures = true;
- _metalFeatures.multisampleLayeredRendering = _metalFeatures.layeredRendering;
+ _metalFeatures.simdPermute = true;
+ _metalFeatures.memoryBarriers = true;
+ }
+
+ if (supportsMTLGPUFamily(Mac2)) {
+ _metalFeatures.multisampleLayeredRendering = true;
_metalFeatures.stencilFeedback = true;
_metalFeatures.depthResolve = true;
_metalFeatures.stencilResolve = true;
- _metalFeatures.simdPermute = true;
_metalFeatures.quadPermute = true;
_metalFeatures.simdReduction = true;
- _metalFeatures.memoryBarriers = true;
- }
+ }
if (supportsMTLGPUFamily(Apple1)) {
_metalFeatures.mtlBufferAlignment = 64;
@@ -2798,7 +2803,7 @@
_features.shaderResourceMinLod = true;
}
- if (supportsMTLGPUFamily(Mac2)) {
+ if (supportsMTLGPUFamily(Mac1)) {
_features.occlusionQueryPrecise = true;
_features.imageCubeArray = true;
_features.tessellationShader = true;
@@ -2970,19 +2975,19 @@
if (supportsMTLGPUFamily(Apple3)) {
_properties.limits.optimalBufferCopyOffsetAlignment = 16;
- } else if (supportsMTLGPUFamily(Mac2)) {
+ } else if (supportsMTLGPUFamily(Mac1)) {
_properties.limits.optimalBufferCopyOffsetAlignment = 256;
} else {
_properties.limits.optimalBufferCopyOffsetAlignment = 64;
}
- if (supportsMTLGPUFamily(Apple4) || supportsMTLGPUFamily(Mac2)) {
+ if (supportsMTLGPUFamily(Apple4) || supportsMTLGPUFamily(Mac1)) {
_properties.limits.maxFragmentInputComponents = 124;
} else {
_properties.limits.maxFragmentInputComponents = 60;
}
- if (supportsMTLGPUFamily(Apple5) || supportsMTLGPUFamily(Mac2)) {
+ if (supportsMTLGPUFamily(Apple5) || supportsMTLGPUFamily(Mac1)) {
_properties.limits.maxTessellationGenerationLevel = 64;
_properties.limits.maxTessellationPatchSize = 32;
} else if (supportsMTLGPUFamily(Apple3)) {
@@ -3653,6 +3658,7 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope
if (supportsMTLGPUFamily(Apple2)) { logMsg += "\n\t\tGPU Family Apple 2"; } else
if (supportsMTLGPUFamily(Apple1)) { logMsg += "\n\t\tGPU Family Apple 1"; }
+ if (supportsMTLGPUFamily(Mac1)) { logMsg += "\n\t\tGPU Family Mac 1"; }
if (supportsMTLGPUFamily(Mac2)) { logMsg += "\n\t\tGPU Family Mac 2"; }
logMsg += "\n\t\tRead-Write Texture Tier ";
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index d2fdd4020..696ec4467 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -1382,7 +1382,7 @@ static MTLRegion getMTLRegion(const ImgRgn& imgRgn) {
const auto placementHeapFlags = VK_IMAGE_CREATE_2D_VIEW_COMPATIBLE_BIT_EXT |
VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT |
VK_IMAGE_CREATE_BLOCK_TEXEL_VIEW_COMPATIBLE_BIT;
- if (!getMVKConfig().useMTLHeap && mvkIsAnyFlagEnabled(pCreateInfo->flags, placementHeapFlags)) {
+ if (!getMetalFeatures().placementHeaps && mvkIsAnyFlagEnabled(pCreateInfo->flags, placementHeapFlags)) {
setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : MTLHeap must be enabled to create 2D-on-3D or block texel view compatible images."));
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
index d16d6c8f6..11ca10a03 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
@@ -1343,7 +1343,7 @@
addMTLVertexFormatDesc( UChar4Normalized_BGRA );
- if (gpuCaps.supportsApple5 || gpuCaps.supportsMac2) {
+ if (gpuCaps.supportsApple5 || gpuCaps.supportsMac1) {
addMTLVertexFormatDesc( FloatRG11B10 );
addMTLVertexFormatDesc( FloatRGB9E5 );
}
@@ -43,11 +43,11 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
INSTALLDIR="$PWD/$INSTALLDIR"
fi
QT=6.11.1
QT=6.11.2
QTAPNG=1.3.0
FREETYPE=2.14.3
SDL=SDL3-3.4.12
SDL=SDL3-3.4.16
HARFBUZZ=14.2.0
ZSTD=1.5.7
LZ4=1.10.0
@@ -85,15 +85,15 @@ CMAKE_ARCH_ARM64=-DCMAKE_OSX_ARCHITECTURES="arm64"
CMAKE_ARCH_UNIVERSAL=-DCMAKE_OSX_ARCHITECTURES="x86_64;arm64"
grep . > SHASUMS <<EOF
d9594a31228aa23ad6b531719a29b45f0f3989fe6c136d45767ea179f233c1ac qtbase-everywhere-src-$QT.tar.xz
b2bf6c6845ac175ed7f819145483ba4676f617aaa6a5012c8efee63c8bbac413 qtimageformats-everywhere-src-$QT.tar.xz
7f3cf02f4824bf03c2c5859ea6db173bf1482a1daf24e6cdf7bc78cfa26a8a94 qtsvg-everywhere-src-$QT.tar.xz
8e61835a679c93fa9c6065b142353c2071ba68e297898937c32a03777fcaf50d qttools-everywhere-src-$QT.tar.xz
37c02c81206594c7bb4edca85ac93e8e55a9836b70c960fde6cb0f8623ec5677 qttranslations-everywhere-src-$QT.tar.xz
5b2e00eccaf5a4d8c14134ffa0ea8dfd0a35ae1ffc7f8d87fa4305a1ed23cf22 qtbase-everywhere-src-$QT.tar.xz
cecd8900f34b6550076309bc94f62f828008b633a4239e0a08c86788f41001f8 qtimageformats-everywhere-src-$QT.tar.xz
d594337feca84c26fb67fe87b85e6a5c12fda404b611d905f9d138210c311876 qtsvg-everywhere-src-$QT.tar.xz
9ea75af35c512f7e09e61c8c3af3997f13b4d43bb099cf43fcec470126b4041e qttools-everywhere-src-$QT.tar.xz
021684c1a7937a9fabc3b056a6698ad5978794caf9ac190fd6cc11399e67c014 qttranslations-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f freetype-$FREETYPE.tar.xz
f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7 $SDL.tar.gz
7322236cd12090c3eb40b9728be4d49c76f66ad17d04369584d4ecad5cf77c68 $SDL.tar.gz
c652d5d94971031654ab3989891a490a895d3e3f2b71171c62692b28e94b1b93 harfbuzz-$HARFBUZZ.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
@@ -289,6 +289,8 @@ echo "Installing MoltenVK..."
rm -fr "MoltenVK-${MOLTENVK}"
tar xf "MoltenVK-$MOLTENVK.tar.gz"
cd "MoltenVK-${MOLTENVK}"
patch -p1 < "$SCRIPTDIR/4cf93f0f16b1503580cdb7ffdedb056321446677.patch"
patch -p1 < "$SCRIPTDIR/mvk-texture-swizzle.patch"
./fetchDependencies --macos
make macos MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=0 MVK_CONFIG_USE_METAL_PRIVATE_API=1
cp Package/Latest/MoltenVK/dynamic/dylib/macOS/libMoltenVK.dylib "$INSTALLDIR/lib/"
@@ -20,11 +20,11 @@ if [ "${INSTALLDIR:0:1}" != "/" ]; then
INSTALLDIR="$PWD/$INSTALLDIR"
fi
QT=6.11.1
QT=6.11.2
QTAPNG=1.3.0
FREETYPE=2.14.3
SDL=SDL3-3.4.12
SDL=SDL3-3.4.16
HARFBUZZ=14.2.0
ZSTD=1.5.7
LZ4=1.10.0
@@ -61,15 +61,15 @@ CMAKE_COMMON=(
)
grep . > SHASUMS <<EOF
d9594a31228aa23ad6b531719a29b45f0f3989fe6c136d45767ea179f233c1ac qtbase-everywhere-src-$QT.tar.xz
b2bf6c6845ac175ed7f819145483ba4676f617aaa6a5012c8efee63c8bbac413 qtimageformats-everywhere-src-$QT.tar.xz
7f3cf02f4824bf03c2c5859ea6db173bf1482a1daf24e6cdf7bc78cfa26a8a94 qtsvg-everywhere-src-$QT.tar.xz
8e61835a679c93fa9c6065b142353c2071ba68e297898937c32a03777fcaf50d qttools-everywhere-src-$QT.tar.xz
37c02c81206594c7bb4edca85ac93e8e55a9836b70c960fde6cb0f8623ec5677 qttranslations-everywhere-src-$QT.tar.xz
5b2e00eccaf5a4d8c14134ffa0ea8dfd0a35ae1ffc7f8d87fa4305a1ed23cf22 qtbase-everywhere-src-$QT.tar.xz
cecd8900f34b6550076309bc94f62f828008b633a4239e0a08c86788f41001f8 qtimageformats-everywhere-src-$QT.tar.xz
d594337feca84c26fb67fe87b85e6a5c12fda404b611d905f9d138210c311876 qtsvg-everywhere-src-$QT.tar.xz
9ea75af35c512f7e09e61c8c3af3997f13b4d43bb099cf43fcec470126b4041e qttools-everywhere-src-$QT.tar.xz
021684c1a7937a9fabc3b056a6698ad5978794caf9ac190fd6cc11399e67c014 qttranslations-everywhere-src-$QT.tar.xz
f1d3be3489f758efe1a8f12118a212febbe611aa670af32e0159fa3c1feab2a6 QtApng-$QTAPNG.tar.gz
36bc4f1cc413335368ee656c42afca65c5a3987e8768cc28cf11ba775e785a5f freetype-$FREETYPE.tar.xz
f07b958a9ac5020fb7a44cadb957f658b2149c3c8abb4f63145fac9303249db7 $SDL.tar.gz
7322236cd12090c3eb40b9728be4d49c76f66ad17d04369584d4ecad5cf77c68 $SDL.tar.gz
c652d5d94971031654ab3989891a490a895d3e3f2b71171c62692b28e94b1b93 harfbuzz-$HARFBUZZ.tar.gz
eb33e51f49a15e023950cd7825ca74a4a2b43db8354825ac24fc1b7ee09e6fa3 zstd-$ZSTD.tar.gz
537512904744b35e232912055ccf8ec66d768639ff3abe5788d90d792ec5f48b lz4-$LZ4.tar.gz
@@ -78,7 +78,7 @@ e4ab7009bf0629fd11982d4c2aa83964cf244cffba7347ecd39019a9e38c4564 libwebp-$LIBWE
eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 libpng-$LIBPNG-apng.patch.gz
6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e libjpeg-turbo-$LIBJPEGTURBO.tar.gz
cf38e0e28c7e5605942c4a77755349b0145804a397af37eb1fb4c77cb237f635 ffmpeg-$FFMPEG.tar.xz
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c v$MOLTENVK.tar.gz
9985f141902a17de818e264d17c1ce334b748e499ee02fcb4703e4dc0038f89c MoltenVK-$MOLTENVK.tar.gz
5cd9495d9316cf6cc937bb328a7fd491c3248ef2469cfa42511f1039f6148aca KDDockWidgets-$KDDOCKWIDGETS.tar.gz
7bd4e79ce18b1d47517e7e91fbb7cf19d4f01942804a519bc7c0bf32b6325dd5 plutovg-$PLUTOVG.tar.gz
78561b571ac224030cdc450ca2986b4de915c2ba7616004a6d71a379bffd15f3 plutosvg-$PLUTOSVG.tar.gz
@@ -102,7 +102,7 @@ if ! shasum -sa 256 --check SHASUMS 2> /dev/null; then
-O "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/$LIBJPEGTURBO/libjpeg-turbo-$LIBJPEGTURBO.tar.gz" \
-O "https://storage.googleapis.com/downloads.webmproject.org/releases/webp/libwebp-$LIBWEBP.tar.gz" \
-O "https://ffmpeg.org/releases/ffmpeg-$FFMPEG.tar.xz" \
-O "https://github.com/KhronosGroup/MoltenVK/archive/refs/tags/v$MOLTENVK.tar.gz" \
-O "https://github.com/KhronosGroup/MoltenVK/archive/v$MOLTENVK/MoltenVK-$MOLTENVK.tar.gz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtbase-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtimageformats-everywhere-src-$QT.tar.xz" \
-O "https://download.qt.io/archive/qt/${QT%.*}/$QT/submodules/qtsvg-everywhere-src-$QT.tar.xz" \
@@ -228,8 +228,10 @@ cd ..
# MoltenVK already builds universal binaries, nothing special to do here.
echo "Installing MoltenVK..."
rm -fr "MoltenVK-${MOLTENVK}"
tar xf "v$MOLTENVK.tar.gz"
tar xf "MoltenVK-$MOLTENVK.tar.gz"
cd "MoltenVK-${MOLTENVK}"
patch -p1 < "$SCRIPTDIR/4cf93f0f16b1503580cdb7ffdedb056321446677.patch"
patch -p1 < "$SCRIPTDIR/mvk-texture-swizzle.patch"
sed -i '' 's/xcodebuild "$@"/xcodebuild $XCODEBUILD_EXTRA_ARGS "$@"/g' fetchDependencies
sed -i '' 's/XCODEBUILD :=/XCODEBUILD ?=/g' Makefile
XCODEBUILD_EXTRA_ARGS="VALID_ARCHS=x86_64" ./fetchDependencies --macos
@@ -0,0 +1,139 @@
From f6be31a110761ea494a938d62473abc085ea447b Mon Sep 17 00:00:00 2001
From: TellowKrinkle <tellowkrinkle@gmail.com>
Date: Mon, 31 Aug 2026 02:52:38 -0500
Subject: [PATCH] Re-add native texture swizzle checks
---
MoltenVK/MoltenVK/API/mvk_deprecated_api.h | 2 +-
MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 3 +-
MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 51 ++++++++++++++++++-
.../MoltenVK/GPUObjects/MVKPixelFormats.mm | 3 ++
4 files changed, 56 insertions(+), 3 deletions(-)
diff --git a/MoltenVK/MoltenVK/API/mvk_deprecated_api.h b/MoltenVK/MoltenVK/API/mvk_deprecated_api.h
index 74fef844..8d16f86c 100644
--- a/MoltenVK/MoltenVK/API/mvk_deprecated_api.h
+++ b/MoltenVK/MoltenVK/API/mvk_deprecated_api.h
@@ -118,7 +118,7 @@ typedef struct {
VkBool32 fences; /**< If true, Metal synchronization fences (MTLFence) are supported. Deprecated. Will always be true on all platforms. */
VkBool32 rasterOrderGroups; /**< If true, Raster order groups in fragment shaders are supported. */
VkBool32 native3DCompressedTextures; /**< If true, 3D compressed images are supported natively, without manual decompression. */
- VkBool32 nativeTextureSwizzle; /**< If true, component swizzle is supported natively, without manual swizzling in shaders. Deprecated. Will always be true on all platforms. */
+ VkBool32 nativeTextureSwizzle; /**< If true, component swizzle is supported natively, without manual swizzling in shaders. */
VkBool32 placementHeaps; /**< If true, MTLHeap objects support placement of resources. */
VkDeviceSize pushConstantSizeAlignment; /**< The alignment used internally when allocating memory for push constants. Must be PoT. */
uint32_t maxTextureLayers; /**< The maximum number of layers in an array texture. */
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index aaf5945b..c7da8256 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -2496,6 +2496,7 @@
_metalFeatures.stencilResolve = true;
_metalFeatures.quadPermute = true;
_metalFeatures.simdReduction = true;
+ _metalFeatures.nativeTextureSwizzle = true;
}
if (supportsMTLGPUFamily(Apple1)) {
@@ -2504,6 +2505,7 @@
_metalFeatures.maxPerStageTextureCount = 31;
_metalFeatures.maxTextureDimension = (8 * KIBI);
_metalFeatures.maxQueryBufferSize = (64 * KIBI);
+ _metalFeatures.nativeTextureSwizzle = true;
_metalFeatures.maxPerStageDynamicMTLBufferCount = _metalFeatures.maxPerStageBufferCount;
_metalFeatures.renderLinearTextures = true;
@@ -2727,7 +2729,6 @@
_metalFeatures.events = true;
_metalFeatures.ioSurfaces = true;
_metalFeatures.renderWithoutAttachments = true;
- _metalFeatures.nativeTextureSwizzle = true;
}
bool MVKPhysicalDevice::isTier2MetalArgumentBuffers() {
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 8eda5515..392a4f98 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -1925,7 +1925,7 @@ static void signalAndUntrack(const MVKSwapchainSignaler& signaler) {
}
id<MTLTexture> texView = nil;
- if (_useSwizzle) {
+ if (_useSwizzle && getMetalFeatures().nativeTextureSwizzle) {
texView = [mtlTex newTextureViewWithPixelFormat: _mtlPixFmt
textureType: _imageView->_mtlTextureType
levels: levelRange
@@ -2103,6 +2103,55 @@ static void signalAndUntrack(const MVKSwapchainSignaler& signaler) {
}
}
+#define SWIZZLE_MATCHES(R, G, B, A) mvkVkComponentMappingsMatch(_componentSwizzle, {VK_COMPONENT_SWIZZLE_ ##R, VK_COMPONENT_SWIZZLE_ ##G, VK_COMPONENT_SWIZZLE_ ##B, VK_COMPONENT_SWIZZLE_ ##A} )
+#define VK_COMPONENT_SWIZZLE_ANY VK_COMPONENT_SWIZZLE_MAX_ENUM
+
+ if (_imageView->_image->hasPixelFormatView(_planeIndex)) {
+ switch (_mtlPixFmt) {
+ case MTLPixelFormatR8Unorm:
+ if (SWIZZLE_MATCHES(ZERO, ANY, ANY, R)) {
+ _mtlPixFmt = MTLPixelFormatA8Unorm;
+ return VK_SUCCESS;
+ }
+ break;
+
+ case MTLPixelFormatA8Unorm:
+ if (SWIZZLE_MATCHES(A, ANY, ANY, ZERO)) {
+ _mtlPixFmt = MTLPixelFormatR8Unorm;
+ return VK_SUCCESS;
+ }
+ break;
+
+ case MTLPixelFormatRGBA8Unorm:
+ if (SWIZZLE_MATCHES(B, G, R, A)) {
+ _mtlPixFmt = MTLPixelFormatBGRA8Unorm;
+ return VK_SUCCESS;
+ }
+ break;
+
+ case MTLPixelFormatRGBA8Unorm_sRGB:
+ if (SWIZZLE_MATCHES(B, G, R, A)) {
+ _mtlPixFmt = MTLPixelFormatBGRA8Unorm_sRGB;
+ return VK_SUCCESS;
+ }
+ break;
+
+ case MTLPixelFormatBGRA8Unorm:
+ if (SWIZZLE_MATCHES(B, G, R, A)) {
+ _mtlPixFmt = MTLPixelFormatRGBA8Unorm;
+ return VK_SUCCESS;
+ }
+ break;
+
+ case MTLPixelFormatBGRA8Unorm_sRGB:
+ if (SWIZZLE_MATCHES(B, G, R, A)) {
+ _mtlPixFmt = MTLPixelFormatRGBA8Unorm_sRGB;
+ return VK_SUCCESS;
+ }
+ break;
+ }
+ }
+
_useSwizzle = !mvkVkComponentMappingsMatch(_componentSwizzle, {VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A});
return VK_SUCCESS;
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
index 316d7c6f..31a2c6a1 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPixelFormats.mm
@@ -654,6 +654,9 @@
bool pfv = false;
+ // Swizzle emulation may need to reinterpret
+ needsReinterpretation |= !_physicalDevice->getMetalFeatures()->nativeTextureSwizzle;
+
pfv |= isColorFormat && needsReinterpretation &&
mvkIsAnyFlagEnabled(vkImageUsageFlags, (VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_STORAGE_BIT |
--
2.39.5 (Apple Git-154)
@@ -54,13 +54,13 @@ echo INSTALLDIR=%INSTALLDIR%
cd "%BUILDDIR%"
set QT=6.11.1
set QT=6.11.2
set QTMINOR=6.11
set QTAPNG=1.3.0
set FREETYPE=2.14.3
set HARFBUZZ=14.2.0
set SDL=SDL3-3.4.12
set SDL=SDL3-3.4.16
set LIBJPEGTURBO=3.2.0
set LIBPNG=1658
set LIBPNGLONG=1.6.58
@@ -81,11 +81,11 @@ set SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73
set AGILITYSDK=1.619.2
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 3529cc37297a5a7aae4486843b9fd41c30df1d79a770f85e240b537dcc327ca5 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 37fba768f2780580dfae535ad6654cb9dc0bf2272e71b9b9781988de9ed0dac0 || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 767730188d4610a89bf8da502f87acf1c8881a3ac54f1e0eb167ab1e08b03a75 || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 2d6ed2a98f458152e3cb17bf0be0494250194933a2d937b5a434e5b2006efca9 || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" eef43700ffd079f5893e435aca1330c8bdbf2a94ae45013e3fc63870df53d3b0 || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 8f8c16703a8170b235361aacdf0ec97d2445ae4e3e3d127eb1576f498269ef79 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" a303149d7b9f087d788135e9733fdac8e4cec694e5afc04bf33e10a516b33282 || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" e07133da0145d8ca87da5567a97c8fc2efd19a41c681d01bfec2ebac772f679c || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" bc80932ac2da0df129583eae62fa8a3d4b0d43ad9d1676fac9c1922e5958cd81 || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 850bc1b316149086512c17a77da51fec94933846fa84944508feb6dd9cbb35aa || goto error
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 e61b31ab26358b946e767ed7eb7f4bb2e507da1cfefeb7a8861ace7fd5c899a1 || goto error
@@ -94,7 +94,7 @@ call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lp
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e || 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" 3d4de8967a49c0451e775a0c1e9022092c19fdef41ba38a83fcf031c5a6496e2 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 5f399fdfbc040169ef4418a3cb99ccc5a0641681f7ccc1da66eeec3c97fa4076 || 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" e8bf55f3017aa181690990cb58a994e77885da140609fc8f94abe9b65d2cae28 || goto error
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
@@ -35,12 +35,6 @@ if defined DEBUG (
set DEBUG=1
)
if defined BUILD_FFMPEG (
echo BUILD_FFMPEG=%BUILD_FFMPEG%
) else (
set BUILD_FFMPEG=0
)
pushd %~dp0
set "SCRIPTDIR=%CD%"
cd ..\..\..\..
@@ -61,11 +55,12 @@ set "PATH=%PATH%;%INSTALLDIR%\bin"
cd "%BUILDDIR%"
set QT=6.11.1
set QT=6.11.2
set QTMINOR=6.11
set QTAPNG=1.3.0
set FFMPEG=9.0.1
set MAKE=4.4.1
set MESON=1.10.2
set PKGCONF=2.5.1
set AMF=1.5.2
@@ -77,7 +72,7 @@ set LIBX264=b35605ace3ddf7c1a5d67a2eb553f034aef41d55
set FREETYPE=2.14.3
set HARFBUZZ=14.2.0
set SDL=SDL3-3.4.12
set SDL=SDL3-3.4.16
set LIBJPEGTURBO=3.2.0
set LIBPNG=1658
set LIBPNGLONG=1.6.58
@@ -99,14 +94,15 @@ set SHADERC_SPIRVTOOLS=6337eb62cadd7d124ac6789bf39c0f71148f0a73
set AGILITYSDK=1.619.2
set DXHEADERS=1.619.1
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 3529cc37297a5a7aae4486843b9fd41c30df1d79a770f85e240b537dcc327ca5 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" 37fba768f2780580dfae535ad6654cb9dc0bf2272e71b9b9781988de9ed0dac0 || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" 767730188d4610a89bf8da502f87acf1c8881a3ac54f1e0eb167ab1e08b03a75 || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" 2d6ed2a98f458152e3cb17bf0be0494250194933a2d937b5a434e5b2006efca9 || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" eef43700ffd079f5893e435aca1330c8bdbf2a94ae45013e3fc63870df53d3b0 || goto error
call :downloadfile "qtbase-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtbase-everywhere-src-%QT%.zip" 8f8c16703a8170b235361aacdf0ec97d2445ae4e3e3d127eb1576f498269ef79 || goto error
call :downloadfile "qtimageformats-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtimageformats-everywhere-src-%QT%.zip" a303149d7b9f087d788135e9733fdac8e4cec694e5afc04bf33e10a516b33282 || goto error
call :downloadfile "qtsvg-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qtsvg-everywhere-src-%QT%.zip" e07133da0145d8ca87da5567a97c8fc2efd19a41c681d01bfec2ebac772f679c || goto error
call :downloadfile "qttools-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttools-everywhere-src-%QT%.zip" bc80932ac2da0df129583eae62fa8a3d4b0d43ad9d1676fac9c1922e5958cd81 || goto error
call :downloadfile "qttranslations-everywhere-src-%QT%.zip" "https://download.qt.io/official_releases/qt/%QTMINOR%/%QT%/submodules/qttranslations-everywhere-src-%QT%.zip" 850bc1b316149086512c17a77da51fec94933846fa84944508feb6dd9cbb35aa || goto error
call :downloadfile "QtApng-%QTAPNG%.zip" "https://github.com/jurplel/QtApng/archive/refs/tags/%QTAPNG%.zip" 5176082cdd468047a7eb1ec1f106b032f57df207aa318d559b29606b00d159ac || goto error
call :downloadfile "ffmpeg-%FFMPEG%.tar.xz" "https://ffmpeg.org/releases/ffmpeg-%FFMPEG%.tar.xz" cf38e0e28c7e5605942c4a77755349b0145804a397af37eb1fb4c77cb237f635 || goto error
call :downloadfile "make-%MAKE%-without-guile-w32-bin.zip" "https://sourceforge.net/projects/ezwinports/files/make-%MAKE%-without-guile-w32-bin.zip/download" fb66a02b530f7466f6222ce53c0b602c5288e601547a034e4156a512dd895ee7 || goto error
call :downloadfile "meson-%MESON%.tar.gz" "https://github.com/mesonbuild/meson/releases/download/%MESON%/meson-%MESON%.tar.gz" 7890287d911dd4ee1ebd0efb61ed0321bfcd87c725df923a837cf90c6508f96b || goto error
call :downloadfile "pkgconf-pkgconf-%PKGCONF%.zip" "https://github.com/pkgconf/pkgconf/archive/refs/tags/pkgconf-%PKGCONF%.zip" c5b5f88a2ca2324dc5d857e35bb145e24290e326357ea94a86d47b8d7fa15477 || goto error
call :downloadfile "amf-headers-v%AMF%.tar.gz" "https://github.com/GPUOpen-LibrariesAndSDKs/AMF/releases/download/v%AMF%/AMF-headers-v%AMF%.tar.gz" d3c12eb324edf05e214608b6a395a51dd95770ed9d45520185d6c3a206811c99 || goto error
@@ -122,7 +118,7 @@ call :downloadfile "lpng%LIBPNG%.zip" https://download.sourceforge.net/libpng/lp
call :downloadfile "lpng%LIBPNG%-apng.patch.gz" https://download.sourceforge.net/libpng-apng/libpng-%LIBPNGLONG%-apng.patch.gz eee7dea22ed502868017971c86c63c4ed1e6085de0baebfdcc3d3322f00f3eb0 || goto error
call :downloadfile "libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" "https://github.com/libjpeg-turbo/libjpeg-turbo/releases/download/%LIBJPEGTURBO%/libjpeg-turbo-%LIBJPEGTURBO%.tar.gz" 6f30092cef9fb839779646608f4ee14ae3cbac989c47fa05e841b0841f09878e || 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" 3d4de8967a49c0451e775a0c1e9022092c19fdef41ba38a83fcf031c5a6496e2 || goto error
call :downloadfile "%SDL%.zip" "https://libsdl.org/release/%SDL%.zip" 5f399fdfbc040169ef4418a3cb99ccc5a0641681f7ccc1da66eeec3c97fa4076 || 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" e8bf55f3017aa181690990cb58a994e77885da140609fc8f94abe9b65d2cae28 || goto error
call :downloadfile "zstd-%ZSTD%.zip" "https://github.com/facebook/zstd/archive/refs/tags/v%ZSTD%.zip" 7897bc5d620580d9b7cd3539c44b59d78f3657d33663fe97a145e07b4ebd69a4 || goto error
@@ -146,139 +142,142 @@ if %DEBUG%==1 (
set FORCEPDB=-DCMAKE_SHARED_LINKER_FLAGS_RELEASE="/DEBUG" -DCMAKE_MODULE_LINKER_FLAGS_RELEASE="/DEBUG" -DCMAKE_SHARED_LINKER_FLAGS_MINSIZEREL="/DEBUG" -DCMAKE_MODULE_LINKER_FLAGS_MINSIZEREL="/DEBUG"
if %BUILD_FFMPEG%==1 (
if not "%INSTALLDIR%"=="%INSTALLDIR: =%" (
echo FFmpeg does not support building in paths with spaces.
goto error
)
where nasm /q
set FOUND_NASM=0
if !ERRORLEVEL!==0 (
set FOUND_NASM=1
)
echo "Installing AMF headers"
rmdir /S /Q "amf-headers-v%AMF%"
tar -xf "amf-headers-v%AMF%.tar.gz" || goto error
xcopy "%BUILDDIR%\amf-headers-v%AMF%\AMF" "%INSTALLDIR%\include\AMF\" /y /s || goto error
echo.
echo "Installing libvpl"
rmdir /S /Q "libvpl-%LIBVPL%"
%SEVENZIP% x "libvpl-%LIBVPL%.zip" || goto error
cd "libvpl-%LIBVPL%" || goto error
cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=OFF -DINSTALL_EXAMPLES=OFF -DINSTALL_LIB=OFF -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -B build -G Ninja || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error
echo "Installing libopus"
rmdir /S /Q "opus-%LIBOPUS%"
tar -xf "opus-%LIBOPUS%.tar.gz" || goto error
cd "opus-%LIBOPUS%" || goto error
cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=OFF -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -B build -G Ninja || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error
echo "Installing libsvtav1"
rmdir /S /Q "SVT-AV1-v%LIBSVTAV1%"
tar -xf "SVT-AV1-v%LIBSVTAV1%.zip" || goto error
cd "SVT-AV1-v%LIBSVTAV1%" || goto error
if !FOUND_NASM!==0 (
set LIBSTVAV1_NASM=-DCOMPILE_C_ONLY=ON
)
cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=OFF -DBUILD_APPS=OFF -DSVT_AV1_LTO=ON !LIBSTVAV1_NASM! -B build -G Ninja || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error
echo "Extracting meson"
rmdir /S /Q "meson-%MESON%"
tar xf "meson-%MESON%.tar.gz" || goto error
set MASON_PY=python "%BUILDDIR%\meson-%MESON%\meson.py"
!MASON_PY! -v || goto error
echo.
rem Alternatively we could grab pkg-config-lite from chocolatey or WinGet.
echo "Installing pkgconf"
rmdir /S /Q "pkgconf-pkgconf-%PKGCONF%"
%SEVENZIP% x "pkgconf-pkgconf-%PKGCONF%.zip" || goto error
cd "pkgconf-pkgconf-%PKGCONF%" || goto error
!MASON_PY! setup --buildtype=release --prefix="%INSTALLDIR%" -Dtests=disabled build --backend=ninja || goto error
!MASON_PY! compile -C build || goto error
ninja -C build install || goto error
set PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1
set PKG_CONFIG_ALLOW_SYSTEM_LIBS=1
Set "PKG_CONFIG_PATH=%INSTALLDIR%\lib\pkgconfig"
cd .. || goto error
set "OLD_PATH=%PATH%"
set "PATH=%PATH%;%UNIX_TOOLS%"
echo "Installing nvenc headers..."
rmdir /S /Q "nv-codec-headers-%NVENC%"
tar xf "nv-codec-headers-%NVENC%.tar.gz" || goto error
make -C "nv-codec-headers-%NVENC%" PREFIX="%INSTALLDIR%" install || goto error
echo.
set CC=cl
set CXX=cl
echo "Installing libx264"
rmdir /S /Q "x264-%LIBX264%"
%SEVENZIP% x "x264-%LIBX264%.zip" || goto error
cd "x264-%LIBX264%" || goto error
if !FOUND_NASM!==0 (
set LIBX264_NASM=--disable-asm
)
%BASH% configure --prefix="%INSTALLDIR%" --disable-cli --enable-static --extra-cflags="-MD -w -Os -GL" !LIBX264_NASM! || goto error
make -j%NUMBER_OF_PROCESSORS% || goto error
make install || goto error
cd .. || goto error
echo.
echo "Installing FFmpeg..."
rmdir /S /Q "ffmpeg-%FFMPEG%"
tar xf "ffmpeg-%FFMPEG%.tar.xz" || goto error
cd "ffmpeg-%FFMPEG%"
%PATCH% -p1 < "%SCRIPTDIR%\ffmpeg-configure-escape.patch" || goto error
if not !FOUND_NASM!==1 (
rem MSVC LTO gives linker errors when building without nasm.
rem The following patches fixes that issue.
%PATCH% -p1 < "%SCRIPTDIR%\ffmpeg-no-nasm-fix-avc-air.patch" || goto error
%PATCH% -p1 < "%SCRIPTDIR%\ffmpeg-no-nasm-fix-swc-air.patch" || goto error
set FFMPEG_NASM=--disable-x86asm
)
rem FFmpeg's build seems to choke when extra-cflags contain `\`, so use `/` as the path separator.
set VULKAN_INCLUDE=%INSTALLDIR:\=/%/../3rdparty/vulkan/include
rem libvpl needs to have advapi32.lib & ole32.lib added as extra libs.
rem For some reason QSV requires the hevc parser on windows.
rem --enable-small removes the display names of codecs, so instead we specify optflag for minsize
%BASH% configure --prefix="%INSTALLDIR%" --disable-all --disable-autodetect --disable-static --enable-shared --disable-debug ^
--toolchain=msvc --extra-ldflags="-LTCG" --extra-libs="advapi32.lib ole32.lib" !FFMPEG_NASM! --pkg-config="%INSTALLDIR%\bin\pkgconf.exe" ^
--extra-cflags="-MD -GL -I!VULKAN_INCLUDE!" --extra-cxxflags="-MD -GL -I!VULKAN_INCLUDE!" --optflags="-O1" ^
--enable-avcodec --enable-avformat --enable-avutil --enable-swresample --enable-swscale ^
--enable-gpl --enable-libx264 --enable-libsvtav1 --enable-libopus --enable-vulkan --enable-ffnvcodec --enable-nvenc --enable-libvpl --enable-amf ^
--enable-d3d11va --enable-mediafoundation ^
--enable-encoder=ffv1,qtrle,libx264*,libsvtav1,aac,flac,libopus,pcm_s16be,pcm_s16le ^
--enable-encoder=h264_qsv,hevc_qsv,av1_qsv ^
--enable-encoder=h264_nvenc,hevc_nvenc,av1_nvenc ^
--enable-encoder=h264_amf,hevc_amf,av1_amf ^
--enable-encoder=h264_vulkan,hevc_vulkan,av1_vulkan ^
--enable-encoder=h264_mf,hevc_mf,av1_mf ^
--enable-parser=hevc ^
--enable-muxer=avi,matroska,mov,mp3,mp4,wav ^
--enable-protocol=file || goto error
make -j%NUMBER_OF_PROCESSORS% || goto error
make install || goto error
cd ..
echo.
set "PATH=!OLD_PATH!"
if not "%INSTALLDIR%"=="%INSTALLDIR: =%" (
echo FFmpeg does not support building in paths with spaces.
goto error
)
where nasm /q
set FOUND_NASM=0
if !ERRORLEVEL!==0 (
set FOUND_NASM=1
)
echo "Installing AMF headers"
rmdir /S /Q "amf-headers-v%AMF%"
tar -xf "amf-headers-v%AMF%.tar.gz" || goto error
xcopy "%BUILDDIR%\amf-headers-v%AMF%\AMF" "%INSTALLDIR%\include\AMF\" /y /s || goto error
echo.
echo "Installing libvpl"
rmdir /S /Q "libvpl-%LIBVPL%"
%SEVENZIP% x "libvpl-%LIBVPL%.zip" || goto error
cd "libvpl-%LIBVPL%" || goto error
cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=OFF -DINSTALL_EXAMPLES=OFF -DINSTALL_LIB=OFF -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -B build -G Ninja || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error
echo "Installing libopus"
rmdir /S /Q "opus-%LIBOPUS%"
tar -xf "opus-%LIBOPUS%.tar.gz" || goto error
cd "opus-%LIBOPUS%" || goto error
cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=OFF -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -B build -G Ninja || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error
echo "Installing libsvtav1"
rmdir /S /Q "SVT-AV1-v%LIBSVTAV1%"
tar -xf "SVT-AV1-v%LIBSVTAV1%.zip" || goto error
cd "SVT-AV1-v%LIBSVTAV1%" || goto error
if !FOUND_NASM!==0 (
set LIBSTVAV1_NASM=-DCOMPILE_C_ONLY=ON
)
cmake -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_PREFIX_PATH="%INSTALLDIR%" -DCMAKE_INSTALL_PREFIX="%INSTALLDIR%" -DBUILD_SHARED_LIBS=OFF -DBUILD_TESTING=OFF -DBUILD_APPS=OFF -DSVT_AV1_LTO=ON !LIBSTVAV1_NASM! -B build -G Ninja || goto error
cmake --build build --parallel || goto error
ninja -C build install || goto error
cd .. || goto error
echo "Extracting meson"
rmdir /S /Q "meson-%MESON%"
tar xf "meson-%MESON%.tar.gz" || goto error
set MASON_PY=python "%BUILDDIR%\meson-%MESON%\meson.py"
!MASON_PY! -v || goto error
echo.
rem Alternatively we could grab pkg-config-lite from chocolatey or WinGet.
echo "Installing pkgconf"
rmdir /S /Q "pkgconf-pkgconf-%PKGCONF%"
%SEVENZIP% x "pkgconf-pkgconf-%PKGCONF%.zip" || goto error
cd "pkgconf-pkgconf-%PKGCONF%" || goto error
!MASON_PY! setup --buildtype=release --prefix="%INSTALLDIR%" -Dtests=disabled build --backend=ninja || goto error
!MASON_PY! compile -C build || goto error
ninja -C build install || goto error
set PKG_CONFIG_ALLOW_SYSTEM_CFLAGS=1
set PKG_CONFIG_ALLOW_SYSTEM_LIBS=1
Set "PKG_CONFIG_PATH=%INSTALLDIR%\lib\pkgconfig"
cd .. || goto error
echo "Extracting make"
%SEVENZIP% e "make-%MAKE%-without-guile-w32-bin.zip" "bin\make.exe" -o"%INSTALLDIR%\bin\" -aoa || goto error
set MAKE_EXE="%INSTALLDIR%\bin\make.exe"
echo.
set "OLD_PATH=%PATH%"
set "PATH=%PATH%;%UNIX_TOOLS%"
echo "Installing nvenc headers..."
rmdir /S /Q "nv-codec-headers-%NVENC%"
tar xf "nv-codec-headers-%NVENC%.tar.gz" || goto error
!MAKE_EXE! -C "nv-codec-headers-%NVENC%" PREFIX="%INSTALLDIR%" install || goto error
echo.
set CC=cl
set CXX=cl
echo "Installing libx264"
rmdir /S /Q "x264-%LIBX264%"
%SEVENZIP% x "x264-%LIBX264%.zip" || goto error
cd "x264-%LIBX264%" || goto error
if !FOUND_NASM!==0 (
set LIBX264_NASM=--disable-asm
)
%BASH% configure --prefix="%INSTALLDIR%" --disable-cli --enable-static --extra-cflags="-MD -w -Os -GL" !LIBX264_NASM! || goto error
!MAKE_EXE! -j%NUMBER_OF_PROCESSORS% || goto error
!MAKE_EXE! install || goto error
cd .. || goto error
echo.
echo "Installing FFmpeg..."
rmdir /S /Q "ffmpeg-%FFMPEG%"
tar xf "ffmpeg-%FFMPEG%.tar.xz" || goto error
cd "ffmpeg-%FFMPEG%"
%PATCH% -p1 < "%SCRIPTDIR%\ffmpeg-configure-escape.patch" || goto error
if not !FOUND_NASM!==1 (
rem MSVC LTO gives linker errors when building without nasm.
rem The following patches fixes that issue.
%PATCH% -p1 < "%SCRIPTDIR%\ffmpeg-no-nasm-fix-avc-air.patch" || goto error
%PATCH% -p1 < "%SCRIPTDIR%\ffmpeg-no-nasm-fix-swc-air.patch" || goto error
set FFMPEG_NASM=--disable-x86asm
)
rem FFmpeg's build seems to choke when extra-cflags contain `\`, so use `/` as the path separator.
set VULKAN_INCLUDE=%INSTALLDIR:\=/%/../3rdparty/vulkan/include
rem libvpl needs to have advapi32.lib & ole32.lib added as extra libs.
rem For some reason QSV requires the hevc parser on windows.
rem --enable-small removes the display names of codecs, so instead we specify optflag for minsize
%BASH% configure --prefix="%INSTALLDIR%" --disable-all --disable-autodetect --disable-static --enable-shared --disable-debug ^
--toolchain=msvc --extra-ldflags="-LTCG" --extra-libs="advapi32.lib ole32.lib" !FFMPEG_NASM! --pkg-config="%INSTALLDIR%\bin\pkgconf.exe" ^
--extra-cflags="-MD -GL -I!VULKAN_INCLUDE!" --extra-cxxflags="-MD -GL -I!VULKAN_INCLUDE!" --optflags="-O1" ^
--enable-avcodec --enable-avformat --enable-avutil --enable-swresample --enable-swscale ^
--enable-gpl --enable-libx264 --enable-libsvtav1 --enable-libopus --enable-vulkan --enable-ffnvcodec --enable-nvenc --enable-libvpl --enable-amf ^
--enable-d3d11va --enable-mediafoundation ^
--enable-encoder=ffv1,qtrle,libx264*,libsvtav1,aac,flac,libopus,pcm_s16be,pcm_s16le ^
--enable-encoder=h264_qsv,hevc_qsv,av1_qsv ^
--enable-encoder=h264_nvenc,hevc_nvenc,av1_nvenc ^
--enable-encoder=h264_amf,hevc_amf,av1_amf ^
--enable-encoder=h264_vulkan,hevc_vulkan,av1_vulkan ^
--enable-encoder=h264_mf,hevc_mf,av1_mf ^
--enable-parser=hevc ^
--enable-muxer=avi,matroska,mov,mp3,mp4,wav ^
--enable-protocol=file || goto error
!MAKE_EXE! -j%NUMBER_OF_PROCESSORS% || goto error
!MAKE_EXE! install || goto error
cd ..
echo.
set "PATH=!OLD_PATH!"
echo Building Zlib...
rmdir /S /Q "zlib-%ZLIB%"
%SEVENZIP% x "zlib%ZLIBSHORT%.zip" || goto error
+1 -1
View File
@@ -145,7 +145,7 @@ jobs:
cmake --build build --config Release || exit /b
cmake --install build --config Release || exit /b
) else (
msbuild "PCSX2_qt.sln" /m /v:m /p:Configuration="${{ inputs.configuration }}" /p:Platform="${{ inputs.platform }}" || exit /b
msbuild "PCSX2_qt.slnx" /m /v:m /p:Configuration="${{ inputs.configuration }}" /p:Platform="${{ inputs.platform }}" || exit /b
)
REM We can use Segoe UI Emoji so we don't need to bundle this
del bin\resources\fonts\Twemoji*
-1
View File
@@ -37,5 +37,4 @@ jobs:
if: steps.cache-deps.outputs.cache-hit != 'true'
env:
DEBUG: 0
BUILD_FFMPEG: 1
run: .github/workflows/scripts/windows/build-dependencies.bat
+244 -3
View File
@@ -39,6 +39,230 @@ HOW TO UPDATE?
and API updates have been a little more frequent lately. They are documented below and in imgui.cpp and should not affect all users.
- Please report any issue!
-----------------------------------------------------------------------
VERSION 1.92.9b (Released 2026-07-31)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.9b
Changes:
- DragXXX, SliderXXX: fixed a regression in 1.92.9 where clicking a previously
Ctrl+Clicked field would flick it to text edit mode for a frame. (#9476, #701)
- Tables:
- Fixed Y2 position of lower horizontal border (ImGuiTableFlags_BordersOuterH)
being off by one pixel when vertical ones are not also enabled. [@thedmd]
- Fixed X position of angled borders being off by half a pixel. [@thedmd]
- ImDrawData: fixed a regression in 1.92.9 where legacy `ImDrawData::CmdListsCount` was always 0.
Prefer using `ImDrawData::CmdList.Size` anyway.
-----------------------------------------------------------------------
VERSION 1.92.9 (Released 2026-07-25)
-----------------------------------------------------------------------
Decorated log and release notes: https://github.com/ocornut/imgui/releases/tag/v1.92.9
Breaking Changes:
- DragXXX, SliderXXX, InputScalar: with `ImGuiItemFlags_LiveEditOnInputScalar` now
defaulting to being disabled: inputting a value with the keyboard doesn't write
intermediate values to the backing variable. (#9476)
Before: DragFloat() with user typing "123" --> write back 1, then 12, then 123.
After: DragFloat() with user typing "123" --> write back 123 when validated/unfocused.
You can enable the flag back for a given scope if needed by specific widget/behavior.
Read below for details.
- TreeNode: commented out legacy name `ImGuiTreeNodeFlags_SpanTextWidth` which
was obsoleted in 1.90.7 (May 2024). Use `ImGuiTreeNodeFlags_SpanLabelWidth`.
- ColorEdit: obsoleted SetColorEditOptions() function added in 1.51 (June 2017) in favor
of directly poking to io.ConfigColorEditFlags. More consistent and easier to discover.
- Drag and Drop: commented out legacy name `ImGuiDragDropFlags_SourceAutoExpirePayload`
which obsoleted in 1.90.9 (July 2024). Use `ImGuiDragDropFlags_PayloadAutoExpire`.
- ImDrawData: marked `CmdListsCount` as obsolete (technically was obsoleted in 1.89.8).
Before: `draw_data->CmdListsCount`, After: `draw_data->CmdLists.Size`.
Other Changes:
- LiveEdit on/off: added `ImGuiItemFlags_LiveEditOnInputText` and `ImGuiItemFlags_LiveEditOnInputScalar`
flags to configure the timing of applying edits of backing variables when typing
values using a keyboard.
(#9476, #701, #3936, #3946, #5904, #6284, #8149, #8065, #8665, #9117, #9299, #700, #1351,
#1875, #2060, #2215, #2380, #2550, #3083, #3338, #3556, #4373, #4714, #4885, #5184,
#5777, #6707, #6766, #8004, #8303, #8915, #9308)
- ImGuiItemFlags_LiveEditOnInputText is enabled by default (same as before):
- The expectation is that for strings/text, enabling LiveEdit is a better default.
- ImGuiItemFlags_LiveEditOnInputScalar is disabled by default (new behavior):
- The expectation is that for numeric/scalars values, disabling LiveEdit is a better default.
- Until now:
- Edits where always applied immediately to backing variable, which is equivalent
to the `ImGuiItemFlags_LiveEditXXX` flags being enabled.
- Typing '123' in an integer field would output successively 1, 12 then 123.
- Most uses of `IsItemDeactivatedAfterEdit()` or `ImGuiInputTextFlags_EnterReturnsTrue`
were actually workarounds for this issue. Advanced applications would typically
use `IsItemDeactivatedAfterEdit()` to distinguish transactions.
Workarounds often required a backing store for scalar values, and there were
also a few niggles related to `IsItemDeactivatedAfterEdit()` when using +/-
buttons of an `InputInt()` widgets.
- Many of those situations can now be naturally simplified when disabling
`ImGuiItemFlags_LiveEditOnInputScalar` is disabled.
- The new flags allows disabling this behavior selectively for strings fields
such as `InputText()` vs scalar fields: `SliderInt()`, `InputFloat()`, etc.
- When LiveEdit is disabled, edits are applied when pressing enter, tabbing out,
clearing a field or deactivating due to a focus loss.
- The flag may be altered programmatically, e.g. for the entire frame scope:
NewFrame();
PushItemFlag(ImGuiItemFlags_LiveEditOnInputScalar, true); // Enable for scalars for the whole frame
....
PopItemFlag();
EndFrame();
Or for a specific widget:
PushItemFlag(ImGuiItemFlags_LiveEditOnInput, true); // Enable for one widget
SliderInt(...);
PopItemFlag();
- We intentionally are not adding `io.ConfigLiveEditXXX` fields to dictate the
default value of each `ImGuiItemFlags_LiveEditXXX`, because this is not expected
to be a user preference but a programmer/widget preferences.
And we strive to make the toolkit consistent.
- Windows:
- Clicking on a window's empty-space to move/focus a window checks
for lack of mouse button ownership. This gives an additional opportunity
for user code to bypass it without using a clickable item. (#9382)
- Clicking on a window's empty-space to move/focus a window checks
for lack of queued focus request. (#9382)
- Fixed double-click collapse toggle not owning the mouse button. If a
`SetNextWindowPos()` with pivot was queued in the same frame, the second
click could trigger another item in the same window. (#9439) [@Cleroth]
- Popups:
- Added bool return value to `OpenPopup()`, `OpenPopupOnItemClick()` functions
to notify when the popup was just opened. (#9429)
- InputText:
- Added `style.InputTextCursorSize` to configure cursor/caret thickness. (#7031, #9409)
It is automatically scaled by `style.ScaleAllSizes()`.
- Reworked `io.ConfigInputTextEnterKeepActive` mode so that pressing
Ctrl+Enter or Shift+Enter still allows to deactivate. (#9239)
- Tables:
- Redesigned/rewrote code to reconcile columns and settings on topology changes. (#9108)
- When a column label is passed to TableSetupColumn(), the underlying identifier
is used to match live columns data and .ini settings data when changing.
This makes it possible to add/remove columns from a table without losing
neither live data neither .ini settings data.
- PS: Note that this is distinct from toggling column visibility or reordering
columns, which was always possible. The new matching makes it easier to create
tables that are entirely customized by user or code, without losing state.
- Columns without identifiers or with duplicate identifiers are matched
sequentially, matching old behavior.
- Column ID are stored in .ini file.
- Code is being tested both for live topology changes and for loading .ini
data with mismatched topology.
- Context Menu: added a "Reset" sub-menu with a "Reset Visibility" option.
(which is greyed out when using default settings)
- Headers: fixed label being clipped early to reserve space for a sort marker
even when no sort marker is displayed. Auto-fitting a column still accounts
for the possible marker, so that sorting after an auto-fit doesn't clip the label.
- Multi-Select:
- Reworked `ImGuiMultiSelectFlags_NoAutoSelect` as it carried side-effects that
were hardcoded/designed to use multi-selection on checkboxes. (#9391)
Specifically removed those undocumented behaviors from `_NoAutoSelect`:
- Clicking a selected/checked item always unselect/uncheck.
- Shift+Click inverts targets value and copy to range.
- Shift+Keyboard copy selection source value to range.
Those behaviors are still happening on checkboxes used within multi-selection.
- Fonts:
- Added `IMGUI_DISABLE_DEFAULT_FONT_BITMAP`/`IMGUI_DISABLE_DEFAULT_FONT_VECTOR` to
disable embedding either fonts separately. (#9407)
- Tweak `CalcTextSize()` awkward width rounding/ceiling code to reduce floating-point
precision issues altering the result by 1 even at relatively small width. (#791)
- Better document the fact that `ImFontAtlas::Clear()`/`ClearFonts()` functions are
unlikely to be useful nowadays. Better recover to an edge case of mistakenly
calling `ClearFonts()` during rendering.
- Fixed an issue where passing a manually created ImFontAtlas to CreateContext() would
incorrectly destroy it in `DestroyContext()` when ref-count gets back to zero. (#9426)
- Destroying an ImGui context using a `ImFontAtlas` checks that the later has no references.
- Nav:
- Fixed context menu activation with gamepad erroneously testing for _NavEnableKeyboard
instead of _NavEnableGamepad. (#9454, #8803, #9270) [@Clownacy]
- TreeNode:
- Fixed nav cursor rendering with rounding even though tree nodes don't have it. (#7589)
- Inputs:
- Added `GetItemClickedCountWithSingleClickDelay()` helper for easy disambiguation
between single-click and double-click for actions that needs single-click to do
something other than selection. (#8337)
- Returns 1 on single-click but delayed by io.MouseSingleClickDelay.
- Returns 2 on double-click, and 2+ on subsequent repeated clicks.
- Added `io.MouseSingleClickDelay` to configure default delayed single click delay when
using `GetItemClickedCountWithSingleClickDelay()` or `IsMouseReleasedWithDelay()`. (#8337)
Note that `io.MouseSingleClickDelay` is always `> io.MouseDoubleClickTime`.
- ColorEdit:
- Added `io.ConfigColorEditFlags` to read/modify current color edit/picker settings.
- ColorPicker: added `ImGuiColorEditFlags_PickerNoRotate` to disable rotation of the
S/V triangle when in `ImGuiColorEditFlags_PickerHueWheel` mode. (#9337) [@SeanTheBuilder1]
Likely best passed to `style.ColorEditFlags` to setup globally and once.
- ColorButton: small rendering tweak/optimization for the alpha checkerboard.
- Style:
- Added style.MenuItemRounding, ImGuiStyleVar_MenuItemRounding. (#7589, #9375, #9453)
- Added style.SelectableRounding, ImGuiStyleVar_SelectableRounding. (#7589, #9375, #9453)
The use of this is discouraged because it can easily create problems rendering e.g.
contiguous selection.
- Scale the NavCursor border thickness when using large values with `ScallAllSizes()`.
- Settings:
- Windows/Tables settings entries can now record the last used date in YYYYMMDD format,
allowing tools to run to e.g. delete entries that haven't been used in X months. (#9460)
- Added `bool io.ConfigIniSettingsSaveLastUsedDate` to disable saving that info. (#9460)
- Added `int io.ConfigIniSettingsAutoDiscardMonths` to enable a mode where unused settings
are automatically discard after xx months. (#9460)
- Added a trimming tool under Metrics->Settings, along with a yet-unexposed function.
- The current system date is fed through `ImGuiPlatformIO::Platform_SessionDate`,
which is automatically set by a call to time() done during context creation. (#9460)
- Added `IMGUI_DISABLE_TIME_FUNCTIONS` to disable setting platform_io.Platform_SessionDate.
A custom backend may still set it manually. (#9460)
- DrawList:
- Minor optimization to `AddLine()`, `AddLineH()`, `AddLineV()` functions. (#4091)
- Added `ImDrawListFlags_TextNoPixelSnap` to disable snapping of AddText()
coordinates for a given scope. (#3437, #9417, #2291)
- Demo:
- Extract 'Widgets->Tree Nodes->Selectable Nodes' out of the 'Advanced'
demo for clarity (manual reimplementation of basic selection).
- Debug Tools:
- Added `IM_DEBUG_BREAK()` handler for GCC+AArch64/ARM64. [@tom-seddon]
- Backends:
- Android:
- Clear mouse position on touch release (`AMOTION_EVENT_ACTION_UP`) to prevent
items from staying in hovered state. (#6627, #9474) [@Turtle-PB]
- Metal4:
- Added new Metal 4 backend (forked from Metal 3 backend). (#9458, #9451) [@AmelieHeinrich]
- Added Metal-cpp support enabled with `IMGUI_IMPL_METAL_CPP` define. (#9461) [@MERL10N]
- OpenGL2:
- Backup and restore `GL_UNPACK_ROW_LENGTH` and `GL_UNPACK_ALIGNMENT` when updating texture
to avoid altering caller GL state. (#8802, #9473) [@Turtle-PB]
- OpenGL3:
- GLSL version detection assume GLSL 410 when GL context is 4.1.
Fixes an issue running on macOS with Wine. [#9427, #6577) [@perminovVS]
- Expose selected render state in `ImGui_ImplOpenGL3_RenderState`, allowing to
dynamically select between use of `glBindSampler()` and `glTexParameter()`. (#9378)
- Backup and restore `GL_UNPACK_ROW_LENGTH` and `GL_UNPACK_ALIGNMENT` when updating texture
to avoid altering caller GL state. (#8802, #9473) [@Turtle-PB]
- SDL2:
- Restore SDL_StartTextInput()/SDL_StopTextInput() in IME handler for on-screen keyboard
support on Android. (#7636, #9474) [@Turtle-PB]
- SDLRenderer3:
- Fixed sampler change which didn't work on all graphics backends. (#7616, #9470, #9378)
- Fixed default sampler not being Linear. Regression in 1.92.8. (#7616, #9470, #9378) [@ShiroKSH]
- Win32:
- Uses `SetProcessDpiAwarenessContext()` instead of `SetThreadDpiAwarenessContext()`
when available, fixing OpenGL DPI scaling issues as e.g. NVIDIA drivers tends
to spawn multiple-thread to manage OpenGL. (#9403)
- Examples:
- Android: update to AGP 9.2.0 to support Gradle 9.6.0.
- Apple+Metal4: added new example. (#9465, #9451) [@hoffstadt]
- OpenGL3+GLFW/SDL2/SDL3: allow Wine compatibility by passing empty GLSL version
string to ImGui_ImplOpenGL3_Init() to let backend decide of a GLSL version based
on actual GL version obtained. (#9427, #6577) [@perminovVS]
- OpenGL3+Win32: rework context creation to allow Wine compatibility. (#9427, #6577) [@perminovVS]
- SDL2/SDL3: use `SDL_GetWindowSizeInPixels()` to create frame-buffers. Fixes issues
with non-fractional framebuffer size on Wayland. (#8761, #9124) [@billtran1632001]
- SDL3+Metal4: added new example. (#9458, #9451) [@AmelieHeinrich]
-----------------------------------------------------------------------
VERSION 1.92.8 (Released 2026-05-12)
-----------------------------------------------------------------------
@@ -68,9 +292,13 @@ Breaking Changes:
The new order is also more convenient as `flags` are less frequently used than `thickness` in real code.
- As a general policy in Dear ImGui, all our flags default to 0 so ImDrawFlags_None was likely written 0 in some call sites.
- Consider adding `#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS` in your imconfig.h, even temporarily, to clean up legacy code.
- Reminder: you do NOT need to specify `ImDrawFlags_RoundCornersAll` for rounding, it is already the default!
- DrawList: obsoleted `ImDrawCallback_ResetRenderState` in favor of using `ImGui::GetPlatformIO().DrawCallback_ResetRenderState`,
which is part of our new standard draw callbacks. (#9378)
Redirecting the earlier value into the later one when set, so both old and new code should work.
- DrawList: changed value of `ImDrawFlags_Closed`. It was previously advertised as "always == 1" when introduced
in 1.82 (2021/02), in order to facilitate backward compatibility with the legacy `bool closed` flag. This
guarantee has been removed. The bit is reserved, and `AddPolyline()`, `PathStroke()` will assert when it is used.
- Backends:
- Vulkan: redesigned to use separate ImageView + Sampler instead of Combined Image Sampler. (#914)
This change allows us to facilitate changing samplers, in line with other backends. [@yaz0r, @ocornut]
@@ -85,6 +313,8 @@ Breaking Changes:
- DirectX10, DirectX11, SDLGPU3, Vulkan: removed samplers from `ImGui_ImplXXXX_RenderState`.
Prefer to use backend-agnostic DrawCallback_SetSamplerLinear which works everywhere! (#9378)
If there is a legit need/request for them or any render state we can always add them back.
- OpenGL3: the new sampler support system prioritize using glBindSampler() when available,
which would override glTexParameter() settings you may have set on custom textures. (#9378)
Other Changes:
@@ -101,6 +331,15 @@ Other Changes:
#5999, #6452, #5156, #7342, #7592, #7511)
- Made `AddCallback()` user data default to Null for convenience.
- Added `AddLineH()`, `AddLineV()` helpers to draw horizontal and vertical lines. [@memononen]
The new functions are more optimal and will be part of a larger effort in 1.93 to fix
inconsistencies and improve the DrawList API. In the current API, `AddLine()` adds a "magic" +0.5f
offset and then center the line, whereas AddLineH()/AddLineV() use the right side of the line to expand.
For thickness=1.0f lines this is equivalent:
`AddLine({10,3}, {20,3}, ...)` --> `AddLineH(x1=10, x2=20, y=3, ...)`.
`AddLine({3,10}, {3,20}, ...)` --> `AddLineV(x=3, y1=10, y2=20, ...)`.
For larger integer thickness, AddLine() will center but may be blurry, AddLineH()/AddLineV()
will expand "inside" (to the right side) and will always be sharp.
A subsequent release will expand on those concepts and add new options.
- InputText:
- InputTextMultiline: fixed an issue processing deactivation logic when an active
multi-line edit is clipped due to being out of view.
@@ -889,7 +1128,7 @@ Other Changes:
not available. (#5924, #5562)
- SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82]
- Win32+DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
- Made examples's main.cpp consistent with returning 1 on error.
- Made examples' main.cpp consistent with returning 1 on error.
-----------------------------------------------------------------------
@@ -3331,8 +3570,10 @@ Breaking changes:
input queue. This is automatically cleared by io.ClearInputKeys(). (#4921)
- ImDrawData: CmdLists[] array is now owned, changed from 'ImDrawList**' to
'ImVector<ImDrawList*>'. Majority of users shouldn't be affected, but you
cannot compare to NULL nor reassign manually anymore.
Instead use AddDrawList(). Allocation count are identical. (#6406, #4879, #1878)
cannot compare to NULL nor reassign manually anymore. (#6406, #4879, #1878)
- Allocation count are identical.
- Use `draw_data->CmdLists.Size` instead of `draw_list->CmdListsCount`!
- Use `AddDrawList()` to add to a `ImDrawData`.
Other changes:
+2 -2
View File
@@ -5,14 +5,14 @@ add_library(imgui
include/imgui_internal.h
include/imgui_stdlib.h
include/imstb_textedit.h
include/imstb_rectpack.h
include/imstb_truetype.h
src/imgui.cpp
src/imgui_demo.cpp
src/imgui_draw.cpp
src/imgui_freetype.cpp
src/imgui_tables.cpp
src/imgui_widgets.cpp
src/imstb_rectpack.h
src/imstb_truetype.h
src/imgui_stdlib.cpp
)
+5 -2
View File
@@ -43,17 +43,20 @@
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_TIME_FUNCTIONS // Don't setup default platform_io.Platform_SessionDate value using time(), localtime_r().
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded fonts (ProggyClean/ProggyForever), remove ~9 KB + ~14 KB from output binary. AddFontDefaultXXX() functions will assert.
//#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded fonts (ProggyClean + ProggyForever). Remove ~9 KB + ~14 KB from output binary. AddFontDefaultXXX() functions will assert.
//#define IMGUI_DISABLE_DEFAULT_FONT_BITMAP // Disable default embedded bitmap font (ProggyClean). Remove ~9 KB from output binary. AddFontDefaultBitmap() will assert.
//#define IMGUI_DISABLE_DEFAULT_FONT_VECTOR // Disable default embedded vector font (ProggyForever), Remove ~14 KB from output binary. AddFontDefaultVector() will assert.
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available
//---- Enable Test Engine / Automation features.
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_imconfig.h", see Test Engine for details.
//---- Include imgui_user.h at the end of imgui.h as a convenience
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
+119 -63
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.8
// dear imgui, v1.92.9b
// (headers)
// Help:
@@ -29,8 +29,8 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.92.8"
#define IMGUI_VERSION_NUM 19280
#define IMGUI_VERSION "1.92.9b"
#define IMGUI_VERSION_NUM 19291
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
@@ -243,7 +243,7 @@ typedef int ImFontAtlasFlags; // -> enum ImFontAtlasFlags_ // Flags: f
typedef int ImGuiBackendFlags; // -> enum ImGuiBackendFlags_ // Flags: for io.BackendFlags
typedef int ImGuiButtonFlags; // -> enum ImGuiButtonFlags_ // Flags: for InvisibleButton()
typedef int ImGuiChildFlags; // -> enum ImGuiChildFlags_ // Flags: for BeginChild()
typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: for ColorEdit4(), ColorPicker4() etc.
typedef int ImGuiColorEditFlags; // -> enum ImGuiColorEditFlags_ // Flags: for ColorEdit4(), ColorPicker4(), io.ConfigColorEditFlags etc.
typedef int ImGuiConfigFlags; // -> enum ImGuiConfigFlags_ // Flags: for io.ConfigFlags
typedef int ImGuiComboFlags; // -> enum ImGuiComboFlags_ // Flags: for BeginCombo()
typedef int ImGuiDragDropFlags; // -> enum ImGuiDragDropFlags_ // Flags: for BeginDragDropSource(), AcceptDragDropPayload()
@@ -613,7 +613,8 @@ namespace ImGui
IMGUI_API ImGuiID GetID(int int_id);
// Widgets: Text
IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Roughly equivalent to Text("%s", text) but: A) doesn't require null terminated string if 'text_end' is specified, B) it's faster, no memory copy is done, no buffer size limits, recommended for long chunks of text.
// - Note that all functions taking format strings in the API may be passed ("%s", text) or ("%.*s", text_len, text): which will automatically bypass the formatter.
IMGUI_API void TextUnformatted(const char* text, const char* text_end = NULL); // raw text without formatting. Practically equivalent to 'Text("%s", text)' but doesn't require null terminated string if 'text_end' is specified.
IMGUI_API void Text(const char* fmt, ...) IM_FMTARGS(1); // formatted text
IMGUI_API void TextV(const char* fmt, va_list args) IM_FMTLIST(1);
IMGUI_API void TextColored(const ImVec4& col, const char* fmt, ...) IM_FMTARGS(2); // shortcut for PushStyleColor(ImGuiCol_Text, col); Text(fmt, ...); PopStyleColor();
@@ -648,7 +649,7 @@ namespace ImGui
// Widgets: Images
// - Read about ImTextureID/ImTextureRef here: https://github.com/ocornut/imgui/wiki/Image-Loading-and-Displaying-Examples
// - 'uv0' and 'uv1' are texture coordinates. Read about them from the same link above.
// - Image() pads adds style.ImageBorderSize on each side, ImageButton() adds style.FramePadding on each side.
// - Image() adds style.ImageBorderSize on each side, ImageButton() adds style.FramePadding on each side.
// - ImageButton() draws a background based on regular Button() color + optionally an inner background if specified.
// - An obsolete version of Image(), before 1.91.9 (March 2025), had a 'tint_col' parameter which is now supported by the ImageWithBg() function.
IMGUI_API void Image(ImTextureRef tex_ref, const ImVec2& image_size, const ImVec2& uv0 = ImVec2(0, 0), const ImVec2& uv1 = ImVec2(1, 1));
@@ -736,7 +737,6 @@ namespace ImGui
IMGUI_API bool ColorPicker3(const char* label, float col[3], ImGuiColorEditFlags flags = 0);
IMGUI_API bool ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags flags = 0, const float* ref_col = NULL);
IMGUI_API bool ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFlags flags = 0, const ImVec2& size = ImVec2(0, 0)); // display a color square/button, hover for details, return true when pressed.
IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // initialize current options (generally on application startup) if you want to select a default format, picker type, etc. User will be able to change many settings, unless you pass the _NoOptions flag to your calls.
// Widgets: Trees
// - TreeNode functions return true when the node is open, in which case you need to also call TreePop() when you are finished displaying the tree node contents.
@@ -808,7 +808,7 @@ namespace ImGui
// - Use BeginMenuBar() on a window ImGuiWindowFlags_MenuBar to append to its menu bar.
// - Use BeginMainMenuBar() to create a menu bar at the top of the screen and append to it.
// - Use BeginMenu() to create a menu. You can call BeginMenu() multiple time with the same identifier to append more items to it.
// - Not that MenuItem() keyboardshortcuts are displayed as a convenience but _not processed_ by Dear ImGui at the moment.
// - Note that MenuItem() keyboard shortcuts are displayed as a convenience but _not processed_ by Dear ImGui at the moment.
IMGUI_API bool BeginMenuBar(); // append to menu-bar of current window (requires ImGuiWindowFlags_MenuBar flag set on parent window).
IMGUI_API void EndMenuBar(); // only call EndMenuBar() if BeginMenuBar() returns true!
IMGUI_API bool BeginMainMenuBar(); // create and append to a full screen menu-bar.
@@ -837,7 +837,7 @@ namespace ImGui
// Popups, Modals
// - They block normal mouse hovering detection (and therefore most mouse interactions) behind them.
// - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
// - If not modal: they can be closed by clicking anywhere outside them, or by pressing Escape (call 'Shortcut(ImGuiKey_Escape)' to claim a higher-priority shortcut).
// - Their visibility state (~bool) is held internally instead of being held by the programmer as we are used to with regular Begin*() calls.
// - The 3 properties above are related: we need to retain popup visibility state in the library because popups may be closed as any time.
// - You can bypass the hovering restriction by using ImGuiHoveredFlags_AllowWhenBlockedByPopup when calling IsItemHovered() or IsWindowHovered().
@@ -850,15 +850,17 @@ namespace ImGui
IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true!
// Popups: open/close functions
// - OpenPopup(): set popup state to open. ImGuiPopupFlags are available for opening options.
// - OpenPopup(): set popup state to open (unless one of the specified ImGuiPopupFlags prevent opening).
// - OpenPopupXXX() functions return true when the popup is toggled open, which allows you to capture local state if needed.
// You may also call IsWindowAppearing() inside the later BeginPopup() scope if you need to prepare/compute data for the popup.
// - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE.
// - CloseCurrentPopup(): use inside the BeginPopup()/EndPopup() scope to close manually.
// - CloseCurrentPopup() is called by default by Selectable()/MenuItem() when activated (FIXME: need some options).
// - Use ImGuiPopupFlags_NoOpenOverExistingPopup to avoid opening a popup if there's already one at the same level. This is equivalent to e.g. testing for !IsAnyPopupOpen() prior to OpenPopup().
// - Use IsWindowAppearing() after BeginPopup() to tell if a window just opened.
IMGUI_API void OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!).
IMGUI_API void OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks
IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors)
IMGUI_API bool OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!).
IMGUI_API bool OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks
IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors)
IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into.
// Popups: Open+Begin popup combined functions helpers to create context menus.
@@ -908,14 +910,15 @@ namespace ImGui
IMGUI_API bool TableSetColumnIndex(int column_n); // append into the specified column. Return true when column is visible.
// Tables: Headers & Columns declaration
// - Use TableSetupColumn() to specify label, resizing policy, default width/weight, id, various other flags etc.
// - Use TableSetupColumn() to specify label, resizing policy, default width/weight, various other flags etc.
// (the trailing 'ImGuiID user_data', which used to be referred to as 'ImGuiID user_id', is merely user data that is blindly copied in ImGuiTableColumnSortSpecs).
// - Use TableHeadersRow() to create a header row and automatically submit a TableHeader() for each column.
// Headers are required to perform: reordering, sorting, and opening the context menu.
// The context menu can also be made available in columns body using ImGuiTableFlags_ContextMenuInBody.
// - You may manually submit headers using TableNextRow() + TableHeader() calls, but this is only useful in
// some advanced use cases (e.g. adding custom widgets in header row).
// - Use TableSetupScrollFreeze() to lock columns/rows so they stay visible when scrolled. When freezing columns you would usually also use ImGuiTableColumnFlags_NoHide on them.
IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_id = 0);
IMGUI_API void TableSetupColumn(const char* label, ImGuiTableColumnFlags flags = 0, float init_width_or_weight = 0.0f, ImGuiID user_data = 0);
IMGUI_API void TableSetupScrollFreeze(int cols, int rows); // lock columns/rows so they stay visible when scrolled.
IMGUI_API void TableHeader(const char* label); // submit one header cell manually (rarely used)
IMGUI_API void TableHeadersRow(); // submit a row with headers cells based on data provided to TableSetupColumn() + submit context menu
@@ -1024,6 +1027,7 @@ namespace ImGui
IMGUI_API ImVec2 GetItemRectMax(); // get lower-right bounding rectangle of the last item (screen space)
IMGUI_API ImVec2 GetItemRectSize(); // get size of last item
IMGUI_API ImGuiItemFlags GetItemFlags(); // get generic flags of last item
IMGUI_API int GetItemClickedCountWithSingleClickDelay(ImGuiMouseButton mouse_button = 0, float delay = -1.0f); // [BETA] building block for disambiguation between single-click and double-click. Returns 1 on single-click but delayed by io.MouseSingleClickDelay after mouse release. Returns 2+ on double-click or repeated clicks.
// Viewports
// - Currently represents the Platform Window created by the application which is hosting our Dear ImGui windows.
@@ -1106,7 +1110,7 @@ namespace ImGui
IMGUI_API bool IsMouseClicked(ImGuiMouseButton button, bool repeat = false); // did mouse button clicked? (went from !Down to Down). Same as GetMouseClickedCount() == 1.
IMGUI_API bool IsMouseReleased(ImGuiMouseButton button); // did mouse button released? (went from Down to !Down)
IMGUI_API bool IsMouseDoubleClicked(ImGuiMouseButton button); // did mouse button double-clicked? Same as GetMouseClickedCount() == 2. (note that a double-click will also report IsMouseClicked() == true)
IMGUI_API bool IsMouseReleasedWithDelay(ImGuiMouseButton button, float delay); // delayed mouse release (use very sparingly!). Generally used with 'delay >= io.MouseDoubleClickTime' + combined with a 'io.MouseClickedLastCount==1' test. This is a very rarely used UI idiom, but some apps use this: e.g. MS Explorer single click on an icon to rename.
IMGUI_API bool IsMouseReleasedWithDelay(ImGuiMouseButton button, float delay=-1.f);// delayed mouse release. Use sparingly. Prefer higher-level helper GetItemClickedCountWithSingleClickDelay(). Generally used with 'delay >= io.MouseDoubleClickTime' + combined with a 'io.MouseClickedLastCount==1' test.
IMGUI_API int GetMouseClickedCount(ImGuiMouseButton button); // return the number of successive mouse-clicks at the time where a click happen (otherwise 0).
IMGUI_API bool IsMouseHoveringRect(const ImVec2& r_min, const ImVec2& r_max, bool clip = true);// is mouse hovering given bounding rect (in screen space). clipped by current clipping settings, but disregarding of other consideration of focus/window ordering/popup-block.
IMGUI_API bool IsMousePosValid(const ImVec2* mouse_pos = NULL); // by convention we use (-FLT_MAX,-FLT_MAX) to denote that there is no mouse available
@@ -1236,14 +1240,27 @@ enum ImGuiChildFlags_
// (Those are shared by all submitted items)
enum ImGuiItemFlags_
{
ImGuiItemFlags_None = 0, // (Default)
ImGuiItemFlags_None = 0, // Default:
ImGuiItemFlags_NoTabStop = 1 << 0, // false // Disable keyboard tabbing. This is a "lighter" version of ImGuiItemFlags_NoNav.
ImGuiItemFlags_NoNav = 1 << 1, // false // Disable any form of focusing (keyboard/gamepad directional navigation and SetKeyboardFocusHere() calls).
ImGuiItemFlags_NoNav = 1 << 1, // false // Disable any form of focusing: keyboard/gamepad directional navigation and SetKeyboardFocusHere() calls.
ImGuiItemFlags_NoNavDefaultFocus = 1 << 2, // false // Disable item being a candidate for default focus (e.g. used by title bar items).
ImGuiItemFlags_ButtonRepeat = 1 << 3, // false // Any button-like behavior will have repeat mode enabled (based on io.KeyRepeatDelay and io.KeyRepeatRate values). Note that you can also call IsItemActive() after any button to tell if it is being held.
ImGuiItemFlags_AutoClosePopups = 1 << 4, // true // MenuItem()/Selectable() automatically close their parent popup window.
ImGuiItemFlags_AllowDuplicateId = 1 << 5, // false // Allow submitting an item with the same identifier as an item already submitted this frame without triggering a warning tooltip if io.ConfigDebugHighlightIdConflicts is set.
ImGuiItemFlags_Disabled = 1 << 6, // false // [Internal] Disable interactions. DOES NOT affect visuals. This is used by BeginDisabled()/EndDisabled() and only provided here so you can read back via GetItemFlags().
//---------------------------------------------------------------------------------
// LiveEdit refers to applying edits to backing variables _while_ typing a value using the keyboard.
// Widget: | Input: | w/ LiveEdit: | Output:
// InputText() | "123" | on(default) | "1" then "12" then "123"
// InputText() | "123" | off | "123" after validating or tabbing out or losing focus.
// DragFloat(), SliderInt(), etc. | "123" | on* | 1 then 12 then 123
// DragFloat(), SliderInt(), etc. | "123" | off(default)* | 123 after validation or tabbing out or losing focus.
// (*) Since 1.92.9 (July 2026), ImGuiItemFlags_LiveEditOnInputScalar is OFF by default. In prior version it was ON for everything.
//---------------------------------------------------------------------------------
ImGuiItemFlags_LiveEditOnInputText = 1 << 7, // true // InputText: apply keyboard edits to backing value while typing. Otherwise, edits are applied when validating, tabbing out or losing focus.
ImGuiItemFlags_LiveEditOnInputScalar = 1 << 8, // false // DragXXX, SliderXXX, InputScalar: apply keyboard edits to backing value while typing. Otherwise, edits are applied when validating, tabbing out or losing focus.
ImGuiItemFlags_LiveEditOnInput = ImGuiItemFlags_LiveEditOnInputText | ImGuiItemFlags_LiveEditOnInputScalar,
};
// Flags for ImGui::InputText()
@@ -1260,7 +1277,7 @@ enum ImGuiInputTextFlags_
// Inputs
ImGuiInputTextFlags_AllowTabInput = 1 << 5, // Pressing TAB input a '\t' character into the text field
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider using IsItemDeactivatedAfterEdit() instead!
ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider disabling LiveEdit! or using IsItemDeactivatedAfterEdit() instead!
ImGuiInputTextFlags_EscapeClearsAll = 1 << 7, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert)
ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode: validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter). Note that Shift+Enter always enter a new line either way.
@@ -1273,6 +1290,7 @@ enum ImGuiInputTextFlags_
ImGuiInputTextFlags_DisplayEmptyRefVal = 1 << 14, // InputFloat(), InputInt(), InputScalar() etc. only: when value is zero, do not display it. Generally used with ImGuiInputTextFlags_ParseEmptyRefVal.
ImGuiInputTextFlags_NoHorizontalScroll = 1 << 15, // Disable following the cursor horizontally
ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
//ImGuiInputTextFlags_NoLiveEdit = 1 << 25, // Disable applying output to backing variable while typing. Same as setting ImGuiItemFlags_LiveEditOnInput to false.
// Elide display / Alignment
ImGuiInputTextFlags_ElideLeft = 1 << 17, // When text doesn't fit, elide left side to ensure right side stays visible. Useful for path/filenames. Single-line only!
@@ -1330,7 +1348,7 @@ enum ImGuiTreeNodeFlags_
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiTreeNodeFlags_NavLeftJumpsBackHere = ImGuiTreeNodeFlags_NavLeftJumpsToParent, // Renamed in 1.92.0
ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7
//ImGuiTreeNodeFlags_SpanTextWidth = ImGuiTreeNodeFlags_SpanLabelWidth, // Renamed in 1.90.7
//ImGuiTreeNodeFlags_AllowItemOverlap = ImGuiTreeNodeFlags_AllowOverlap, // Renamed in 1.89.7
#endif
};
@@ -1501,7 +1519,7 @@ enum ImGuiDragDropFlags_
ImGuiDragDropFlags_AcceptPeekOnly = ImGuiDragDropFlags_AcceptBeforeDelivery | ImGuiDragDropFlags_AcceptNoDrawDefaultRect, // For peeking ahead and inspecting the payload before delivery.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiDragDropFlags_SourceAutoExpirePayload = ImGuiDragDropFlags_PayloadAutoExpire, // Renamed in 1.90.9
//ImGuiDragDropFlags_SourceAutoExpirePayload = ImGuiDragDropFlags_PayloadAutoExpire, // Renamed in 1.90.9
#endif
};
@@ -1854,6 +1872,8 @@ enum ImGuiStyleVar_
ImGuiStyleVar_TableAngledHeadersTextAlign,// ImVec2 TableAngledHeadersTextAlign
ImGuiStyleVar_TreeLinesSize, // float TreeLinesSize
ImGuiStyleVar_TreeLinesRounding, // float TreeLinesRounding
ImGuiStyleVar_MenuItemRounding, // float MenuItemRounding
ImGuiStyleVar_SelectableRounding, // float SelectableRounding
ImGuiStyleVar_DragDropTargetRounding, // float DragDropTargetRounding
ImGuiStyleVar_ButtonTextAlign, // ImVec2 ButtonTextAlign
ImGuiStyleVar_SelectableTextAlign, // ImVec2 SelectableTextAlign
@@ -1900,7 +1920,8 @@ enum ImGuiColorEditFlags_
ImGuiColorEditFlags_AlphaNoBg = 1 << 13, // // ColorEdit, ColorPicker, ColorButton: disable rendering a checkerboard background behind transparent color.
ImGuiColorEditFlags_AlphaPreviewHalf= 1 << 14, // // ColorEdit, ColorPicker, ColorButton: display half opaque / half transparent preview.
// User Options (right-click on widget to change some of them).
// User Options (right-click on widget to change some of them)
// Current settings are stored in style.ColorEditFlags.
ImGuiColorEditFlags_AlphaBar = 1 << 18, // // ColorEdit, ColorPicker: show vertical alpha bar/gradient in picker.
ImGuiColorEditFlags_HDR = 1 << 19, // // (WIP) ColorEdit: Currently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well).
ImGuiColorEditFlags_DisplayRGB = 1 << 20, // [Display] // ColorEdit: override _display_ type among RGB/HSV/Hex. ColorPicker: select any combination using one or more of RGB/HSV/Hex.
@@ -1910,11 +1931,13 @@ enum ImGuiColorEditFlags_
ImGuiColorEditFlags_Float = 1 << 24, // [DataType] // ColorEdit, ColorPicker, ColorButton: _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers.
ImGuiColorEditFlags_PickerHueBar = 1 << 25, // [Picker] // ColorPicker: bar for Hue, rectangle for Sat/Value.
ImGuiColorEditFlags_PickerHueWheel = 1 << 26, // [Picker] // ColorPicker: wheel for Hue, triangle for Sat/Value.
ImGuiColorEditFlags_InputRGB = 1 << 27, // [Input] // ColorEdit, ColorPicker: input and output data in RGB format.
ImGuiColorEditFlags_InputHSV = 1 << 28, // [Input] // ColorEdit, ColorPicker: input and output data in HSV format.
ImGuiColorEditFlags_PickerNoRotate = 1 << 27, // [Picker] // ColorPicker: disable rotating Sat/Value triangle. Best set in io.ConfigColorEditFlags once.
ImGuiColorEditFlags_InputRGB = 1 << 28, // [Input] // ColorEdit, ColorPicker: input and output data in RGB format.
ImGuiColorEditFlags_InputHSV = 1 << 29, // [Input] // ColorEdit, ColorPicker: input and output data in HSV format.
// Defaults Options. You can set application defaults using SetColorEditOptions(). The intent is that you probably don't want to
// override them in most of your calls. Let the user choose via the option menu and/or call SetColorEditOptions() once during startup.
// Defaults Options copied to io.ConfigColorEditFlags during initialization.
// The intent is that you probably don't want to override them in most of your calls.
// Let the user choose via the option menu and/or modify io.ConfigColorEditFlags directly during startup if you want.
ImGuiColorEditFlags_DefaultOptions_ = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputRGB | ImGuiColorEditFlags_PickerHueBar,
// [Internal] Masks
@@ -1927,8 +1950,8 @@ enum ImGuiColorEditFlags_
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiColorEditFlags_AlphaPreview = 0, // Removed in 1.91.8. This is the default now. Will display a checkerboard unless ImGuiColorEditFlags_AlphaNoBg is set.
#endif
//ImGuiColorEditFlags_RGB = ImGuiColorEditFlags_DisplayRGB, ImGuiColorEditFlags_HSV = ImGuiColorEditFlags_DisplayHSV, ImGuiColorEditFlags_HEX = ImGuiColorEditFlags_DisplayHex // [renamed in 1.69]
#endif
};
// Flags for DragFloat(), DragInt(), SliderFloat(), SliderInt() etc.
@@ -1946,6 +1969,8 @@ enum ImGuiSliderFlags_
ImGuiSliderFlags_NoSpeedTweaks = 1 << 11, // Disable keyboard modifiers altering tweak speed. Useful if you want to alter tweak speed yourself based on your own logic.
ImGuiSliderFlags_ColorMarkers = 1 << 12, // DragScalarN(), SliderScalarN(): Draw R/G/B/A color markers on each component.
ImGuiSliderFlags_AlwaysClamp = ImGuiSliderFlags_ClampOnInput | ImGuiSliderFlags_ClampZeroRange,
//ImGuiSliderFlags_LiveEditOnInput = 1 << 13, // Shortcut to enable LiveEdit for this field.
//ImGuiSliderFlags_NoLiveEditOnInput= 1 << 14, // Shortcut to disable LiveEdit for this field.
ImGuiSliderFlags_InvalidMask_ = 0x7000000F, // [Internal] We treat using those bits as being potentially a 'float power' argument from legacy API (obsoleted 2020-08) that has got miscast to this enum, and will trigger an assert if needed.
};
@@ -2158,7 +2183,7 @@ struct ImGuiTableSortSpecs
// Sorting specification for one column of a table (sizeof == 12 bytes)
struct ImGuiTableColumnSortSpecs
{
ImGuiID ColumnUserID; // User id of the column (if specified by a TableSetupColumn() call)
ImGuiID ColumnUserID; // User data for the column (if specified by a TableSetupColumn() call in the 'ImGuiID user_data' field). FIXME: Should be called 'UserData'..
ImS16 ColumnIndex; // Index of the column
ImS16 SortOrder; // Index within parent ImGuiTableSortSpecs (always stored in order starting from 0, tables sorted on a single criteria will always have a 0 here)
ImGuiSortDirection SortDirection; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
@@ -2331,6 +2356,8 @@ struct ImGuiStyle
ImGuiTreeNodeFlags TreeLinesFlags; // Default way to draw lines connecting TreeNode hierarchy. ImGuiTreeNodeFlags_DrawLinesNone or ImGuiTreeNodeFlags_DrawLinesFull or ImGuiTreeNodeFlags_DrawLinesToNodes.
float TreeLinesSize; // Thickness of outlines when using ImGuiTreeNodeFlags_DrawLines.
float TreeLinesRounding; // Radius of lines connecting child nodes to the vertical line.
float MenuItemRounding; // Radius of MenuItem, BeginMenu rounding.
float SelectableRounding; // Radius of Selectable rounding. MODIFYING THIS IS DISCOURAGED. CONTIGUOUS SELECTIONS WILL NOT LOOK RIGHT. (#7589)
float DragDropTargetRounding; // Radius of the drag and drop target frame. When <0.0f: use FrameRounding.
float DragDropTargetBorderSize; // Thickness of the drag and drop target border.
float DragDropTargetPadding; // Size to expand the drag and drop target from actual target item size.
@@ -2338,6 +2365,7 @@ struct ImGuiStyle
ImGuiDir ColorButtonPosition; // Side of the color button in the ColorEdit4 widget (left/right). Defaults to ImGuiDir_Right.
ImVec2 ButtonTextAlign; // Alignment of button text when button is larger than text. Defaults to (0.5f, 0.5f) (centered).
ImVec2 SelectableTextAlign; // Alignment of selectable text. Defaults to (0.0f, 0.0f) (top-left aligned). It's generally important to keep this left-aligned if you want to lay multiple items on a same line.
float InputTextCursorSize; // Thickness of cursor/caret in InputText().
float SeparatorSize; // Thickness of border in Separator(). Must be >= 1.0f.
float SeparatorTextBorderSize; // Thickness of border in SeparatorText()
ImVec2 SeparatorTextAlign; // Alignment of text within the separator. Defaults to (0.0f, 0.5f) (left aligned, center).
@@ -2428,24 +2456,33 @@ struct ImGuiIO
bool ConfigNavCursorVisibleAuto; // = true // Using directional navigation key makes the cursor visible. Mouse click hides the cursor.
bool ConfigNavCursorVisibleAlways; // = false // Navigation cursor is always visible.
// Miscellaneous options
// (you can visualize and interact with all options in 'Demo->Configuration')
bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
// Widget options
bool ConfigMacOSXBehaviors; // = defined(__APPLE__) // Swap Cmd<>Ctrl keys + OS X style text editing cursor movement using Alt instead of Ctrl, Shortcuts using Cmd/Super instead of Ctrl, Line/Text Start and End using Cmd+Arrows instead of Home/End, Double click selects by word instead of selecting whole text, Multi-selection in lists uses Cmd/Super instead of Ctrl.
bool ConfigInputTrickleEventQueue; // = true // Enable input queue trickling: some types of events submitted during the same frame (e.g. button down + up) will be spread over multiple frames, improving interactions with low framerates.
bool ConfigInputTextCursorBlink; // = true // Enable blinking cursor (optional as some users consider it to be distracting).
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only).
bool ConfigInputTextEnterKeepActive; // = false // [BETA] Pressing Enter will reactivate item and select all text (single-line only). Ctrl+Enter or Shift+Enter will deactivate normally.
ImGuiColorEditFlags ConfigColorEditFlags; // = <defaults> // Current settings for ColorEdit/ColorPicker widgets. Must have one bit of ImGuiColorEditFlags_DisplayMask_, one bit of ImGuiColorEditFlags_DataTypeMask_, one bit of ImGuiColorEditFlags_PickerMask_, one bit of ImGuiColorEditFlags_InputMask_. Defaults to ImGuiColorEditFlags_DefaultOptions_. May be further edited by users, unless you also set ImGuiColorEditFlags_NoOptions.
bool ConfigDragClickToInputText; // = false // [BETA] Enable turning DragXXX widgets into text input with a simple mouse click-release (without moving). Not desirable on devices without a keyboard.
bool ConfigWindowsResizeFromEdges; // = true // Enable resizing of windows from their edges and from the lower-left corner. This requires ImGuiBackendFlags_HasMouseCursors for better mouse cursor feedback. (This used to be a per-window ImGuiWindowFlags_ResizeFromAnySide flag)
bool ConfigWindowsMoveFromTitleBarOnly; // = false // Enable allowing to move windows only when clicking on their title bar. Does not apply to windows without a title bar.
bool ConfigWindowsCopyContentsWithCtrlC; // = false // [EXPERIMENTAL] Ctrl+C copy the contents of focused window into the clipboard. Experimental because: (1) has known issues with nested Begin/End pairs (2) text output quality varies (3) text output is in submission order rather than spatial order.
bool ConfigScrollbarScrollByPage; // = true // Enable scrolling page by page when clicking outside the scrollbar grab. When disabled, always scroll to clicked location. When enabled, Shift+Click scrolls to clicked location.
// Ini Settings options
bool ConfigIniSettingsSaveLastUsedDate;// = true // Enable loading/saving last used day (YYYYMMDD) in some .ini struct, making things easier to audit and allowing custom tools to cleanup old data.
int ConfigIniSettingsAutoDiscardMonths; // = 0 // [BETA] Set number of months after which unused .ini entries are discarded on load. Require platform_io.Platform_SessionDate to be set. For systems supporting the feature, .ini entries without a LastUsed field will always be discarded! Please report if you are using this.
bool ConfigDebugIniSettings; // = false // Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower)
// Miscellaneous options
// (you can visualize and interact with all options in 'Demo->Configuration')
bool MouseDrawCursor; // = false // Request ImGui to draw a mouse cursor for you (if you are on a platform without a mouse cursor). Cannot be easily renamed to 'io.ConfigXXX' because this is frequently used by backend implementations.
float ConfigMemoryCompactTimer; // = 60.0f // Timer (in seconds) to free transient windows/tables memory buffers when unused. Set to -1.0f to disable.
// Inputs Behaviors
// (other variables, ones which are expected to be tweaked within UI code, are exposed in ImGuiStyle)
float MouseDoubleClickTime; // = 0.30f // Time for a double-click, in seconds.
float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click, in pixels.
float MouseDoubleClickTime; // = 0.30f // Time for consecutive clicks to account as a double-click, in seconds.
float MouseDoubleClickMaxDist; // = 6.0f // Distance threshold to stay in to validate a double-click or multiple clicks, in pixels.
float MouseSingleClickDelay; // = 0.60f // Time for a delayed click when using GetItemClickedCountWithSingleClickDelay() or IsMouseReleasedWithDelay(), in seconds. Must be > io.MouseDoubleClickTime.
float MouseDragThreshold; // = 6.0f // Distance threshold before considering we are dragging.
float KeyRepeatDelay; // = 0.275f // When holding a key/button, time before it starts repeating, in seconds (for buttons in Repeat mode, etc.).
float KeyRepeatRate; // = 0.050f // When holding a key/button, rate at which it repeats, in seconds.
@@ -2498,9 +2535,6 @@ struct ImGuiIO
// - Backends may have other side-effects on focus loss, so this will reduce side-effects but not necessary remove all of them.
bool ConfigDebugIgnoreFocusLoss; // = false // Ignore io.AddFocusEvent(false), consequently not calling io.ClearInputKeys()/io.ClearInputMouse() in input processing.
// Option to audit .ini data
bool ConfigDebugIniSettings; // = false // Save .ini data with extra comments (particularly helpful for Docking, but makes saving slower)
//------------------------------------------------------------------
// Platform Identifiers
// (the imgui_impl_xxxx backend files are setting those up for you)
@@ -2612,7 +2646,7 @@ struct ImGuiIO
//void* ImeWindowHandle; // [Obsoleted in 1.87] Set ImGuiViewport::PlatformHandleRaw instead. Set this to your HWND to get automatic IME cursor positioning.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
float FontGlobalScale; // Moved io.FontGlobalScale to style.FontScaleMain in 1.92 (June 2025)
float FontGlobalScale; // Moved io.FontGlobalScale to style.FontScaleMain in 1.92.0 (June 2025)
// Legacy: before 1.91.1, clipboard functions were stored in ImGuiIO instead of ImGuiPlatformIO.
// As this is will affect all users of custom engines/backends, we are providing proper legacy redirection (will obsolete).
@@ -3049,6 +3083,7 @@ enum ImGuiMultiSelectFlags_
ImGuiMultiSelectFlags_NavWrapX = 1 << 16, // [Temporary] Enable navigation wrapping on X axis. Provided as a convenience because we don't have a design for the general Nav API for this yet. When the more general feature be public we may obsolete this flag in favor of new one.
ImGuiMultiSelectFlags_NoSelectOnRightClick = 1 << 17, // Disable default right-click processing, which selects item on mouse down, and is designed for context-menus.
ImGuiMultiSelectFlags_SelectOnMask_ = ImGuiMultiSelectFlags_SelectOnAuto | ImGuiMultiSelectFlags_SelectOnClickAlways | ImGuiMultiSelectFlags_SelectOnClickRelease,
ImGuiMultiSelectFlags_CheckboxMode_ = 1 << 20, // [Internal]
// Obsolete names
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
@@ -3245,20 +3280,27 @@ struct ImDrawListSplitter
enum ImDrawFlags_
{
ImDrawFlags_None = 0,
ImDrawFlags_RoundCornersTopLeft = 1 << 4, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-left corner only (when rounding > 0.0f, we default to all corners). Was 0x01.
ImDrawFlags_RoundCornersTopRight = 1 << 5, // AddRect(), AddRectFilled(), PathRect(): enable rounding top-right corner only (when rounding > 0.0f, we default to all corners). Was 0x02.
ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-left corner only (when rounding > 0.0f, we default to all corners). Was 0x04.
ImDrawFlags_RoundCornersBottomRight = 1 << 7, // AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-right corner only (when rounding > 0.0f, we default to all corners). Wax 0x08.
ImDrawFlags_RoundCornersNone = 1 << 8, // AddRect(), AddRectFilled(), PathRect(): disable rounding on all corners (when rounding > 0.0f). This is NOT zero, NOT an implicit flag!
ImDrawFlags_Closed = 1 << 9, // PathStroke(), AddPolyline(): specify that shape should be closed (Important: this is always == 1 for legacy reason)
// Rounding for AddRect(), AddRectFilled(), PathRect()
// - When not specified, we defaults to ImDrawFlags_RoundCornersAll! So you only need to use those flags if you want another configuration.
ImDrawFlags_RoundCornersTopLeft = 1 << 4, // Round top-left corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersTopRight = 1 << 5, // Round top-right corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersBottomLeft = 1 << 6, // Round bottom-left corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersBottomRight = 1 << 7, // Round bottom-right corner only (when rounding > 0.0f, we default to all corners).
ImDrawFlags_RoundCornersNone = 1 << 8, // Disable rounding even if `float rounding > 0.0f`. This is NOT zero, NOT an implicit flag!
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight, // (Default!!)
ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified!
ImDrawFlags_RoundCornersTop = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight,
ImDrawFlags_RoundCornersBottom = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
ImDrawFlags_RoundCornersLeft = ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersTopLeft,
ImDrawFlags_RoundCornersRight = ImDrawFlags_RoundCornersBottomRight | ImDrawFlags_RoundCornersTopRight,
ImDrawFlags_RoundCornersAll = ImDrawFlags_RoundCornersTopLeft | ImDrawFlags_RoundCornersTopRight | ImDrawFlags_RoundCornersBottomLeft | ImDrawFlags_RoundCornersBottomRight,
ImDrawFlags_RoundCornersDefault_ = ImDrawFlags_RoundCornersAll, // Default to ALL corners if none of the _RoundCornersXX flags are specified.
ImDrawFlags_RoundCornersMask_ = ImDrawFlags_RoundCornersAll | ImDrawFlags_RoundCornersNone,
ImDrawFlags_InvalidMask_ = (ImDrawFlags)0x8000000F,
// Stroke options
ImDrawFlags_Closed = 1 << 9, // PathStroke(), AddPolyline(): specify that shape should be closed.
//ImDrawFlags_Closed = 1, // Prior to 1.92.8 (May 2026), ImDrawFlags_Closed was guaranteed to be == 1<<0 == 1 for legacy compatibility reason. Hardcoded use of 1 or true should be replaced.
ImDrawFlags_InvalidMask_ = ~0x7FFFFFF0, // == 0x8000000F,
};
// Flags for ImDrawList instance. Those are set automatically by ImGui:: functions from ImGuiIO settings, and generally not manipulated directly.
@@ -3270,6 +3312,7 @@ enum ImDrawListFlags_
ImDrawListFlags_AntiAliasedLinesUseTex = 1 << 1, // Enable anti-aliased lines/borders using textures when possible. Require backend to render with bilinear filtering (NOT point/nearest filtering).
ImDrawListFlags_AntiAliasedFill = 1 << 2, // Enable anti-aliased edge around filled shapes (rounded rectangles, circles).
ImDrawListFlags_AllowVtxOffset = 1 << 3, // Can emit 'VtxOffset > 0' to allow large meshes. Set when 'ImGuiBackendFlags_RendererHasVtxOffset' is enabled.
ImDrawListFlags_TextNoPixelSnap = 1 << 4, // Disable automatically snapping AddText() calls to pixel boundaries.
};
// Draw command list
@@ -3421,8 +3464,8 @@ struct ImDrawList
inline void PushTextureID(ImTextureRef tex_ref) { PushTexture(tex_ref); } // RENAMED in 1.92.0
inline void PopTextureID() { PopTexture(); } // RENAMED in 1.92.0
#else
IMGUI_API void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding /*= 0.0f*/, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
IMGUI_API void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) = delete;
void AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding /*= 0.0f*/, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
void AddPolyline(const ImVec2* points, int num_points, ImU32 col, ImDrawFlags flags, float thickness) = delete;
inline void PathStroke(ImU32 col, ImDrawFlags flags /*= 0*/, float thickness /*= 1.0f*/) = delete;
#endif
//inline void AddEllipse(const ImVec2& center, float radius_x, float radius_y, ImU32 col, float rot = 0.0f, int num_segments = 0, float thickness = 1.0f) { AddEllipse(center, ImVec2(radius_x, radius_y), col, rot, num_segments, thickness); } // OBSOLETED in 1.90.5 (Mar 2024)
@@ -3452,7 +3495,7 @@ struct ImDrawList
struct ImDrawData
{
bool Valid; // Only valid after Render() is called and before the next NewFrame() is called.
int CmdListsCount; // == CmdLists.Size. (OBSOLETE: exists for legacy reasons). Number of ImDrawList* to render.
int FrameCount; // Frame counter of the emitter context. Mostly for debugging purpose.
int TotalIdxCount; // For convenience, sum of all ImDrawList's IdxBuffer.Size
int TotalVtxCount; // For convenience, sum of all ImDrawList's VtxBuffer.Size
ImVector<ImDrawList*> CmdLists; // Array of ImDrawList* to render. The ImDrawLists are owned by ImGuiContext and only pointed to from here.
@@ -3462,6 +3505,10 @@ struct ImDrawData
ImGuiViewport* OwnerViewport; // Viewport carrying the ImDrawData instance, might be of use to the renderer (generally not).
ImVector<ImTextureData*>* Textures; // List of textures to update. Most of the times the list is shared by all ImDrawData, has only 1 texture and it doesn't need any update. This almost always points to ImGui::GetPlatformIO().Textures[]. May be overridden or set to NULL if you want to manually update textures.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
int CmdListsCount; // Use CmdLists.Size instead. Number of ImDrawList* to render.
#endif
// Functions
ImDrawData() { Clear(); }
IMGUI_API void Clear();
@@ -3503,7 +3550,7 @@ enum ImTextureStatus
// You may use ImTextureData::Updates[] for the list, or ImTextureData::UpdateBox for a single bounding box.
struct ImTextureRect
{
unsigned short x, y; // Upper-left coordinates of rectangle to update
unsigned short x, y; // Upper-left coordinates of rectangle to update, within the parent Pixels[] array.
unsigned short w, h; // Size of rectangle to update (in pixels)
};
@@ -3513,19 +3560,20 @@ struct ImTextureRect
// Why does we store two identifiers: TexID and BackendUserData?
// - ImTextureID TexID = lower-level identifier stored in ImDrawCmd. ImDrawCmd can refer to textures not created by the backend, and for which there's no ImTextureData.
// - void* BackendUserData = higher-level opaque storage for backend own book-keeping. Some backends may have enough with TexID and not need both.
// In columns below: who reads/writes each fields? 'r'=read, 'w'=write, 'core'=main library, 'backend'=renderer backend
// In columns below: who reads/writes each fields? 'r'=read, 'w'=write, 'core'=main library, 'backend'=renderer backend
struct ImTextureData
{
//------------------------------------------ core / backend ---------------------------------------
int UniqueID; // w - // [DEBUG] Sequential index to facilitate identifying a texture when debugging/printing. Unique per atlas.
ImTextureStatus Status; // rw rw // ImTextureStatus_OK/_WantCreate/_WantUpdates/_WantDestroy. Always use SetStatus() to modify!
void* BackendUserData; // - rw // Convenience storage for backend. Some backends may have enough with TexID.
void* QueueUserData; // r - // Convenience storage for a staged/multi-threaded rendering texture queue (e.g. imgui_threaded_rendering.h. See #8597). When != NULL, core assumes the texture is referenced by the queue.
ImTextureID TexID; // r w // Backend-specific texture identifier. Always use SetTexID() to modify! The identifier will stored in ImDrawCmd::GetTexID() and passed to backend's RenderDrawData function.
ImTextureFormat Format; // w r // ImTextureFormat_RGBA32 (default) or ImTextureFormat_Alpha8
int Width; // w r // Texture width
int Height; // w r // Texture height
int BytesPerPixel; // w r // 4 or 1
unsigned char* Pixels; // w r // Pointer to buffer holding 'Width*Height' pixels and 'Width*Height*BytesPerPixels' bytes.
unsigned char* Pixels; // w r // Pointer to whole texture buffer holding 'Width*Height' pixels and 'Width*Height*BytesPerPixels' bytes.
ImTextureRect UsedRect; // w r // Bounding box encompassing all past and queued Updates[].
ImTextureRect UpdateRect; // w r // Bounding box encompassing all queued Updates[].
ImVector<ImTextureRect> Updates; // w r // Array of individual updates.
@@ -3535,7 +3583,7 @@ struct ImTextureData
bool WantDestroyNextFrame; // rw - // [Internal] Queued to set ImTextureStatus_WantDestroy next frame. May still be used in the current frame.
// Functions
// - If GetPixels() functions asserts while being called by your render loop, it could be caused by calling ImFontAtlas::Clear() instead of ClearFonts()?
// - If GetPixels() functions asserts while being called by your render loop, it could be caused by calling ImFontAtlas::Clear()/ClearFonts()?
ImTextureData() { memset((void*)this, 0, sizeof(*this)); Status = ImTextureStatus_Destroyed; TexID = ImTextureID_Invalid; }
~ImTextureData() { DestroyPixels(); }
IMGUI_API void Create(ImTextureFormat format, int w, int h);
@@ -3690,14 +3738,16 @@ struct ImFontAtlas
IMGUI_API ImFont* AddFontFromMemoryTTF(void* font_data, int font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // Note: Transfer ownership of 'ttf_data' to ImFontAtlas! Will be deleted after destruction of the atlas. Set font_cfg->FontDataOwnedByAtlas=false to keep ownership of your data and it won't be freed.
IMGUI_API ImFont* AddFontFromMemoryCompressedTTF(const void* compressed_font_data, int compressed_font_data_size, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data' still owned by caller. Compress with binary_to_compressed_c.cpp.
IMGUI_API ImFont* AddFontFromMemoryCompressedBase85TTF(const char* compressed_font_data_base85, float size_pixels = 0.0f, const ImFontConfig* font_cfg = NULL, const ImWchar* glyph_ranges = NULL); // 'compressed_font_data_base85' still owned by caller. Compress with binary_to_compressed_c.cpp with -base85 parameter.
IMGUI_API void RemoveFont(ImFont* font);
IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame!
IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. You can call this mid-frame if you load new fonts afterwards!
IMGUI_API void CompactCache(); // Compact cached glyphs and texture.
IMGUI_API void RemoveFont(ImFont* font); // Remove a font
IMGUI_API void CompactCache(); // Compact cached glyphs and texture.
IMGUI_API void SetFontLoader(const ImFontLoader* font_loader); // Change font loader at runtime.
// As we are transitioning toward a new font system, we expect to obsolete those soon:
// Clearing the atlas/fonts has little use nowadays, unless you want to batch remove all fonts.
// - Since 1.92, you can call ClearFonts() mid-frame, if you load new fonts afterwards.
// - As we are transitioning toward our new font system the semantic for those functions gets increasingly misleading and are often a source of issues.
// TL;DR; most likely, don't use any of those functions. We expect to obsolete/rework them.
IMGUI_API void Clear(); // Clear everything (fonts + textures). Don't call mid-frame!
IMGUI_API void ClearFonts(); // Clear input+output font data/glyphs. New fonts and textures will be recreated afterwards.
IMGUI_API void ClearInputData(); // [OBSOLETE] Clear input data (all ImFontConfig structures including sizes, TTF data, glyph ranges, etc.) = all the data used to build the texture and fonts.
IMGUI_API void ClearTexData(); // [OBSOLETE] Clear CPU-side copy of the texture data. Saves RAM once the texture has been copied to graphics memory.
@@ -3885,7 +3935,7 @@ struct ImFont
ImFontAtlas* OwnerAtlas; // 4-8 // What we have been loaded into.
ImFontFlags Flags; // 4 // Font flags.
float CurrentRasterizerDensity; // Current rasterizer density. This is a varying state of the font.
float LineHeight; // 4 // Line Height
float LineHeight; // 4 // [PCSX2 Custom] Line Height
// [Internal] Members: Cold ~24-52 bytes
// Conceptually Sources[] is the list of font sources merged to create this font.
@@ -3917,7 +3967,7 @@ struct ImFont
IMGUI_API void RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, ImWchar c, const ImVec4* cpu_fine_clip = NULL);
IMGUI_API void RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width = 0.0f, ImDrawTextFlags flags = 0);
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, text, text_end, wrap_width); }
inline const char* CalcWordWrapPositionA(float scale, const char* text, const char* text_end, float wrap_width) { return CalcWordWrapPosition(LegacySize * scale, text, text_end, wrap_width); } // Obsoleted old name in 1.92.0. Note how `scale` was to `size`.
#endif
// [Internal] Don't use!
@@ -4019,7 +4069,11 @@ struct ImGuiPlatformIO
// Optional: Platform locale
// [Experimental] Configure decimal point e.g. '.' or ',' useful for some languages (e.g. German), generally pulled from *localeconv()->decimal_point
ImWchar Platform_LocaleDecimalPoint; // '.'
ImWchar Platform_LocaleDecimalPoint; // '.'
// Optional: Platform time/date
// This is automatically filled on startup. Used to store a "last used date" in some .ini structures. Facilitate creating tools to clean up old/unused data.
int Platform_SessionDate; // Integer storing YYYYMMDD e.g. 20261231 corresponding to the beginning of application session.
//------------------------------------------------------------------
// Input - Interface with Renderer Backend
@@ -4075,6 +4129,8 @@ struct ImGuiPlatformImeData
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
namespace ImGui
{
// OBSOLETED in 1.92.9 (from July 2026)
IMGUI_API void SetColorEditOptions(ImGuiColorEditFlags flags); // set current options for if you want to select a default format, picker type, etc. User will be able to change those settings, unless you pass the _NoOptions flag to your calls.
// OBSOLETED in 1.92.0 (from June 2025)
inline void PushFont(ImFont* font) { PushFont(font, font ? font->LegacySize : 0.0f); }
IMGUI_API void SetWindowFontScale(float scale); // Set font scale factor for current window. Prefer using PushFont(NULL, style.FontSizeBase * factor) or use style.FontScaleMain to scale all windows.
+205 -110
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.8
// dear imgui, v1.92.9b
// (internal structures/api)
// You may use this file to debug, understand or extend Dear ImGui features but we don't provide any guarantee of forward compatibility.
@@ -35,7 +35,7 @@ Index of this file:
// [SECTION] ImGuiContext (main imgui context)
// [SECTION] ImGuiWindowTempData, ImGuiWindow
// [SECTION] Tab bar, Tab item support
// [SECTION] Table support
// [SECTION] Table support + internal API
// [SECTION] ImGui internal API
// [SECTION] ImFontLoader
// [SECTION] ImFontAtlas internal API
@@ -98,6 +98,7 @@ Index of this file:
#pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" // warning: implicit conversion from 'xxx' to 'float' may lose precision
#pragma clang diagnostic ignored "-Wmissing-noreturn" // warning: function 'xxx' could be declared with attribute 'noreturn'
#pragma clang diagnostic ignored "-Wdeprecated-enum-enum-conversion"// warning: bitwise operation between different enumeration types ('XXXFlags_' and 'XXXFlagsPrivate_') is deprecated
#pragma clang diagnostic ignored "-Wreserved-identifier" // warning: identifier '_Xxx' is reserved because it starts with '_' followed by a capital letter
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" // warning: 'xxx' is an unsafe pointer used for buffer access
#pragma clang diagnostic ignored "-Wnontrivial-memaccess" // warning: first argument in call to 'memset' is a pointer to non-trivially copyable type
#elif defined(__GNUC__)
@@ -138,6 +139,7 @@ Index of this file:
struct ImBitVector; // Store 1-bit per value
struct ImRect; // An axis-aligned rectangle (2 points)
struct ImGuiTextIndex; // Maintain a line index for a text buffer.
struct ImGuiPackedDate; // A date in YYYYMMDD format packed into 16-bits
// ImDrawList/ImFontAtlas
struct ImDrawDataBuilder; // Helper to build a ImDrawData instance
@@ -247,6 +249,7 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
#define IMGUI_DEBUG_LOG_POPUP(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventPopup) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_NAV(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventNav) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_SELECTION(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_TABLE(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventTable) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_CLIPPER(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventClipper) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_IO(...) do { if (g.DebugLogFlags & ImGuiDebugLogFlags_EventIO) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0)
#define IMGUI_DEBUG_LOG_FONT(...) do { ImGuiContext* g2 = GImGui; if (g2 && g2->DebugLogFlags & ImGuiDebugLogFlags_EventFont) IMGUI_DEBUG_LOG(__VA_ARGS__); } while (0) // Called from ImFontAtlas function which may operate without a context.
@@ -321,6 +324,8 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xde01")
#elif defined(__GNUC__) && defined(__arm__) && !defined(__thumb__)
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xe7f001f0")
#elif defined(__GNUC__) && defined(__aarch64__)
#define IM_DEBUG_BREAK() __asm__ volatile(".inst 0xd4200000") // GDB needs 'set $pc=($pc+4)' to skip this :(
#else
#define IM_DEBUG_BREAK() IM_ASSERT(0) // It is expected that you define IM_DEBUG_BREAK() into something that will break nicely in a debugger!
#endif
@@ -531,6 +536,7 @@ inline float ImFloor(float f) { return
inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); }
inline float ImTrunc64(float f) { return (float)(ImS64)(f); }
inline float ImRound64(float f) { return (float)(ImS64)(f + 0.5f); } // FIXME: Positive values only.
inline float ImCeilFast(float f) { int i = (int)f; return (float)(i + (f > (float)i)); } // Consider using the the bit-hack version (search for "0x1p120f").
inline int ImModPositive(int a, int b) { return (a + b) % b; }
inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
inline ImVec2 ImRotate(const ImVec2& v, float cos_a, float sin_a) { return ImVec2(v.x * cos_a - v.y * sin_a, v.x * sin_a + v.y * cos_a); }
@@ -688,6 +694,8 @@ struct ImSpan
inline void set(T* data, int size) { Data = data; DataEnd = data + size; }
inline void set(T* data, T* data_end) { Data = data; DataEnd = data_end; }
inline void clear() { Data = DataEnd = NULL; }
inline bool empty() const { return Data == DataEnd; }
inline int size() const { return (int)(ptrdiff_t)(DataEnd - Data); }
inline int size_in_bytes() const { return (int)(ptrdiff_t)(DataEnd - Data) * (int)sizeof(T); }
inline T& operator[](int i) { T* p = Data + i; IM_ASSERT(p >= Data && p < DataEnd); return *p; }
@@ -827,6 +835,22 @@ struct ImGuiTextIndex
void append(const char* base, int old_size, int new_size);
};
// Helper: ImGuiPackedDate (sizeof() == 2)
// Store a date in a way that is efficient to read/write in text form. If we stored e.g. number of days since Epoch we'd need costlier back and forth.
// This is specifically designed to be able to prune old .ini data.
struct ImGuiPackedDate
{
ImU16 Year : 7; // Year since 2000 // We can change to another offset e.g. 1970 but this is easier to watch in debugger.
ImU16 Month : 4; // Month (1-12)
ImU16 Day : 5; // Day (1-31)
ImGuiPackedDate() { Year = Month = Day = 0; }
ImGuiPackedDate(int yyyymmdd) { Year = (ImU16)((yyyymmdd / 10000) - 2000); Month = (ImU16)((yyyymmdd / 100) % 100); Day = (ImU16)(yyyymmdd % 100); } // Pack
bool IsValid() { return (Year && Month && Day); }
int Unpack() const { return (Year && Month && Day) ? ((Year + 2000) * 10000) + (Month * 100) + Day : 0; } // Unpack
void SubtractMonths(int m) { while (m > 0) { Year -= Month == 1; Month = (Month == 1) ? 12 : Month - 1; m--; } } // FIXME-OPT: Stupid but enough for what we do with it.
};
// Helper: ImGuiStorage
IMGUI_API ImGuiStoragePair* ImLowerBound(ImGuiStoragePair* in_begin, ImGuiStoragePair* in_end, ImGuiID key);
@@ -872,7 +896,7 @@ struct IMGUI_API ImDrawListSharedData
float FontSize; // Current font size (used for for simplified AddText overload)
float FontScale; // Current font scale (== FontSize / Font->FontSize)
float CurveTessellationTol; // Tessellation tolerance when using PathBezierCurveTo()
float CircleSegmentMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
float CircleTessellationMaxError; // Number of circle segments to use per pixel of radius for AddCircle() etc
float InitialFringeScale; // Initial scale to apply to AA fringe
ImDrawListFlags InitialFlags; // Initial flags at the beginning of the frame (it is possible to alter flags on a per-drawlist basis afterwards)
ImVec4 ClipRectFullscreen; // Value for PushClipRectFullscreen()
@@ -982,7 +1006,7 @@ enum ImGuiItemFlagsPrivate_
ImGuiItemFlags_HasSelectionUserData = 1 << 21, // false // Set by SetNextItemSelectionUserData()
ImGuiItemFlags_IsMultiSelect = 1 << 22, // false // Set by SetNextItemSelectionUserData()
ImGuiItemFlags_Default_ = ImGuiItemFlags_AutoClosePopups, // Please don't change, use PushItemFlag() instead.
ImGuiItemFlags_Default_ = ImGuiItemFlags_AutoClosePopups | ImGuiItemFlags_LiveEditOnInputText, // Please don't change, use PushItemFlag() instead.
// Obsolete
//ImGuiItemFlags_SelectableDontClosePopup = !ImGuiItemFlags_AutoClosePopups, // Can't have a redirect as we inverted the behavior
@@ -1185,7 +1209,7 @@ struct IMGUI_API ImGuiGroupData
ImVec2 BackupCurrLineSize;
float BackupCurrLineTextBaseOffset;
ImGuiID BackupActiveIdIsAlive;
bool BackupActiveIdHasBeenEditedThisFrame;
bool BackupAnyIdHasBeenEditedThisFrame;
bool BackupDeactivatedIdIsAlive;
bool BackupHoveredIdIsAlive;
bool BackupIsSameLine;
@@ -1215,10 +1239,11 @@ struct IMGUI_API ImGuiMenuColumns
struct IMGUI_API ImGuiInputTextDeactivatedState
{
ImGuiID ID; // widget id owning the text state (which just got deactivated)
int ElapseFrame;
ImVector<char> TextA; // text buffer
ImGuiInputTextDeactivatedState() { memset((void*)this, 0, sizeof(*this)); }
void ClearFreeMemory() { ID = 0; TextA.clear(); }
void ClearFreeMemory() { ID = 0; ElapseFrame = 0; TextA.clear(); }
};
// Forward declare imstb_textedit.h structure + make its main configuration define accessible
@@ -1240,6 +1265,7 @@ struct IMGUI_API ImGuiInputTextState
ImStbTexteditState* Stb; // State for stb_textedit.h
ImGuiInputTextFlags Flags; // copy of InputText() flags. may be used to check if e.g. ImGuiInputTextFlags_Password is set.
ImGuiID ID; // widget id owning the text state
//int LastFrameActive; // Last used frame-count (unused)
int TextLen; // UTF-8 length of the string in TextA (in bytes)
const char* TextSrc; // == TextA.Data unless read-only, in which case == buf passed to InputText(). For _ReadOnly fields, pointer will be null outside the InputText() call.
ImVector<char> TextA; // main UTF8 buffer. TextA.Size is a buffer size! Should always be >= buf_size passed by user (and of course >= CurLenA + 1).
@@ -1363,7 +1389,7 @@ enum ImGuiNextItemDataFlags_
struct ImGuiNextItemData
{
ImGuiNextItemDataFlags HasFlags; // Called HasFlags instead of Flags to avoid mistaking this
ImGuiItemFlags ItemFlags; // Currently only tested/used for ImGuiItemFlags_AllowOverlap and ImGuiItemFlags_HasSelectionUserData.
ImGuiItemFlags ItemFlagsSet; // Currently only tested/used for ImGuiItemFlags_AllowOverlap and ImGuiItemFlags_HasSelectionUserData.
// Members below are NOT cleared by ItemAdd() meaning they are still valid during e.g. NavProcessItem(). Always rely on HasFlags.
ImGuiID FocusScopeId; // Set by SetNextItemSelectionUserData()
@@ -1378,7 +1404,7 @@ struct ImGuiNextItemData
ImU32 ColorMarker; // Set by SetNextItemColorMarker(). Not exposed yet, supported by DragScalar,SliderScalar and for ImGuiSliderFlags_ColorMarkers.
ImGuiNextItemData() { memset((void*)this, 0, sizeof(*this)); SelectionUserData = -1; }
inline void ClearFlags() { HasFlags = ImGuiNextItemDataFlags_None; ItemFlags = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
inline void ClearFlags() { HasFlags = ImGuiNextItemDataFlags_None; ItemFlagsSet = ImGuiItemFlags_None; } // Also cleared manually by ItemAdd()!
};
// Status storage for the last submitted item
@@ -1702,6 +1728,7 @@ enum ImGuiActivateFlags_
};
// Early work-in-progress API for ScrollToItem()
// FIXME: Missing flags to request making both edges visible when possible.
enum ImGuiScrollFlags_
{
ImGuiScrollFlags_None = 0,
@@ -1721,8 +1748,8 @@ enum ImGuiNavRenderCursorFlags_
ImGuiNavRenderCursorFlags_None = 0,
ImGuiNavRenderCursorFlags_Compact = 1 << 1, // Compact highlight, no padding/distance from focused item
ImGuiNavRenderCursorFlags_AlwaysDraw = 1 << 2, // Draw rectangular highlight if (g.NavId == id) even when g.NavCursorVisible == false, aka even when using the mouse.
ImGuiNavRenderCursorFlags_NoRounding = 1 << 3,
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
ImGuiNavRenderCursorFlags_NoRounding = 1 << 3,
ImGuiNavHighlightFlags_None = ImGuiNavRenderCursorFlags_None, // Renamed in 1.91.4
ImGuiNavHighlightFlags_Compact = ImGuiNavRenderCursorFlags_Compact, // Renamed in 1.91.4
ImGuiNavHighlightFlags_AlwaysDraw = ImGuiNavRenderCursorFlags_AlwaysDraw, // Renamed in 1.91.4
@@ -1933,6 +1960,7 @@ struct IMGUI_API ImGuiMultiSelectTempData
bool NavIdPassedBy;
bool RangeSrcPassedBy; // Set by the item that matches RangeSrcItem.
bool RangeDstPassedBy; // Set by the item that matches NavJustMovedToId when IsSetRange is set.
bool IsSoleOrUnknownSelectionSize;
ImGuiMultiSelectTempData() { Clear(); }
void Clear() { size_t io_sz = sizeof(IO); ClearIO(); memset((void*)(&IO + 1), 0, sizeof(*this) - io_sz); } // Zero-clear except IO as we preserve IO.Requests[] buffer allocation.
@@ -2007,18 +2035,30 @@ struct ImGuiViewportP : public ImGuiViewport
// (this is designed to be stored in a ImChunkStream buffer, with the variable-length Name following our structure)
struct ImGuiWindowSettings
{
ImGuiID ID;
ImVec2ih Pos;
ImVec2ih Size;
bool Collapsed;
bool IsChild;
bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
bool WantDelete; // Set to invalidate/delete the settings entry
ImGuiID ID;
ImVec2ih Pos;
ImVec2ih Size;
ImGuiPackedDate LastUsedDate;
bool Collapsed : 1;
bool IsChild : 1;
bool WantApply : 1; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
bool WantDelete : 1; // Set to invalidate/delete the settings entry
ImGuiWindowSettings() { memset((void*)this, 0, sizeof(*this)); }
char* GetName() { return (char*)(this + 1); }
};
struct ImGuiSettingsCleanupArgs
{
ImGuiID TypeHashFilter = 0; // Set to restrict cleanup to a given .ini type, e.g. == ImHashStr("Window"), ImHashStr("Table"). Otherwise every types supporting Cleanup will be affected.
int DiscardOlderThanMonths = 0; // Enable to discard entries older than XX months.
bool DiscardWhenMissingDate = false; // Enable to discard entries missing a date.
bool DiscardAll = false; // Enable to discard all entries = same as calling ClearIniSettings() except it may be filtered.
bool SetCurrentSessionDateToAll = false; // Enable to write current SessionDate to all supporting entries. // Let us know in #9460 if you use this.
bool SetCurrentSessionDateWhenMissingDate = false; // Enable to write current SessionDate to all supporting entries missing a date. // Let us know in #9460 if you use this.
int _DiscardOlderThanDate = 0; // [Internal]
};
struct ImGuiSettingsHandler
{
const char* TypeName; // Short description stored in .ini file. Disallowed characters: '[' ']'
@@ -2029,6 +2069,7 @@ struct ImGuiSettingsHandler
void (*ReadLineFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, void* entry, const char* line); // Read: Called for every line of text within an ini entry
void (*ApplyAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler); // Read: Called after reading (in registration order)
void (*WriteAllFn)(ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiTextBuffer* out_buf); // Write: Output every entries into 'out_buf'
void (*CleanupFn) (ImGuiContext* ctx, ImGuiSettingsHandler* handler, ImGuiSettingsCleanupArgs* args);// Cleanup/patch settings
void* UserData;
ImGuiSettingsHandler() { memset((void*)this, 0, sizeof(*this)); }
@@ -2045,7 +2086,10 @@ enum ImGuiLocKey : int
ImGuiLocKey_TableSizeOne,
ImGuiLocKey_TableSizeAllFit,
ImGuiLocKey_TableSizeAllDefault,
ImGuiLocKey_TableReset,
//ImGuiLocKey_TableResetAll,
ImGuiLocKey_TableResetOrder,
ImGuiLocKey_TableResetVisibility,
ImGuiLocKey_WindowingMainMenuBar,
ImGuiLocKey_WindowingPopup,
ImGuiLocKey_WindowingUntitled,
@@ -2099,8 +2143,9 @@ enum ImGuiDebugLogFlags_
ImGuiDebugLogFlags_EventInputRouting = 1 << 9,
ImGuiDebugLogFlags_EventDocking = 1 << 10, // Unused in this branch
ImGuiDebugLogFlags_EventViewport = 1 << 11, // Unused in this branch
ImGuiDebugLogFlags_EventTable = 1 << 12,
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventFont | ImGuiDebugLogFlags_EventInputRouting | ImGuiDebugLogFlags_EventDocking | ImGuiDebugLogFlags_EventViewport,
ImGuiDebugLogFlags_EventMask_ = ImGuiDebugLogFlags_EventError | ImGuiDebugLogFlags_EventActiveId | ImGuiDebugLogFlags_EventFocus | ImGuiDebugLogFlags_EventPopup | ImGuiDebugLogFlags_EventNav | ImGuiDebugLogFlags_EventClipper | ImGuiDebugLogFlags_EventSelection | ImGuiDebugLogFlags_EventTable | ImGuiDebugLogFlags_EventIO | ImGuiDebugLogFlags_EventFont | ImGuiDebugLogFlags_EventInputRouting | ImGuiDebugLogFlags_EventDocking | ImGuiDebugLogFlags_EventViewport,
ImGuiDebugLogFlags_OutputToTTY = 1 << 20, // Also send output to TTY
ImGuiDebugLogFlags_OutputToDebugger = 1 << 21, // Also send output to Debugger Console [Windows only]
ImGuiDebugLogFlags_OutputToTestEngine = 1 << 22, // Also send output to Dear ImGui Test Engine
@@ -2138,6 +2183,8 @@ struct ImGuiMetricsConfig
int ShowTablesRectsType = -1;
int HighlightMonitorIdx = -1;
ImGuiID HighlightViewportID = 0;
int SettingsDiscardMonths = 6;
bool SettingsHighlightOldEntries = false;
bool ShowFontPreview = true;
};
@@ -2266,10 +2313,13 @@ struct ImGuiContext
bool HoveredIdAllowOverlap;
bool HoveredIdIsDisabled; // At least one widget passed the rect test, but has been discarded by disabled flag or popup inhibit. May be true even if HoveredId == 0.
bool ItemUnclipByLog; // Disable ItemAdd() clipping, essentially a memory-locality friendly copy of LogEnabled
bool AnyIdHasBeenEditedThisFrame;
ImGuiID ActiveId; // Active widget
ImGuiID ActiveIdIsAlive; // Active widget has been seen this frame (we can't use a bool as the ActiveId may change within the frame)
float ActiveIdTimer;
bool ActiveIdIsJustActivated; // Set at the time of activation for one frame
bool ActiveIdWasSelected; // Active ID was selected at the time of activating
bool ActiveIdWasSoleSelected; // Active ID was sole selection at the time of activating
bool ActiveIdAllowOverlap; // Active widget allows another widget to steal active id (generally for overlapping widgets, but not always)
bool ActiveIdNoClearOnFocusLoss; // Disable losing active id if the active id window gets unfocused.
bool ActiveIdHasBeenPressedBefore; // Track whether the active id led to a press (this is to allow changing between PressOnClick and PressOnRelease without pressing twice). Used by range_select branch.
@@ -2286,6 +2336,8 @@ struct ImGuiContext
ImGuiDataTypeStorage ActiveIdValueOnActivation; // Backup of initial value at the time of activation. ONLY SET BY SPECIFIC WIDGETS: DragXXX and SliderXXX.
ImGuiID LastActiveId; // Store the last non-zero ActiveId, useful for animation.
float LastActiveIdTimer; // Store the last non-zero ActiveId timer since the beginning of activation, useful for animation.
bool LastActiveIdWasSelected;
bool LastActiveIdWasSoleSelected;
// Key/Input Ownership + Shortcut Routing system
// - The idea is that instead of "eating" a given key, we can link to an owner.
@@ -2482,7 +2534,6 @@ struct ImGuiContext
ImGuiDataTypeStorage DataTypeZeroValue; // 0 for all data types
int BeginMenuDepth;
int BeginComboDepth;
ImGuiColorEditFlags ColorEditOptions; // Store user options for color edit widgets
ImGuiID ColorEditCurrentID; // Set temporarily while inside of the parent-most ColorEdit4/ColorPicker4 (because they call each others).
ImGuiID ColorEditSavedID; // ID we are saving/restoring HS for
float ColorEditSavedHue; // Backup of last Hue associated to LastColor, so we can restore Hue in lossy RGB<>HSV round trips
@@ -2517,6 +2568,7 @@ struct ImGuiContext
ImVector<ImTextureData*> UserTextures; // List of textures created/managed by user or third-party extension. Automatically appended into platform_io.Textures[].
// Settings
ImGuiPackedDate SessionDate; // Packed copy of platform_io.Platform_SessionDate, when valid.
bool SettingsLoaded;
float SettingsDirtyTimer; // Save .ini Settings to memory when time reaches zero
ImGuiTextBuffer SettingsIniData; // In memory .ini settings
@@ -2876,13 +2928,13 @@ struct IMGUI_API ImGuiTabBar
};
//-----------------------------------------------------------------------------
// [SECTION] Table support
// [SECTION] Table support + internal API
//-----------------------------------------------------------------------------
#define IM_COL32_DISABLE IM_COL32(0,0,0,1) // Special sentinel code which cannot be used as a regular color.
#define IMGUI_TABLE_MAX_COLUMNS 512 // Arbitrary "safety" maximum, may be lifted in the future if needed. Must fit in ImGuiTableColumnIdx/ImGuiTableDrawChannelIdx.
// [Internal] sizeof() ~ 112
// [Internal] sizeof() ~ 120
// We use the terminology "Enabled" to refer to a column that is not Hidden by user/api.
// We use the terminology "Clipped" to refer to a column that is out of sight because of scrolling/clipping.
// This is in contrast with some user-facing api such as IsItemVisible() / IsRectVisible() which use "Visible" to mean "not clipped".
@@ -2898,7 +2950,8 @@ struct ImGuiTableColumn
float StretchWeight; // Master width weight when (Flags & _WidthStretch). Often around ~1.0f initially.
float InitStretchWeightOrWidth; // Value passed to TableSetupColumn(). For Width it is a content width (_without padding_).
ImRect ClipRect; // Clipping rectangle for the column
ImGuiID UserID; // Optional, value passed to TableSetupColumn()
ImGuiID ID; // Hash of column name (ignoring top of ID stack), used for .ini persistence when available.
ImGuiID UserData; // (Optional) User data value passed to TableSetupColumn()
float WorkMinX; // Contents region min ~(MinX + CellPaddingX + CellSpacingX1) == cursor start position when entering column
float WorkMaxX; // Contents region max ~(MaxX - CellPaddingX - CellSpacingX2)
float ItemWidth; // Current item width for the column, preserved across rows
@@ -2922,10 +2975,14 @@ struct ImGuiTableColumn
bool IsVisibleY;
bool IsRequestOutput; // Return value for TableSetColumnIndex() / TableNextColumn(): whether we request user to output contents or not.
bool IsSkipItems; // Do we want item submissions to this column to be completely ignored (no layout will happen).
bool IsPreserveWidthAuto;
bool IsPreserveWidthAuto : 1;
bool IsJustCreated : 1;
bool IsLoadedSettings : 1;
bool IsNeedReconcileSrc : 1;
bool IsNeedReconcileDst : 1;
ImS8 NavLayerCurrent; // ImGuiNavLayer in 1 byte
ImU8 AutoFitQueue; // Queue of 8 values for the next 8 frames to request auto-fit
ImU8 CannotSkipItemsQueue; // Queue of 8 values for the next 8 frames to disable Clipped/SkipItem
ImU8 AutoFitQueue : 4; // Queue of 4 values for the next 4 frames to request auto-fit
ImU8 CannotSkipItemsQueue : 4; // Queue of 4 values for the next 4 frames to disable Clipped/SkipItem
ImU8 SortDirection : 2; // ImGuiSortDirection_Ascending or ImGuiSortDirection_Descending
ImU8 SortDirectionsAvailCount : 2; // Number of available sort directions (0 to 3)
ImU8 SortDirectionsAvailMask : 4; // Mask of available sort directions (1-bit each)
@@ -2940,10 +2997,28 @@ struct ImGuiTableColumn
PrevEnabledColumn = NextEnabledColumn = -1;
SortOrder = -1;
SortDirection = ImGuiSortDirection_None;
IsJustCreated = true;
DrawChannelCurrent = DrawChannelFrozen = DrawChannelUnfrozen = (ImU8)-1;
}
};
// Passed to TableSetupColumn()
// sizeof() ~ 24+120 bytes
struct ImGuiTableReconcileColumnData
{
// Setup data
ImGuiID ID;
ImS16 NameOffset;
ImGuiTableColumnFlags Flags;
float InitWidthOrWeight;
ImGuiID UserData;
// Reconcile data
ImGuiTableColumnIdx ColumnNewIdx; // Index in the current table.
ImGuiTableColumnIdx ColumnOldIdx; // Index in the previous frame table.
ImGuiTableColumn ColumnOldData; // Full backup of the column. Could be avoided by storing 1 of them and applying reconcile in the right order. Not worth bothering.
};
// Transient cell data stored per row.
// sizeof() ~ 6 bytes
struct ImGuiTableCellData
@@ -3077,6 +3152,7 @@ struct IMGUI_API ImGuiTable
bool IsLayoutLocked; // Set by TableUpdateLayout() which is called when beginning the first row.
bool IsInsideRow; // Set when inside TableBeginRow()/TableEndRow().
bool IsInitializing;
bool IsReconcileMode;
bool IsSortSpecsDirty;
bool IsUsingHeaders; // Set when the first row had the ImGuiTableRowFlags_Headers flag.
bool IsContextPopupOpen; // Set when default context menu is open (also see: ContextPopupColumn, InstanceInteracted).
@@ -3084,8 +3160,10 @@ struct IMGUI_API ImGuiTable
bool IsSettingsRequestLoad;
bool IsSettingsDirty; // Set when table settings have changed and needs to be reported into ImGuiTableSettings data.
bool IsDefaultDisplayOrder; // Set when display order is unchanged from default (DisplayOrder contains 0...Count-1)
bool IsResetAllRequest;
bool IsDefaultVisibility; // Set when enabled/visibility is unchanged from default
bool IsResetAllRequest; // Set to queue a call to TableResetSettings() in BeginTable()
bool IsResetDisplayOrderRequest;
bool IsResetVisibilityRequest;
bool IsUnfrozenRows; // Set when we got past the frozen row.
bool IsDefaultSizingPolicy; // Set if user didn't explicitly set a sizing policy in BeginTable()
bool IsActiveIdAliveBeforeTable;
@@ -3103,14 +3181,19 @@ struct IMGUI_API ImGuiTable
// - Accessing those requires chasing an extra pointer so for very frequently used data we leave them in the main table structure.
// - We also leave out of this structure data that tend to be particularly useful for debugging/metrics.
// FIXME-TABLE: more transient data could be stored in a stacked ImGuiTableTempData: e.g. SortSpecs.
// sizeof() ~ 136 bytes.
// sizeof() ~ 176 bytes.
struct IMGUI_API ImGuiTableTempData
{
ImGuiID WindowID; // Shortcut to g.Tables[TableIndex]->OuterWindow->ID.
int TableIndex; // Index in g.Tables.Buf[] pool
float LastTimeActive; // Last timestamp this structure was used
float AngledHeadersExtraWidth; // Used in EndTable()
ImVector<ImGuiTableHeaderData> AngledHeadersRequests; // Used in TableAngledHeadersRow()
ImVector<ImGuiTableHeaderData> AngledHeadersRequests; // Used in TableAngledHeadersRow() // FIXME: Single instance is enough?
// Topology change
ImVector<ImGuiTableReconcileColumnData> ReconcileColumnsRequests; // Used in TableSetupColumn(), TableUpdateLayout(). Cleared every frame.
void* OldColumnsRawData; // Used in BeginTable() -> TableUpdateLayout() when resizing.
ImSpan<ImGuiTableColumn> OldColumnsData;
ImVec2 UserOuterSize; // outer_size.x passed to BeginTable()
ImDrawListSplitter DrawSplitter;
@@ -3131,23 +3214,25 @@ struct IMGUI_API ImGuiTableTempData
struct ImGuiTableColumnSettings
{
float WidthOrWeight;
ImGuiID UserID;
ImGuiID ID;
ImGuiTableColumnIdx Index;
ImGuiTableColumnIdx DisplayOrder;
ImGuiTableColumnIdx SortOrder;
ImU8 SortDirection : 2;
ImS8 IsEnabled : 2; // "Visible" in ini file
ImS8 IsEnabled : 2; // "Visible" in .ini file
ImU8 IsStretch : 1;
bool IsLoaded : 1; // Using during loading to mark finding a matching column.
ImGuiTableColumnSettings()
{
WidthOrWeight = 0.0f;
UserID = 0;
ID = 0;
Index = -1;
DisplayOrder = SortOrder = -1;
SortDirection = ImGuiSortDirection_None;
IsEnabled = -1;
IsStretch = 0;
IsLoaded = false;
}
};
@@ -3159,12 +3244,94 @@ struct ImGuiTableSettings
float RefScale; // Reference scale to be able to rescale columns on font/dpi changes.
ImGuiTableColumnIdx ColumnsCount;
ImGuiTableColumnIdx ColumnsCountMax; // Maximum number of columns this settings instance can store, we can recycle a settings instance with lower number of columns but not higher
bool WantApply; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
ImGuiPackedDate LastUsedDate;
bool WantApply : 1; // Set when loaded from .ini data (to enable merging/loading .ini data into an already running context)
ImGuiTableSettings() { memset((void*)this, 0, sizeof(*this)); }
ImGuiTableColumnSettings* GetColumnSettings() { return (ImGuiTableColumnSettings*)(this + 1); }
};
namespace ImGui
{
// Tables: Candidates for public API
IMGUI_API void TableOpenContextMenu(int column_n = -1);
IMGUI_API void TableSetColumnWidth(int column_n, float width);
IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs);
IMGUI_API int TableGetHoveredRow(); // Retrieve *PREVIOUS FRAME* hovered row. This difference with TableGetHoveredColumn() is the reason why this is not public yet.
IMGUI_API float TableGetHeaderRowHeight();
IMGUI_API float TableGetHeaderAngledMaxLabelWidth();
IMGUI_API void TablePushBackgroundChannel();
IMGUI_API void TablePopBackgroundChannel();
IMGUI_API void TablePushColumnChannel(int column_n);
IMGUI_API void TablePopColumnChannel();
IMGUI_API void TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label_width, const ImGuiTableHeaderData* data, int data_count);
// Tables: Internals
inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; }
IMGUI_API ImGuiTable* TableFindByID(ImGuiID id);
IMGUI_API bool BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f);
IMGUI_API void TableBeginInitMemory(ImGuiTable* table, int columns_count);
IMGUI_API void TableApplyQueuedRequests(ImGuiTable* table);
IMGUI_API void TableSetupDrawChannels(ImGuiTable* table);
IMGUI_API void TableReconcileColumns(ImGuiTable* table);
IMGUI_API void TableUpdateLayout(ImGuiTable* table);
IMGUI_API void TableUpdateBorders(ImGuiTable* table);
IMGUI_API void TableUpdateColumnsWeightFromWidth(ImGuiTable* table);
IMGUI_API void TableApplyExternalUnclipRect(ImGuiTable* table, ImRect& rect);
IMGUI_API void TableDrawBorders(ImGuiTable* table);
IMGUI_API void TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags_for_section_to_display);
IMGUI_API bool TableBeginContextMenuPopup(ImGuiTable* table);
IMGUI_API void TableMergeDrawChannels(ImGuiTable* table);
inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; }
inline ImGuiID TableGetInstanceID(ImGuiTable* table, int instance_no) { return TableGetInstanceData(table, instance_no)->TableInstanceID; }
IMGUI_API void TableFixDisplayOrder(ImGuiTable* table);
IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table);
IMGUI_API void TableSortSpecsBuild(ImGuiTable* table);
IMGUI_API void TableInitColumnDefaults(ImGuiTable* table, ImGuiTableColumn* column, ImGuiTableColumnFlags init_mask);
IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column);
IMGUI_API void TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column);
IMGUI_API float TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column);
IMGUI_API void TableBeginRow(ImGuiTable* table);
IMGUI_API void TableEndRow(ImGuiTable* table);
IMGUI_API void TableBeginCell(ImGuiTable* table, int column_n);
IMGUI_API void TableEndCell(ImGuiTable* table);
IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n);
IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n);
IMGUI_API ImGuiID TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no = 0);
IMGUI_API float TableCalcMaxColumnWidth(const ImGuiTable* table, int column_n);
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
IMGUI_API void TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
IMGUI_API void TableQueueSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
IMGUI_API void TableRemove(ImGuiTable* table);
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table);
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table);
IMGUI_API void TableGcCompactSettings();
// Tables: Settings
IMGUI_API void TableLoadSettings(ImGuiTable* table);
IMGUI_API void TableLoadSettingsForColumns(ImGuiTable* table);
IMGUI_API void TableLoadSettingsForColumn(ImGuiTableColumn* column, ImGuiTableColumnSettings* column_settings, ImGuiTableFlags load_flags);
IMGUI_API void TableSaveSettings(ImGuiTable* table);
IMGUI_API void TableResetSettings(ImGuiTable* table);
IMGUI_API ImGuiTableSettings* TableGetBoundSettings(ImGuiTable* table);
IMGUI_API void TableSettingsAddSettingsHandler();
IMGUI_API ImGuiTableSettings* TableSettingsCreate(ImGuiID id, int columns_count);
IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id);
// Legacy Columns API (this is not exposed because we will encourage transitioning to the Tables API)
IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect);
IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
IMGUI_API void EndColumns(); // close columns
IMGUI_API void PushColumnClipRect(int column_index);
IMGUI_API void PushColumnsBackground();
IMGUI_API void PopColumnsBackground();
IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count);
IMGUI_API ImGuiOldColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id);
IMGUI_API float GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm);
IMGUI_API float GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset);
}
//-----------------------------------------------------------------------------
// [SECTION] ImGui internal API
// No guarantee of forward compatibility here!
@@ -3262,6 +3429,7 @@ namespace ImGui
IMGUI_API void MarkIniSettingsDirty();
IMGUI_API void MarkIniSettingsDirty(ImGuiWindow* window);
IMGUI_API void ClearIniSettings();
IMGUI_API void CleanupIniSettings(ImGuiSettingsCleanupArgs* args); // [BETA] Expected to turn into a public API. Please report if you are using this!
IMGUI_API void AddSettingsHandler(const ImGuiSettingsHandler* handler);
IMGUI_API void RemoveSettingsHandler(const char* type_name);
IMGUI_API ImGuiSettingsHandler* FindSettingsHandler(const char* type_name);
@@ -3337,7 +3505,7 @@ namespace ImGui
// Popups, Modals
IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags);
IMGUI_API bool BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags extra_window_flags);
IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None);
IMGUI_API bool OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None);
IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup);
IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup);
IMGUI_API void ClosePopupsExceptModals();
@@ -3512,86 +3680,12 @@ namespace ImGui
// Multi-Select API
IMGUI_API void MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags* p_button_flags);
IMGUI_API void MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed);
IMGUI_API void MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed, ImGuiMultiSelectFlags extra_flags = 0);
IMGUI_API void MultiSelectAddSetAll(ImGuiMultiSelectTempData* ms, bool selected);
IMGUI_API void MultiSelectAddSetRange(ImGuiMultiSelectTempData* ms, bool selected, int range_dir, ImGuiSelectionUserData first_item, ImGuiSelectionUserData last_item);
inline ImGuiBoxSelectState* GetBoxSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.BoxSelectState.ID == id && g.BoxSelectState.IsActive) ? &g.BoxSelectState : NULL; }
inline ImGuiMultiSelectState* GetMultiSelectState(ImGuiID id) { ImGuiContext& g = *GImGui; return g.MultiSelectStorage.GetByKey(id); }
// Internal Columns API (this is not exposed because we will encourage transitioning to the Tables API)
IMGUI_API void SetWindowClipRectBeforeSetChannel(ImGuiWindow* window, const ImRect& clip_rect);
IMGUI_API void BeginColumns(const char* str_id, int count, ImGuiOldColumnFlags flags = 0); // setup number of columns. use an identifier to distinguish multiple column sets. close with EndColumns().
IMGUI_API void EndColumns(); // close columns
IMGUI_API void PushColumnClipRect(int column_index);
IMGUI_API void PushColumnsBackground();
IMGUI_API void PopColumnsBackground();
IMGUI_API ImGuiID GetColumnsID(const char* str_id, int count);
IMGUI_API ImGuiOldColumns* FindOrCreateColumns(ImGuiWindow* window, ImGuiID id);
IMGUI_API float GetColumnOffsetFromNorm(const ImGuiOldColumns* columns, float offset_norm);
IMGUI_API float GetColumnNormFromOffset(const ImGuiOldColumns* columns, float offset);
// Tables: Candidates for public API
IMGUI_API void TableOpenContextMenu(int column_n = -1);
IMGUI_API void TableSetColumnWidth(int column_n, float width);
IMGUI_API void TableSetColumnSortDirection(int column_n, ImGuiSortDirection sort_direction, bool append_to_sort_specs);
IMGUI_API int TableGetHoveredRow(); // Retrieve *PREVIOUS FRAME* hovered row. This difference with TableGetHoveredColumn() is the reason why this is not public yet.
IMGUI_API float TableGetHeaderRowHeight();
IMGUI_API float TableGetHeaderAngledMaxLabelWidth();
IMGUI_API void TablePushBackgroundChannel();
IMGUI_API void TablePopBackgroundChannel();
IMGUI_API void TablePushColumnChannel(int column_n);
IMGUI_API void TablePopColumnChannel();
IMGUI_API void TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label_width, const ImGuiTableHeaderData* data, int data_count);
// Tables: Internals
inline ImGuiTable* GetCurrentTable() { ImGuiContext& g = *GImGui; return g.CurrentTable; }
IMGUI_API ImGuiTable* TableFindByID(ImGuiID id);
IMGUI_API bool BeginTableEx(const char* name, ImGuiID id, int columns_count, ImGuiTableFlags flags = 0, const ImVec2& outer_size = ImVec2(0, 0), float inner_width = 0.0f);
IMGUI_API void TableBeginInitMemory(ImGuiTable* table, int columns_count);
IMGUI_API void TableBeginApplyRequests(ImGuiTable* table);
IMGUI_API void TableSetupDrawChannels(ImGuiTable* table);
IMGUI_API void TableUpdateLayout(ImGuiTable* table);
IMGUI_API void TableUpdateBorders(ImGuiTable* table);
IMGUI_API void TableUpdateColumnsWeightFromWidth(ImGuiTable* table);
IMGUI_API void TableApplyExternalUnclipRect(ImGuiTable* table, ImRect& rect);
IMGUI_API void TableDrawBorders(ImGuiTable* table);
IMGUI_API void TableDrawDefaultContextMenu(ImGuiTable* table, ImGuiTableFlags flags_for_section_to_display);
IMGUI_API bool TableBeginContextMenuPopup(ImGuiTable* table);
IMGUI_API void TableMergeDrawChannels(ImGuiTable* table);
inline ImGuiTableInstanceData* TableGetInstanceData(ImGuiTable* table, int instance_no) { if (instance_no == 0) return &table->InstanceDataFirst; return &table->InstanceDataExtra[instance_no - 1]; }
inline ImGuiID TableGetInstanceID(ImGuiTable* table, int instance_no) { return TableGetInstanceData(table, instance_no)->TableInstanceID; }
IMGUI_API void TableFixDisplayOrder(ImGuiTable* table);
IMGUI_API void TableSortSpecsSanitize(ImGuiTable* table);
IMGUI_API void TableSortSpecsBuild(ImGuiTable* table);
IMGUI_API ImGuiSortDirection TableGetColumnNextSortDirection(ImGuiTableColumn* column);
IMGUI_API void TableFixColumnSortDirection(ImGuiTable* table, ImGuiTableColumn* column);
IMGUI_API float TableGetColumnWidthAuto(ImGuiTable* table, ImGuiTableColumn* column);
IMGUI_API void TableBeginRow(ImGuiTable* table);
IMGUI_API void TableEndRow(ImGuiTable* table);
IMGUI_API void TableBeginCell(ImGuiTable* table, int column_n);
IMGUI_API void TableEndCell(ImGuiTable* table);
IMGUI_API ImRect TableGetCellBgRect(const ImGuiTable* table, int column_n);
IMGUI_API const char* TableGetColumnName(const ImGuiTable* table, int column_n);
IMGUI_API ImGuiID TableGetColumnResizeID(ImGuiTable* table, int column_n, int instance_no = 0);
IMGUI_API float TableCalcMaxColumnWidth(const ImGuiTable* table, int column_n);
IMGUI_API void TableSetColumnWidthAutoSingle(ImGuiTable* table, int column_n);
IMGUI_API void TableSetColumnWidthAutoAll(ImGuiTable* table);
IMGUI_API void TableSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
IMGUI_API void TableQueueSetColumnDisplayOrder(ImGuiTable* table, int column_n, int dst_order);
IMGUI_API void TableRemove(ImGuiTable* table);
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTable* table);
IMGUI_API void TableGcCompactTransientBuffers(ImGuiTableTempData* table);
IMGUI_API void TableGcCompactSettings();
// Tables: Settings
IMGUI_API void TableLoadSettings(ImGuiTable* table);
IMGUI_API void TableSaveSettings(ImGuiTable* table);
IMGUI_API void TableResetSettings(ImGuiTable* table);
IMGUI_API ImGuiTableSettings* TableGetBoundSettings(ImGuiTable* table);
IMGUI_API void TableSettingsAddSettingsHandler();
IMGUI_API ImGuiTableSettings* TableSettingsCreate(ImGuiID id, int columns_count);
IMGUI_API ImGuiTableSettings* TableSettingsFindByID(ImGuiID id);
// Tab Bars
inline ImGuiTabBar* GetCurrentTabBar() { ImGuiContext& g = *GImGui; return g.CurrentTabBar; }
IMGUI_API ImGuiTabBar* TabBarFindByID(ImGuiID id);
@@ -3628,7 +3722,7 @@ namespace ImGui
IMGUI_API void RenderFrameBorder(ImVec2 p_min, ImVec2 p_max, float rounding = 0.0f);
IMGUI_API void RenderColorComponentMarker(const ImRect& bb, ImU32 col, float rounding);
IMGUI_API void RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p_min, ImVec2 p_max, ImU32 fill_col, float grid_step, ImVec2 grid_off, float rounding = 0.0f, ImDrawFlags flags = 0);
IMGUI_API void RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None); // Navigation highlight
IMGUI_API void RenderNavCursor(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None, float rounding = -1.0f); // Navigation highlight
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
inline void RenderNavHighlight(const ImRect& bb, ImGuiID id, ImGuiNavRenderCursorFlags flags = ImGuiNavRenderCursorFlags_None) { RenderNavCursor(bb, id, flags); } // Renamed in 1.91.4
#endif
@@ -3707,7 +3801,7 @@ namespace ImGui
IMGUI_API void InputTextDeactivateHook(ImGuiID id);
IMGUI_API bool TempInputText(const ImRect& bb, ImGuiID id, const char* label, char* buf, size_t buf_size, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImGuiDataType data_type, void* p_data, const char* format, const void* p_clamp_min = NULL, const void* p_clamp_max = NULL);
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return g.ActiveId == id && g.TempInputId == id; }
inline bool TempInputIsActive(ImGuiID id) { ImGuiContext& g = *GImGui; return (g.TempInputId == id && g.ActiveId == id) || (g.InputTextDeactivatedState.ID == id); }
inline ImGuiInputTextState* GetInputTextState(ImGuiID id) { ImGuiContext& g = *GImGui; return (id != 0 && g.InputTextState.ID == id) ? &g.InputTextState : NULL; } // Get input text state if active
IMGUI_API void SetNextItemRefVal(ImGuiDataType data_type, void* p_data);
inline bool IsItemActiveAsInputText() { ImGuiContext& g = *GImGui; return g.ActiveId != 0 && g.ActiveId == g.LastItemData.ID && g.InputTextState.ID == g.LastItemData.ID; } // This may be useful to apply workaround that a based on distinguish whenever an item is active as a text input field.
@@ -3769,7 +3863,7 @@ namespace ImGui
IMGUI_API void DebugNodeStorage(ImGuiStorage* storage, const char* label);
IMGUI_API void DebugNodeTabBar(ImGuiTabBar* tab_bar, const char* label);
IMGUI_API void DebugNodeTable(ImGuiTable* table);
IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings);
IMGUI_API void DebugNodeTableSettings(ImGuiTableSettings* settings, ImGuiTable* table);
IMGUI_API void DebugNodeInputTextState(ImGuiInputTextState* state);
IMGUI_API void DebugNodeTypingSelectState(ImGuiTypingSelectState* state);
IMGUI_API void DebugNodeMultiSelectState(ImGuiMultiSelectState* state);
@@ -3979,6 +4073,7 @@ IMGUI_API void ImFontAtlasTextureBlockFill(ImTextureData* dst_tex,
IMGUI_API void ImFontAtlasTextureBlockCopy(ImTextureData* src_tex, int src_x, int src_y, ImTextureData* dst_tex, int dst_x, int dst_y, int w, int h);
IMGUI_API void ImFontAtlasTextureBlockQueueUpload(ImFontAtlas* atlas, ImTextureData* tex, int x, int y, int w, int h);
IMGUI_API bool ImTextureDataUpdateNewFrame(ImTextureData* tex);
IMGUI_API void ImTextureDataQueueUpload(ImTextureData* tex, int x, int y, int w, int h);
IMGUI_API int ImTextureDataGetFormatBytesPerPixel(ImTextureFormat format);
IMGUI_API const char* ImTextureDataGetStatusName(ImTextureStatus status);
+346 -96
View File
File diff suppressed because it is too large Load Diff
+163 -61
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.8
// dear imgui, v1.92.9b
// (demo code)
// Help:
@@ -86,6 +86,7 @@ Index of this file:
// [SECTION] DemoWindowWidgetsFonts()
// [SECTION] DemoWindowWidgetsImages()
// [SECTION] DemoWindowWidgetsListBoxes()
// [SECTION] DemoWindowWidgetsLiveEdit()
// [SECTION] DemoWindowWidgetsMultiComponents()
// [SECTION] DemoWindowWidgetsPlotting()
// [SECTION] DemoWindowWidgetsProgressBars()
@@ -331,6 +332,8 @@ struct ImGuiDemoWindowData
// Other data
bool DisableSections = false;
bool LiveEditOverride = false;
ImGuiItemFlags LiveEditFlags = ImGuiItemFlags_LiveEditOnInputText;
ExampleTreeNode* DemoTree = NULL;
~ImGuiDemoWindowData() { if (DemoTree) ExampleTree_DestroyNode(DemoTree); }
@@ -538,6 +541,9 @@ void ImGui::ShowDemoWindow(bool* p_open)
ImGui::SameLine(); HelpMarker("Swap Cmd<>Ctrl keys, enable various MacOS style behaviors.");
ImGui::Text("Also see Style->Rendering for rendering options.");
ImGui::SeparatorText("Settings");
ImGui::Checkbox("io.ConfigIniSettingsSaveLastUsedDate", &io.ConfigIniSettingsSaveLastUsedDate);
// Also read: https://github.com/ocornut/imgui/wiki/Error-Handling
ImGui::SeparatorText("Error Handling");
@@ -1323,6 +1329,7 @@ static void DemoWindowWidgetsColorAndPickers()
ImGui::ColorEdit4("##RefColor", &ref_color_v.x, ImGuiColorEditFlags_NoInputs | base_flags);
}
}
ImGui::CheckboxFlags("ImGuiColorEditFlags_PickerNoRotate", &color_picker_flags, ImGuiColorEditFlags_PickerNoRotate);
ImGui::Combo("Picker Mode", &picker_mode, "Auto/Current\0ImGuiColorEditFlags_PickerHueBar\0ImGuiColorEditFlags_PickerHueWheel\0");
ImGui::SameLine(); HelpMarker("When not specified explicitly, user can right-click the picker to change mode.");
@@ -1331,7 +1338,7 @@ static void DemoWindowWidgetsColorAndPickers()
ImGui::SameLine(); HelpMarker(
"ColorEdit defaults to displaying RGB inputs if you don't specify a display mode, "
"but the user can change it with a right-click on those inputs.\n\nColorPicker defaults to displaying RGB+HSV+Hex "
"if you don't specify a display mode.\n\nYou can change the defaults using SetColorEditOptions().");
"if you don't specify a display mode.\n\nYou can change the defaults using io.ConfigColorEditFlags.");
ImGuiColorEditFlags flags = base_flags | color_picker_flags;
if (picker_mode == 1) flags |= ImGuiColorEditFlags_PickerHueBar;
@@ -1344,14 +1351,14 @@ static void DemoWindowWidgetsColorAndPickers()
ImGui::Text("Set defaults in code:");
ImGui::SameLine(); HelpMarker(
"SetColorEditOptions() is designed to allow you to set boot-time default.\n"
"io.ConfigColorEditFlags is designed to allow you to set boot-time default.\n"
"We don't have Push/Pop functions because you can force options on a per-widget basis if needed, "
"and the user can change non-forced ones with the options menu.\nWe don't have a getter to avoid "
"encouraging you to persistently save values that aren't forward-compatible.");
if (ImGui::Button("Default: Uint8 + HSV + Hue Bar"))
ImGui::SetColorEditOptions(ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar);
if (ImGui::Button("Default: Float + HDR + Hue Wheel"))
ImGui::SetColorEditOptions(ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel);
if (ImGui::Button("Overwrite default: Uint8 + HSV + Hue Bar"))
ImGui::GetIO().ConfigColorEditFlags = ImGuiColorEditFlags_Uint8 | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_PickerHueBar;
if (ImGui::Button("Overwrite default: Float + HDR + Hue Wheel"))
ImGui::GetIO().ConfigColorEditFlags = ImGuiColorEditFlags_Float | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_PickerHueWheel;
// Always display a small version of both types of pickers
// (that's in order to make it more visible in the demo to people who are skimming quickly through it)
@@ -1740,7 +1747,7 @@ static void DemoWindowWidgetsDragAndDrop()
if (ImGui::IsItemActive() && !ImGui::IsItemHovered())
{
int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.f ? -1 : 1);
int n_next = n + (ImGui::GetMouseDragDelta(0).y < 0.0f ? -1 : 1);
if (n_next >= 0 && n_next < IM_COUNTOF(item_names))
{
item_names[n] = item_names[n_next];
@@ -2005,6 +2012,44 @@ static void DemoWindowWidgetsListBoxes()
}
}
//-----------------------------------------------------------------------------
// [SECTION] DemoWindowWidgetsLiveEdit()
//-----------------------------------------------------------------------------
static void DemoWindowWidgetsLiveEdit(ImGuiDemoWindowData* demo_data)
{
if (ImGui::TreeNode("Live Edit Flags"))
{
IMGUI_DEMO_MARKER("Widgets/Live Edit Flgs");
ImGui::TextWrapped("Select whether to apply keyboard edits to backing variables _while_ typing.");
ImGui::Checkbox("Override Live Edit Flags in Demo Window", &demo_data->LiveEditOverride);
if (!demo_data->LiveEditOverride)
demo_data->LiveEditFlags = ImGui::GetItemFlags();
ImGui::BeginDisabled(demo_data->LiveEditOverride == false);
ImGui::Indent();
ImGui::CheckboxFlags("ImGuiItemFlags_LiveEditOnInputText", &demo_data->LiveEditFlags, ImGuiItemFlags_LiveEditOnInputText);
ImGui::CheckboxFlags("ImGuiItemFlags_LiveEditOnInputScalar", &demo_data->LiveEditFlags, ImGuiItemFlags_LiveEditOnInputScalar);
ImGui::Unindent();
ImGui::EndDisabled();
ImGui::Text("Try typing '123' and seeing effect on backing value:");
static char str[32] = "";
ImGui::InputText("str", str, IM_COUNTOF(str));
ImGui::Text("Backing value: \"%s\"", str);
static int i = 0;
ImGui::InputInt("int", &i, 0, 0);
ImGui::Text("Backing value: %d", i);
static float f = 0.0f;
ImGui::SliderFloat("float", &f, 0.0f, 100.0f);
ImGui::Text("Backing value: %f", f);
ImGui::TreePop();
}
}
//-----------------------------------------------------------------------------
// [SECTION] DemoWindowWidgetsMultiComponents()
//-----------------------------------------------------------------------------
@@ -2156,7 +2201,7 @@ static void DemoWindowWidgetsProgressBars()
char buf[32];
sprintf(buf, "%d/%d", (int)(progress * 1753), 1753);
ImGui::ProgressBar(progress, ImVec2(0.f, 0.f), buf);
ImGui::ProgressBar(progress, ImVec2(0.0f, 0.0f), buf);
// Pass an animated negative value, e.g. -1.0f * (float)ImGui::GetTime() is the recommended value.
// Adjust the factor if you want to adjust the animation speed.
@@ -2185,10 +2230,28 @@ static void DemoWindowWidgetsQueryingStatuses()
};
static int item_type = 4;
static bool item_disabled = false;
static bool liveedit_flags_override = false;
static ImGuiItemFlags liveedit_flags = 0;
ImGui::Combo("Item Type", &item_type, item_names, IM_COUNTOF(item_names), IM_COUNTOF(item_names));
ImGui::SameLine();
HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions. Note that the bool return value of most ImGui function is generally equivalent to calling ImGui::IsItemHovered().");
ImGui::Checkbox("Item Disabled", &item_disabled);
ImGui::Checkbox("Override LiveEdit:", &liveedit_flags_override);
ImGui::SameLine();
if (!liveedit_flags_override)
liveedit_flags = ImGui::GetItemFlags();
ImGui::BeginDisabled(liveedit_flags_override == false);
ImGui::CheckboxFlags("_LiveEditOnInput", &liveedit_flags, ImGuiItemFlags_LiveEditOnInput);
ImGui::SameLine();
ImGui::CheckboxFlags("_LiveEditOnInputText", &liveedit_flags, ImGuiItemFlags_LiveEditOnInputText);
ImGui::SameLine();
ImGui::CheckboxFlags("_LiveEditOnInputScalar", &liveedit_flags, ImGuiItemFlags_LiveEditOnInputScalar);
ImGui::EndDisabled();
if (liveedit_flags_override)
{
ImGui::PushItemFlag(ImGuiItemFlags_LiveEditOnInputText, (liveedit_flags & ImGuiItemFlags_LiveEditOnInputText) != 0);
ImGui::PushItemFlag(ImGuiItemFlags_LiveEditOnInputScalar, (liveedit_flags & ImGuiItemFlags_LiveEditOnInputScalar) != 0);
}
// Submit selected items so we can query their status in the code following it.
bool ret = false;
@@ -2275,6 +2338,11 @@ static void DemoWindowWidgetsQueryingStatuses()
"IsItemHovered(_Tooltip) = %d",
hovered_delay_none, hovered_delay_stationary, hovered_delay_short, hovered_delay_normal, hovered_delay_tooltip);
if (liveedit_flags_override)
{
ImGui::PopItemFlag();
ImGui::PopItemFlag();
}
if (item_disabled)
ImGui::EndDisabled();
@@ -4121,7 +4189,7 @@ static void DemoWindowWidgetsTooltips()
ImGui::BeginDisabled();
ImGui::Button("Disabled item", sz);
if (ImGui::IsItemHovered(ImGuiHoveredFlags_ForTooltip))
ImGui::SetTooltip("I am a a tooltip for a disabled item.");
ImGui::SetTooltip("I am a tooltip for a disabled item.");
ImGui::EndDisabled();
ImGui::TreePop();
@@ -4138,9 +4206,9 @@ static void DemoWindowWidgetsTreeNodes()
{
IMGUI_DEMO_MARKER("Widgets/Tree Nodes");
// See see "Examples -> Property Editor" (ShowExampleAppPropertyEditor() function) for a fancier, data-driven tree.
if (ImGui::TreeNode("Basic trees"))
if (ImGui::TreeNode("Basic Trees"))
{
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Basic trees");
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Basic Trees");
for (int i = 0; i < 5; i++)
{
// Use SetNextItemOpen() so set the default state of a node to be open. We could
@@ -4164,9 +4232,9 @@ static void DemoWindowWidgetsTreeNodes()
ImGui::TreePop();
}
if (ImGui::TreeNode("Hierarchy lines"))
if (ImGui::TreeNode("Hierarchy Lines"))
{
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Hierarchy lines");
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Hierarchy Lines");
static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_DrawLinesFull | ImGuiTreeNodeFlags_DefaultOpen;
HelpMarker("Default option for DrawLinesXXX is stored in style.TreeLinesFlags");
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesNone", &base_flags, ImGuiTreeNodeFlags_DrawLinesNone);
@@ -4203,15 +4271,57 @@ static void DemoWindowWidgetsTreeNodes()
ImGui::TreePop();
}
if (ImGui::TreeNode("Advanced, with Selectable nodes"))
if (ImGui::TreeNode("Selectable Nodes"))
{
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Advanced, with Selectable nodes");
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Selectable Nodes");
HelpMarker(
"This is a more typical looking tree with selectable nodes.\n"
"Click to select, Ctrl+Click to toggle, click on arrows or double-click to open.");
"Manually implemented selectable nodes.\n"
"Click to select, Ctrl+Click to toggle, click on arrows or double-click to open.\n\n"
"You may also use the multi-select API (see 'Demo->Widgets->Selection State & Multi-Select') for more advanced multi-selection features.");
// Hold in 'selection_mask' a simple representation of what may be user-side selection state.
// - You may retain selection state inside or outside your objects in whatever format you see fit.
// You may use ImGuiSelectionBasicStorage which is conceptually close to a set<> of identifiers.
// - We record which node was clicked and then apply selection at the end of the loop.
// - This is a manual and simplified reimplementation of multi-selection, which the full
// BeginMultiSelect() API implements better, but which is not trivial to wire for trees.
static int selection_mask = 0x00;
int node_clicked_idx = -1;
for (int node_n = 0; node_n < 6; node_n++)
{
// Disable the default "open on single-click behavior" + set Selected flag according to our selection.
// To alter selection we use if 'IsItemClicked() && !IsItemToggledOpen()', so clicking on an arrow doesn't alter selection.
// In a BeginMultiSelect()/EndMultiSelect() we could use IsItemToggledSelection() but here we reimplement and use our own logic.
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
if (selection_mask & (1 << node_n))
flags |= ImGuiTreeNodeFlags_Selected;
bool is_open = ImGui::TreeNodeEx((void*)(intptr_t)node_n, flags, "Selectable Node %d", node_n);
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
node_clicked_idx = node_n;
if (is_open)
{
ImGui::BulletText("<Node contents here>");
ImGui::TreePop();
}
}
if (node_clicked_idx != -1)
{
// Update selection state (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
if (ImGui::GetIO().KeyCtrl)
selection_mask ^= (1 << node_clicked_idx); // Ctrl+Click to toggle
else //if (!(selection_mask & (1 << node_clicked_idx))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection
selection_mask = (1 << node_clicked_idx); // Click to single-select
}
ImGui::TreePop();
}
if (ImGui::TreeNode("Advanced"))
{
IMGUI_DEMO_MARKER("Widgets/Tree Nodes/Advanced");
static ImGuiTreeNodeFlags base_flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanAvailWidth;
static bool align_label_with_current_x_position = false;
static bool test_drag_and_drop = false;
static bool use_drag_and_drop = false;
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnArrow", &base_flags, ImGuiTreeNodeFlags_OpenOnArrow);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_OpenOnDoubleClick", &base_flags, ImGuiTreeNodeFlags_OpenOnDoubleClick);
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_SpanAvailWidth", &base_flags, ImGuiTreeNodeFlags_SpanAvailWidth); ImGui::SameLine(); HelpMarker("Extend hit area to all available width instead of allowing more items to be laid out after the node.");
@@ -4229,44 +4339,30 @@ static void DemoWindowWidgetsTreeNodes()
ImGui::CheckboxFlags("ImGuiTreeNodeFlags_DrawLinesToNodes", &base_flags, ImGuiTreeNodeFlags_DrawLinesToNodes);
ImGui::Checkbox("Align label with current X position", &align_label_with_current_x_position);
ImGui::Checkbox("Test tree node as drag source", &test_drag_and_drop);
ImGui::Text("Hello!");
ImGui::Checkbox("Make Tree Nodes as drag & drop sources", &use_drag_and_drop);
if (align_label_with_current_x_position)
ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing());
// 'selection_mask' is dumb representation of what may be user-side selection state.
// You may retain selection state inside or outside your objects in whatever format you see fit.
// 'node_clicked' is temporary storage of what node we have clicked to process selection at the end
/// of the loop. May be a pointer to your own node type, etc.
static int selection_mask = (1 << 2);
int node_clicked = -1;
for (int i = 0; i < 6; i++)
for (int node_n = 0; node_n < 6; node_n++)
{
// Disable the default "open on single-click behavior" + set Selected flag according to our selection.
// To alter selection we use IsItemClicked() && !IsItemToggledOpen(), so clicking on an arrow doesn't alter selection.
ImGuiTreeNodeFlags node_flags = base_flags;
const bool is_selected = (selection_mask & (1 << i)) != 0;
if (is_selected)
node_flags |= ImGuiTreeNodeFlags_Selected;
if (i < 3)
if (node_n < 3)
{
// Items 0..2 are Tree Node
bool node_open = ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Node %d", i);
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
node_clicked = i;
if (test_drag_and_drop && ImGui::BeginDragDropSource())
bool is_open = ImGui::TreeNodeEx((void*)(intptr_t)node_n, node_flags, "Selectable Node %d", node_n);
if (use_drag_and_drop && ImGui::BeginDragDropSource())
{
ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
ImGui::SetDragDropPayload("MY_TREENODE_PAYLOAD_TYPE", NULL, 0);
ImGui::Text("This is a drag and drop source");
ImGui::EndDragDropSource();
}
if (i == 2 && (base_flags & ImGuiTreeNodeFlags_SpanLabelWidth))
if (node_n == 2 && (base_flags & ImGuiTreeNodeFlags_SpanLabelWidth))
{
// Item 2 has an additional inline button to help demonstrate SpanLabelWidth.
ImGui::SameLine();
if (ImGui::SmallButton("button")) {}
}
if (node_open)
if (is_open)
{
ImGui::BulletText("Blah blah\nBlah Blah");
ImGui::SameLine();
@@ -4280,26 +4376,15 @@ static void DemoWindowWidgetsTreeNodes()
// The only reason we use TreeNode at all is to allow selection of the leaf. Otherwise we can
// use BulletText() or advance the cursor by GetTreeNodeToLabelSpacing() and call Text().
node_flags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; // ImGuiTreeNodeFlags_Bullet
ImGui::TreeNodeEx((void*)(intptr_t)i, node_flags, "Selectable Leaf %d", i);
if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
node_clicked = i;
if (test_drag_and_drop && ImGui::BeginDragDropSource())
ImGui::TreeNodeEx((void*)(intptr_t)node_n, node_flags, "Selectable Leaf %d", node_n);
if (use_drag_and_drop && ImGui::BeginDragDropSource())
{
ImGui::SetDragDropPayload("_TREENODE", NULL, 0);
ImGui::SetDragDropPayload("MY_TREENODE_PAYLOAD_TYPE", NULL, 0);
ImGui::Text("This is a drag and drop source");
ImGui::EndDragDropSource();
}
}
}
if (node_clicked != -1)
{
// Update selection state
// (process outside of tree loop to avoid visual inconsistencies during the clicking frame)
if (ImGui::GetIO().KeyCtrl)
selection_mask ^= (1 << node_clicked); // Ctrl+Click to toggle
else //if (!(selection_mask & (1 << node_clicked))) // Depending on selection behavior you want, may want to preserve selection when clicking on item that is part of the selection
selection_mask = (1 << node_clicked); // Click to single-select
}
if (align_label_with_current_x_position)
ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing());
ImGui::TreePop();
@@ -4392,8 +4477,14 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data)
// IMGUI_DEMO_MARKER("Widgets");
const bool disable_all = demo_data->DisableSections; // The Checkbox for that is inside the "Disabled" section at the bottom
const bool override_liveedit = demo_data->LiveEditOverride;
if (disable_all)
ImGui::BeginDisabled();
if (override_liveedit)
{
ImGui::PushItemFlag(ImGuiItemFlags_LiveEditOnInputText, (demo_data->LiveEditFlags & ImGuiItemFlags_LiveEditOnInputText) != 0);
ImGui::PushItemFlag(ImGuiItemFlags_LiveEditOnInputScalar, (demo_data->LiveEditFlags & ImGuiItemFlags_LiveEditOnInputScalar) != 0);
}
DemoWindowWidgetsBasic();
DemoWindowWidgetsBullets();
@@ -4413,6 +4504,7 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data)
DemoWindowWidgetsFonts();
DemoWindowWidgetsImages();
DemoWindowWidgetsListBoxes();
DemoWindowWidgetsLiveEdit(demo_data);
DemoWindowWidgetsMultiComponents();
DemoWindowWidgetsPlotting();
DemoWindowWidgetsProgressBars();
@@ -4427,6 +4519,11 @@ static void DemoWindowWidgets(ImGuiDemoWindowData* demo_data)
DemoWindowWidgetsTreeNodes();
DemoWindowWidgetsVerticalSliders();
if (override_liveedit)
{
ImGui::PopItemFlag();
ImGui::PopItemFlag();
}
if (disable_all)
ImGui::EndDisabled();
}
@@ -5071,7 +5168,8 @@ static void DemoWindowLayout()
// If you want to create your own time line for a real application you may be better off manipulating
// the cursor position yourself, aka using SetCursorPos/SetCursorScreenPos to position the widgets
// yourself. You may also want to use the lower-level ImDrawList API.
int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
const int num_buttons = 10 + ((line & 1) ? line * 9 : line * 3);
const float base_w = ImGui::GetFontSize() * 3;
for (int n = 0; n < num_buttons; n++)
{
if (n > 0) ImGui::SameLine();
@@ -5083,7 +5181,7 @@ static void DemoWindowLayout()
ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(hue, 0.6f, 0.6f));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(hue, 0.7f, 0.7f));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(hue, 0.8f, 0.8f));
ImGui::Button(label, ImVec2(40.0f + sinf((float)(line + n)) * 20.0f, 0.0f));
ImGui::Button(label, ImVec2(base_w + sinf((float)(line + n)) * base_w * 0.5f, 0.0f));
ImGui::PopStyleColor(3);
ImGui::PopID();
}
@@ -8539,6 +8637,8 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
SliderFloat("FrameRounding", &style.FrameRounding, 0.0f, 12.0f, "%.0f");
SliderFloat("PopupRounding", &style.PopupRounding, 0.0f, 12.0f, "%.0f");
SliderFloat("GrabRounding", &style.GrabRounding, 0.0f, 12.0f, "%.0f");
SliderFloat("MenuItemRounding", &style.MenuItemRounding, 0.0f, 12.0f, "%.0f");
// NB: SelectableRounding is intentionally NOT made visible here. We don't want to encourage people using that.
SeparatorText("Scrollbar");
SliderFloat("ScrollbarSize", &style.ScrollbarSize, 1.0f, 20.0f, "%.0f");
@@ -8994,7 +9094,7 @@ struct ExampleAppConsole
static int Stricmp(const char* s1, const char* s2) { int d; while ((d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; } return d; }
static int Strnicmp(const char* s1, const char* s2, int n) { int d = 0; while (n > 0 && (d = toupper(*s2) - toupper(*s1)) == 0 && *s1) { s1++; s2++; n--; } return d; }
static char* Strdup(const char* s) { IM_ASSERT(s); size_t len = strlen(s) + 1; void* buf = ImGui::MemAlloc(len); IM_ASSERT(buf); return (char*)memcpy(buf, (const void*)s, len); }
static void Strtrim(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; }
static void Strtrimblanks(char* s) { char* str_end = s + strlen(s); while (str_end > s && str_end[-1] == ' ') str_end--; *str_end = 0; }
void ClearLog()
{
@@ -9143,10 +9243,10 @@ struct ExampleAppConsole
if (ImGui::InputText("Input", InputBuf, IM_COUNTOF(InputBuf), input_text_flags, &TextEditCallbackStub, (void*)this))
{
char* s = InputBuf;
Strtrim(s);
Strtrimblanks(s);
if (s[0])
ExecCommand(s);
strcpy(s, "");
s[0] = 0;
reclaim_focus = true;
}
@@ -10165,6 +10265,7 @@ static void ShowExampleAppCustomRendering(bool* p_open)
{
IMGUI_DEMO_MARKER("Examples/Custom rendering/Primitives");
ImGui::PushItemWidth(-ImGui::GetFontSize() * 15);
ImGui::PushItemFlag(ImGuiItemFlags_LiveEditOnInput, true);
ImDrawList* draw_list = ImGui::GetWindowDrawList();
// Draw gradients
@@ -10191,7 +10292,7 @@ static void ShowExampleAppCustomRendering(bool* p_open)
// Draw a bunch of primitives
ImGui::Text("All primitives");
static float sz = 36.0f;
static float sz = 42.0f;
static float thickness = 3.0f;
static int ngon_sides = 6;
static bool circle_segments_override = false;
@@ -10285,6 +10386,7 @@ static void ShowExampleAppCustomRendering(bool* p_open)
x += sz + spacing;
ImGui::Dummy(ImVec2((sz + spacing) * 13.2f, (sz + spacing) * 3.0f));
ImGui::PopItemFlag();
ImGui::PopItemWidth();
ImGui::EndTabItem();
}
+153 -117
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.8
// dear imgui, v1.92.9b
// (drawing and font code)
/*
@@ -402,7 +402,6 @@ ImDrawListSharedData::ImDrawListSharedData()
const float a = ((float)i * 2 * IM_PI) / (float)IM_COUNTOF(ArcFastVtx);
ArcFastVtx[i] = ImVec2(ImCos(a), ImSin(a));
}
ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError);
}
ImDrawListSharedData::~ImDrawListSharedData()
@@ -412,17 +411,17 @@ ImDrawListSharedData::~ImDrawListSharedData()
void ImDrawListSharedData::SetCircleTessellationMaxError(float max_error)
{
if (CircleSegmentMaxError == max_error)
if (CircleTessellationMaxError == max_error)
return;
IM_ASSERT(max_error > 0.0f);
CircleSegmentMaxError = max_error;
CircleTessellationMaxError = max_error;
for (int i = 0; i < IM_COUNTOF(CircleSegmentCounts); i++)
{
const float radius = (float)i;
CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleSegmentMaxError) : IM_DRAWLIST_ARCFAST_SAMPLE_MAX);
CircleSegmentCounts[i] = (ImU8)((i > 0) ? IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, CircleTessellationMaxError) : IM_DRAWLIST_ARCFAST_SAMPLE_MAX);
}
ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleSegmentMaxError);
ArcFastRadiusCutoff = IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC_R(IM_DRAWLIST_ARCFAST_SAMPLE_MAX, CircleTessellationMaxError);
}
ImDrawList::ImDrawList(ImDrawListSharedData* shared_data)
@@ -656,11 +655,11 @@ void ImDrawList::_OnChangedVtxOffset()
int ImDrawList::_CalcCircleAutoSegmentCount(float radius) const
{
// Automatic segment count
const int radius_idx = (int)(radius + 0.999999f); // ceil to never reduce accuracy
const int radius_idx = (int)(radius + 0.999f); // ceil to never reduce accuracy
if (radius_idx >= 0 && radius_idx < IM_COUNTOF(_Data->CircleSegmentCounts))
return _Data->CircleSegmentCounts[radius_idx]; // Use cached value
else
return IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleSegmentMaxError);
return IM_DRAWLIST_CIRCLE_AUTO_SEGMENT_CALC(radius, _Data->CircleTessellationMaxError);
}
// Render-level scissoring. This is passed down to your render function but not used for CPU-side coarse clipping. Prefer using higher-level ImGui::PushClipRect() to affect logic (hit-testing and widget culling)
@@ -823,7 +822,12 @@ void ImDrawList::AddPolyline(const ImVec2* points, const int points_count, ImU32
const ImVec2 opaque_uv = _Data->TexUvWhitePixel;
const int count = closed ? points_count : points_count - 1; // The number of line segments we need to draw
const bool thick_line = (thickness > _FringeScale);
IM_ASSERT((flags & ImDrawFlags_InvalidMask_) == 0 && "Incorrect parameter. Did you swapped 'thickness' and 'flags'?");
// If this assert triggers on legacy code:
// - 1.92.8 (2025/05): swapped two last parameters order: flags, thickness --> thickness, flags. This should normally be caught by compile-time type-checking.
// - 1.92.8 (2025/05): changed value of ImDrawList_Closed which was previously guaranteed to be == 1. Hardcoded use of 1 or true should be replaced.
// Read more details near AddRect() + see "API BREAKING CHANGES" section for 1.82, 1.90 and 1.92.8.
IM_ASSERT_USER_ERROR_RET((flags & ImDrawFlags_InvalidMask_) == 0, "Incorrect parameter. Did you swap 'thickness' and 'flags'?");
if (Flags & ImDrawListFlags_AntiAliasedLines)
{
@@ -1475,27 +1479,24 @@ void ImDrawList::AddLine(const ImVec2& p1, const ImVec2& p2, ImU32 col, float th
{
if ((col & IM_COL32_A_MASK) == 0)
return;
PathLineTo(p1 + ImVec2(0.5f, 0.5f));
PathLineTo(p2 + ImVec2(0.5f, 0.5f));
PathStroke(col, thickness);
const ImVec2 points[2] = { ImVec2(p1.x + 0.5f, p1.y + 0.5f), ImVec2(p2.x + 0.5f, p2.y + 0.5f) };
AddPolyline(points, 2, col, thickness);
}
void ImDrawList::AddLineH(float min_x, float max_x, float y, ImU32 col, float thickness)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
PathLineTo(ImVec2(min_x + 0.5f, y + 0.5f)); // Same as AddLine() above.
PathLineTo(ImVec2(max_x + 0.5f, y + 0.5f));
PathStroke(col, thickness);
const ImVec2 points[2] = { ImVec2(min_x + 0.5f, y + 0.5f), ImVec2(max_x + 0.5f, y + 0.5f) }; // Same as AddLine() above.
AddPolyline(points, 2, col, thickness);
}
void ImDrawList::AddLineV(float x, float min_y, float max_y, ImU32 col, float thickness)
{
if ((col & IM_COL32_A_MASK) == 0)
return;
PathLineTo(ImVec2(x + 0.5f, min_y + 0.5f)); // Same as AddLine() above.
PathLineTo(ImVec2(x + 0.5f, max_y + 0.5f));
PathStroke(col, thickness);
const ImVec2 points[2] = { ImVec2(x + 0.5f, min_y + 0.5f), ImVec2(x + 0.5f, max_y + 0.5f) }; // Same as AddLine() above.
AddPolyline(points, 2, col, thickness);
}
// p_min = upper-left, p_max = lower-right
@@ -1503,14 +1504,15 @@ void ImDrawList::AddLineV(float x, float min_y, float max_y, ImU32 col, float th
void ImDrawList::AddRect(const ImVec2& p_min, const ImVec2& p_max, ImU32 col, float rounding, float thickness, ImDrawFlags flags)
{
// If this assert triggers on legacy code:
// - 1.92.8 (2025/04): swapped two last parameters order: flags, thickness --> thickness, flags. This should normally be caught by compile-time type-checking.
// - 1.92.8 (2025/05): swapped two last parameters order: flags, thickness --> thickness, flags. This should normally be caught by compile-time type-checking.
// - 1.92.8 (2025/05): changed value of ImDrawList_Closed which was previously guaranteed to be == 1. Hardcoded use of 1 or true should be replaced.
// - 1.82.0 (2021/03): changed ImDrawCornerFlags to ImDrawFlags_RoundCornersXXX values.
// If you used hard-coded 1 to 15 or ~0 in flags to configure corner rounding use the new flags!
// - Hard coded support for ~0 == ImDrawFlags_RoundCornersAll.
// - Hard coded support for values 0x01 to 0x0F (matching 15 out of 16 old flags combinations) --> see FixRectCornerFlags() in <1.90 code.
// - Hard coded 0x00 with 'float rounding > 0.0f' --> replace with ImDrawFlags_RoundCornersNone or use 'float rounding = 0.0f'.
// See "API BREAKING CHANGES" section for 1.82 and 1.90.
IM_ASSERT((flags & ImDrawFlags_InvalidMask_) == 0 && "Incorrect parameter. Did you swapped 'thickness' and 'flags'?"); // Or misuse of legacy hard-coded ImDrawCornerFlags values
// See "API BREAKING CHANGES" section for 1.82, 1.90 and 1.92.8.
IM_ASSERT_USER_ERROR_RET((flags & ImDrawFlags_InvalidMask_) == 0, "Incorrect parameter. Did you swap 'thickness' and 'flags'?"); // Or misuse of legacy hard-coded ImDrawCornerFlags values
if ((col & IM_COL32_A_MASK) == 0)
return;
@@ -2278,11 +2280,14 @@ void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx)
void ImDrawData::Clear()
{
Valid = false;
CmdListsCount = TotalIdxCount = TotalVtxCount = 0;
FrameCount = TotalIdxCount = TotalVtxCount = 0;
CmdLists.resize(0); // The ImDrawList are NOT owned by ImDrawData but e.g. by ImGuiContext, so we don't clear them.
DisplayPos = DisplaySize = FramebufferScale = ImVec2(0.0f, 0.0f);
OwnerViewport = NULL;
Textures = NULL;
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
CmdListsCount = 0;
#endif
}
// Important: 'out_list' is generally going to be draw_data->CmdLists, but may be another temporary list
@@ -2327,14 +2332,12 @@ void ImGui::AddDrawListToDrawDataEx(ImDrawData* draw_data, ImVector<ImDrawList*>
// Add to output list + records state in ImDrawData
out_list->push_back(draw_list);
draw_data->CmdListsCount++;
draw_data->TotalVtxCount += draw_list->VtxBuffer.Size;
draw_data->TotalIdxCount += draw_list->IdxBuffer.Size;
}
void ImDrawData::AddDrawList(ImDrawList* draw_list)
{
IM_ASSERT(CmdLists.Size == CmdListsCount);
draw_list->_PopUnusedDrawCmd();
ImGui::AddDrawListToDrawDataEx(this, &CmdLists, draw_list);
}
@@ -2443,7 +2446,7 @@ ImFontConfig::ImFontConfig()
GlyphMaxAdvanceX = FLT_MAX;
RasterizerMultiply = 1.0f;
RasterizerDensity = 1.0f;
LineHeight = 1.0f;
LineHeight = 1.0f; // [PCSX2 Custom]
EllipsisChar = 0;
}
@@ -2561,8 +2564,6 @@ void ImTextureData::DestroyPixels()
// - ImFontAtlasBuildPreloadAllGlyphRanges()
// - ImFontAtlasBuildUpdatePointers()
// - ImFontAtlasBuildRenderBitmapFromString()
// - ImFontAtlasBuildUpdateBasicTexData()
// - ImFontAtlasBuildUpdateLinesTexData()
// - ImFontAtlasBuildAddFont()
// - ImFontAtlasBuildSetupFontBakedEllipsis()
// - ImFontAtlasBuildSetupFontBakedBlanks()
@@ -2579,13 +2580,14 @@ void ImTextureData::DestroyPixels()
// - ImFontAtlasUpdateDrawListsSharedData()
//-----------------------------------------------------------------------------
// - ImFontAtlasBuildSetTexture()
// - ImFontAtlasBuildAddTexture()
// - ImFontAtlasBuildMakeSpace()
// - ImFontAtlasBuildRepackTexture()
// - ImFontAtlasBuildGrowTexture()
// - ImFontAtlasBuildRepackOrGrowTexture()
// - ImFontAtlasBuildGetTextureSizeEstimate()
// - ImFontAtlasBuildCompactTexture()
// - ImFontAtlasBuildUpdateTexData()
// - ImFontAtlasTextureAdd()
// - ImFontAtlasTextureRepack()
// - ImFontAtlasTextureGrow()
// - ImFontAtlasTextureMakeSpace()
// - ImFontAtlasTextureGetSizeEstimate()
// - ImFontAtlasBuildClear()
// - ImFontAtlasTextureCompact()
// - ImFontAtlasBuildInit()
// - ImFontAtlasBuildDestroy()
//-----------------------------------------------------------------------------
@@ -2690,6 +2692,7 @@ ImFontAtlas::~ImFontAtlas()
// Calling this mid-frame will discard the CPU-side copy of the texture data which is generally unreliable as you may have textures queued for creation or updates.
void ImFontAtlas::Clear()
{
IMGUI_DEBUG_LOG_FONT("[font] ImFontAtlas::Clear()\n");
bool backup_renderer_has_textures = RendererHasTextures;
RendererHasTextures = false; // Full Clear() is supported, but ClearTexData() only isn't.
ClearFonts();
@@ -2700,6 +2703,7 @@ void ImFontAtlas::Clear()
void ImFontAtlas::ClearFonts()
{
// FIXME-NEWATLAS: Illegal to remove currently bound font.
IMGUI_DEBUG_LOG_FONT("[font] ImFontAtlas::ClearFonts()\n");
IM_ASSERT(!Locked && "Cannot modify a locked ImFontAtlas!");
for (ImFont* font : Fonts)
ImFontAtlasBuildNotifySetFont(this, font, NULL);
@@ -2775,6 +2779,28 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool rendere
IM_ASSERT(atlas->Builder == NULL || atlas->Builder->FrameCount < frame_count); // Protection against being called twice.
atlas->RendererHasTextures = renderer_has_textures;
// Update texture status and discard old textures.
// (we do this first thing to handle an edge case: if user mistakenly calls ClearFonts()+SetStatus(OK) during
// rendering, it would ImFontAtlasBuildMain() rebuilding before tex->Updates[] gets a chance to be cleared)
// (if somehow we need to move this back lower in the function, we could manually call the code to clear Updates[]).
for (int tex_n = 0; tex_n < atlas->TexList.Size; tex_n++)
{
// Update and remove if requested
ImTextureData* tex = atlas->TexList[tex_n];
if (tex->Status == ImTextureStatus_WantCreate && atlas->RendererHasTextures)
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture's TexID/BackendUserData but did not update Status to OK.");
bool remove_from_list = ImTextureDataUpdateNewFrame(tex);
if (remove_from_list)
{
IM_ASSERT(atlas->TexData != tex);
tex->DestroyPixels();
IM_DELETE(tex);
atlas->TexList.erase(atlas->TexList.begin() + tex_n);
tex_n--;
}
}
// Check that font atlas was built or backend support texture reload in which case we can build now
if (atlas->RendererHasTextures)
{
@@ -2814,61 +2840,50 @@ void ImFontAtlasUpdateNewFrame(ImFontAtlas* atlas, int frame_count, bool rendere
builder->BakedPool.Size -= builder->BakedDiscardedCount;
builder->BakedDiscardedCount = 0;
}
}
// Update texture status
for (int tex_n = 0; tex_n < atlas->TexList.Size; tex_n++)
bool ImTextureDataUpdateNewFrame(ImTextureData* tex)
{
bool remove_from_list = false;
if (tex->Status == ImTextureStatus_OK)
{
ImTextureData* tex = atlas->TexList[tex_n];
bool remove_from_list = false;
if (tex->Status == ImTextureStatus_OK)
{
tex->Updates.resize(0);
tex->UpdateRect.x = tex->UpdateRect.y = (unsigned short)~0;
tex->UpdateRect.w = tex->UpdateRect.h = 0;
}
if (tex->Status == ImTextureStatus_WantCreate && atlas->RendererHasTextures)
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture's TexID/BackendUserData but did not update Status to OK.");
// Request destroy
// - Keep bool to true in order to differentiate a planned destroy vs a destroy decided by the backend.
// - We don't destroy pixels right away, as backend may have an in-flight copy from RAM.
if (tex->WantDestroyNextFrame && tex->Status != ImTextureStatus_Destroyed && tex->Status != ImTextureStatus_WantDestroy)
{
IM_ASSERT(tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates);
tex->Status = ImTextureStatus_WantDestroy;
}
// If a texture has never reached the backend, they don't need to know about it.
// (note: backends between 1.92.0 and 1.92.4 could set an already destroyed texture to ImTextureStatus_WantDestroy
// when invalidating graphics objects twice, which would previously remove it from the list and crash.)
if (tex->Status == ImTextureStatus_WantDestroy && tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL)
tex->Status = ImTextureStatus_Destroyed;
// Process texture being destroyed
if (tex->Status == ImTextureStatus_Destroyed)
{
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture Status to Destroyed but did not clear TexID/BackendUserData!");
if (tex->WantDestroyNextFrame)
remove_from_list = true; // Destroy was scheduled by us
else
tex->Status = ImTextureStatus_WantCreate; // Destroy was done was backend: recreate it (e.g. freed resources mid-run)
}
// The backend may need defer destroying by a few frames, to handle texture used by previous in-flight rendering.
// We allow the texture staying in _WantDestroy state and increment a counter which the backend can use to take its decision.
if (tex->Status == ImTextureStatus_WantDestroy)
tex->UnusedFrames++;
// Destroy and remove
if (remove_from_list)
{
IM_ASSERT(atlas->TexData != tex);
tex->DestroyPixels();
IM_DELETE(tex);
atlas->TexList.erase(atlas->TexList.begin() + tex_n);
tex_n--;
}
tex->Updates.resize(0);
tex->UpdateRect.x = tex->UpdateRect.y = (unsigned short)~0;
tex->UpdateRect.w = tex->UpdateRect.h = 0;
}
// Request destroy
// - Keep bool to true in order to differentiate a planned destroy vs a destroy decided by the backend.
// - We don't destroy pixels right away, as backend may have an in-flight copy from RAM.
if (tex->WantDestroyNextFrame && tex->Status != ImTextureStatus_Destroyed && tex->Status != ImTextureStatus_WantDestroy)
{
IM_ASSERT(tex->Status == ImTextureStatus_OK || tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates);
tex->Status = ImTextureStatus_WantDestroy;
}
// If a texture has never reached the backend, they don't need to know about it.
// (note: backends between 1.92.0 and 1.92.4 could set an already destroyed texture to ImTextureStatus_WantDestroy
// when invalidating graphics objects twice, which would previously remove it from the list and crash.)
if (tex->Status == ImTextureStatus_WantDestroy && tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && tex->QueueUserData == NULL)
tex->Status = ImTextureStatus_Destroyed;
// Process texture being destroyed
if (tex->Status == ImTextureStatus_Destroyed)
{
IM_ASSERT(tex->TexID == ImTextureID_Invalid && tex->BackendUserData == NULL && "Backend set texture Status to Destroyed but did not clear TexID/BackendUserData!");
IM_ASSERT(tex->QueueUserData == NULL && "Texture queue set Status to Destroyed but did not clear QueueUserData!");
if (tex->WantDestroyNextFrame)
remove_from_list = true; // Destroy was scheduled by us
else
tex->Status = ImTextureStatus_WantCreate; // Destroy was done was backend: recreate it (e.g. freed resources mid-run)
}
// The backend may need defer destroying by a few frames, to handle texture used by previous in-flight rendering.
// We allow the texture staying in _WantDestroy state and increment a counter which the backend can use to take its decision.
if (tex->Status == ImTextureStatus_WantDestroy)
tex->UnusedFrames++;
return remove_from_list;
}
void ImFontAtlasTextureBlockConvert(const unsigned char* src_pixels, ImTextureFormat src_fmt, int src_pitch, unsigned char* dst_pixels, ImTextureFormat dst_fmt, int dst_pitch, int w, int h)
@@ -3071,7 +3086,7 @@ ImFont* ImFontAtlas::AddFont(const ImFontConfig* font_cfg_in)
font->Flags = font_cfg_in->Flags;
font->LegacySize = font_cfg_in->SizePixels;
font->CurrentRasterizerDensity = font_cfg_in->RasterizerDensity;
font->LineHeight = font_cfg_in->LineHeight;
font->LineHeight = font_cfg_in->LineHeight; // [PCSX2 Custom]
Fonts.push_back(font);
}
else
@@ -3145,9 +3160,11 @@ static void Decode85(const unsigned char* src, unsigned char* dst)
dst += 4;
}
}
#ifndef IMGUI_DISABLE_DEFAULT_FONT
static const char* GetDefaultCompressedFontDataProggyClean(int* out_size);
static const char* GetDefaultCompressedFontDataProggyForever(int* out_size);
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_BITMAP)
const char* ImGui_GetDefaultCompressedFontDataProggyClean(int* out_size);
#endif
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_VECTOR)
const char* ImGui_GetDefaultCompressedFontDataProggyForever(int* out_size);
#endif
// This duplicates some of the logic in UpdateFontsNewFrame() which is a bit chicken-and-eggy/tricky to extract due to variety of codepaths and possible initialization ordering.
@@ -3171,7 +3188,7 @@ ImFont* ImFontAtlas::AddFontDefault(const ImFontConfig* font_cfg)
// If you want a similar font which may be better scaled, consider using AddFontDefaultVector().
ImFont* ImFontAtlas::AddFontDefaultBitmap(const ImFontConfig* font_cfg_template)
{
#ifndef IMGUI_DISABLE_DEFAULT_FONT
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_BITMAP)
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
if (!font_cfg_template)
font_cfg.PixelSnapH = true; // Prevents sub-integer scaling factors at lower-level layers.
@@ -3186,20 +3203,20 @@ ImFont* ImFontAtlas::AddFontDefaultBitmap(const ImFontConfig* font_cfg_template)
font_cfg.GlyphOffset.y += 1.0f * (font_cfg.SizePixels / 13.0f); // Add +1 offset per 13 units
int ttf_compressed_size = 0;
const char* ttf_compressed = GetDefaultCompressedFontDataProggyClean(&ttf_compressed_size);
const char* ttf_compressed = ImGui_GetDefaultCompressedFontDataProggyClean(&ttf_compressed_size);
return AddFontFromMemoryCompressedTTF(ttf_compressed, ttf_compressed_size, font_cfg.SizePixels, &font_cfg);
#else
IM_ASSERT(0 && "Function is disabled in this build.");
IM_UNUSED(font_cfg_template);
return NULL;
#endif // #ifndef IMGUI_DISABLE_DEFAULT_FONT
#endif
}
// Load a minimal version of ProggyForever, designed to match our good old ProggyClean, but nicely scalable.
// (See build script in https://github.com/ocornut/proggyforever for details)
ImFont* ImFontAtlas::AddFontDefaultVector(const ImFontConfig* font_cfg_template)
{
#ifndef IMGUI_DISABLE_DEFAULT_FONT
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_VECTOR)
ImFontConfig font_cfg = font_cfg_template ? *font_cfg_template : ImFontConfig();
if (!font_cfg_template)
font_cfg.PixelSnapH = true; // Precisely match ProggyClean, but prevents sub-integer scaling factors at lower-level layers.
@@ -3214,13 +3231,13 @@ ImFont* ImFontAtlas::AddFontDefaultVector(const ImFontConfig* font_cfg_template)
font_cfg.GlyphOffset.y += 0.5f * (font_cfg.SizePixels / 16.0f); // Closer match ProggyClean + avoid descenders going too high (with current code).
int ttf_compressed_size = 0;
const char* ttf_compressed = GetDefaultCompressedFontDataProggyForever(&ttf_compressed_size);
const char* ttf_compressed = ImGui_GetDefaultCompressedFontDataProggyForever(&ttf_compressed_size);
return AddFontFromMemoryCompressedTTF(ttf_compressed, ttf_compressed_size, font_cfg.SizePixels, &font_cfg);
#else
IM_ASSERT(0 && "Function is disabled in this build.");
IM_UNUSED(font_cfg_template);
return NULL;
#endif // #ifndef IMGUI_DISABLE_DEFAULT_FONT
#endif
}
ImFont* ImFontAtlas::AddFontFromFileTTF(const char* filename, float size_pixels, const ImFontConfig* font_cfg_template, const ImWchar* glyph_ranges)
@@ -3576,7 +3593,7 @@ void ImFontAtlasBuildRenderBitmapFromString(ImFontAtlas* atlas, int x, int y, in
}
}
static void ImFontAtlasBuildUpdateBasicTexData(ImFontAtlas* atlas)
static void ImFontAtlasBuildUpdateTexDataBasic(ImFontAtlas* atlas)
{
// Pack and store identifier so we can refresh UV coordinates on texture resize.
// FIXME-NEWATLAS: User/custom rects where user code wants to store UV coordinates will need to do the same thing.
@@ -3610,7 +3627,7 @@ static void ImFontAtlasBuildUpdateBasicTexData(ImFontAtlas* atlas)
atlas->TexUvWhitePixel = ImVec2((r.x + 0.5f) * atlas->TexUvScale.x, (r.y + 0.5f) * atlas->TexUvScale.y);
}
static void ImFontAtlasBuildUpdateLinesTexData(ImFontAtlas* atlas)
static void ImFontAtlasBuildUpdateTexDataLines(ImFontAtlas* atlas)
{
if (atlas->Flags & ImFontAtlasFlags_NoBakedLines)
return;
@@ -4059,6 +4076,12 @@ static void ImFontAtlasBuildSetTexture(ImFontAtlas* atlas, ImTextureData* tex)
ImFontAtlasUpdateDrawListsTextures(atlas, old_tex_ref, atlas->TexRef);
}
static void ImFontAtlasBuildUpdateTexData(ImFontAtlas* atlas)
{
ImFontAtlasBuildUpdateTexDataBasic(atlas);
ImFontAtlasBuildUpdateTexDataLines(atlas);
}
// Create a new texture, discard previous one
ImTextureData* ImFontAtlasTextureAdd(ImFontAtlas* atlas, int w, int h)
{
@@ -4173,8 +4196,7 @@ void ImFontAtlasTextureRepack(ImFontAtlas* atlas, int w, int h)
}
// Update other cached UV
ImFontAtlasBuildUpdateLinesTexData(atlas);
ImFontAtlasBuildUpdateBasicTexData(atlas);
ImFontAtlasBuildUpdateTexData(atlas);
builder->LockDisableResize = false;
ImFontAtlasUpdateDrawListsSharedData(atlas);
@@ -4323,8 +4345,7 @@ void ImFontAtlasBuildInit(ImFontAtlas* atlas)
ImFontAtlasPackInit(atlas);
// Add required texture data
ImFontAtlasBuildUpdateLinesTexData(atlas);
ImFontAtlasBuildUpdateBasicTexData(atlas);
ImFontAtlasBuildUpdateTexData(atlas);
// Register fonts
ImFontAtlasBuildUpdatePointers(atlas);
@@ -4353,6 +4374,8 @@ void ImFontAtlasBuildDestroy(ImFontAtlas* atlas)
atlas->Builder = NULL;
}
//-----------------------------------------------------------------------------
void ImFontAtlasPackInit(ImFontAtlas * atlas)
{
ImTextureData* tex = atlas->TexData;
@@ -5651,6 +5674,7 @@ ImVec2 ImFontCalcTextSizeEx(ImFont* font, float size, float max_width, float wra
text_end_display = text_end;
ImFontBaked* baked = font->GetFontBaked(size);
// [PCSX2 Custom]
const float line_height = ImCeil(size * font->LineHeight);
const float scale = size / baked->Size;
@@ -5749,8 +5773,13 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im
if (glyph->Colored)
col |= ~IM_COL32_A_MASK;
float scale = (size >= 0.0f) ? (size / baked->Size) : 1.0f;
float x = IM_TRUNC(pos.x);
float y = IM_TRUNC(pos.y);
float x = pos.x;
float y = pos.y;
if ((draw_list->Flags & ImDrawListFlags_TextNoPixelSnap) == 0)
{
x = IM_TRUNC(x);
y = IM_TRUNC(y);
}
float x1 = x + glyph->X0 * scale;
float x2 = x + glyph->X1 * scale;
@@ -5782,17 +5811,22 @@ void ImFont::RenderChar(ImDrawList* draw_list, float size, const ImVec2& pos, Im
// DO NOT CALL DIRECTLY THIS WILL CHANGE WILDLY IN 2026. Use ImDrawList::AddText().
void ImFont::RenderText(ImDrawList* draw_list, float size, const ImVec2& pos, ImU32 col, const ImVec4& clip_rect, const char* text_begin, const char* text_end, float wrap_width, ImDrawTextFlags flags)
{
// Align to be pixel perfect
begin:
float x = IM_TRUNC(pos.x);
float y = IM_TRUNC(pos.y);
// Align to be pixel perfect
float x = pos.x;
float y = pos.y;
if (y > clip_rect.w)
return;
if ((draw_list->Flags & ImDrawListFlags_TextNoPixelSnap) == 0)
{
x = IM_TRUNC(x);
y = IM_TRUNC(y);
}
if (!text_end)
text_end = text_begin + ImStrlen(text_begin); // ImGui:: functions generally already provides a valid text_end, so this is merely to handle direct calls.
const float line_height = ImCeil(size * LineHeight);
const float line_height = ImCeil(size * LineHeight); // [PCSX2 Custom]
ImFontBaked* baked = GetFontBaked(size);
const float scale = size / baked->Size;
@@ -6173,8 +6207,8 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p
flags = ImDrawFlags_RoundCornersDefault_;
if (((col & IM_COL32_A_MASK) >> IM_COL32_A_SHIFT) < 0xFF)
{
ImU32 col_bg1 = GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col));
ImU32 col_bg2 = GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col));
ImU32 col_bg1 = GetColorU32(ImAlphaBlendColors(IM_COL32(128, 128, 128, 255), col));
ImU32 col_bg2 = GetColorU32(ImAlphaBlendColors(IM_COL32(204, 204, 204, 255), col));
draw_list->AddRectFilled(p_min, p_max, col_bg1, rounding, flags);
int yi = 0;
@@ -6183,12 +6217,12 @@ void ImGui::RenderColorRectWithAlphaCheckerboard(ImDrawList* draw_list, ImVec2 p
float y1 = ImClamp(y, p_min.y, p_max.y), y2 = ImMin(y + grid_step, p_max.y);
if (y2 <= y1)
continue;
for (float x = p_min.x + grid_off.x + (yi & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f)
for (float x = p_min.x + grid_off.x + ((yi ^ 1) & 1) * grid_step; x < p_max.x; x += grid_step * 2.0f)
{
float x1 = ImClamp(x, p_min.x, p_max.x), x2 = ImMin(x + grid_step, p_max.x);
if (x2 <= x1)
continue;
ImDrawFlags cell_flags = ImDrawFlags_RoundCornersNone;
ImDrawFlags cell_flags = ImDrawFlags_RoundCornersNone; // FIXME: Could use CalcRoundingFlagsForRectInRect()
if (y1 <= p_min.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersTopLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersTopRight; }
if (y2 >= p_max.y) { if (x1 <= p_min.x) cell_flags |= ImDrawFlags_RoundCornersBottomLeft; if (x2 >= p_max.x) cell_flags |= ImDrawFlags_RoundCornersBottomRight; }
@@ -6330,7 +6364,7 @@ static unsigned int stb_decompress(unsigned char *output, const unsigned char *i
// Download and more information at https://github.com/bluescan/proggyfonts
//-----------------------------------------------------------------------------
#ifndef IMGUI_DISABLE_DEFAULT_FONT
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_BITMAP)
// File: 'ProggyClean.ttf' (41208 bytes)
// Exported using binary_to_compressed_c.exe -u8 "ProggyClean.ttf" proggy_clean_ttf
@@ -6505,11 +6539,12 @@ static const unsigned char proggy_clean_ttf_compressed_data[9583] =
239,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,239,32,57,141,239,35,57,102,0,0,5,250,72,249,98,247,
};
static const char* GetDefaultCompressedFontDataProggyClean(int* out_size)
const char* ImGui_GetDefaultCompressedFontDataProggyClean(int* out_size)
{
*out_size = proggy_clean_ttf_compressed_size;
return (const char*)proggy_clean_ttf_compressed_data;
}
#endif // #if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_BITMAP)
//-----------------------------------------------------------------------------
// [SECTION] Default font data (ProggyForever-Regular-minimal.ttf)
@@ -6518,6 +6553,8 @@ static const char* GetDefaultCompressedFontDataProggyClean(int* out_size)
// MIT license / Copyright (c) 2026 Disco Hello, Copyright (c) 2019,2023 Tristan Grimmer
//-----------------------------------------------------------------------------
#if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_VECTOR)
// File: 'output/ProggyForever-Regular-minimal.ttf' (18556 bytes)
// Exported using binary_to_compressed_c.exe -u8 "output/ProggyForever-Regular-minimal.ttf" proggy_forever_minimal_ttf
static const unsigned int proggy_forever_minimal_ttf_compressed_size = 14562;
@@ -6767,12 +6804,11 @@ static const unsigned char proggy_forever_minimal_ttf_compressed_data[14562] =
3,36,0,229,13,183,147,132,7,42,175,187,66,0,0,0,0,229,178,59,232,5,250,48,120,202,241,
};
static const char* GetDefaultCompressedFontDataProggyForever(int* out_size)
const char* ImGui_GetDefaultCompressedFontDataProggyForever(int* out_size)
{
*out_size = proggy_forever_minimal_ttf_compressed_size;
return (const char*)proggy_forever_minimal_ttf_compressed_data;
}
#endif // #ifndef IMGUI_DISABLE_DEFAULT_FONT
#endif // #if !defined(IMGUI_DISABLE_DEFAULT_FONT) && !defined(IMGUI_DISABLE_DEFAULT_FONT_VECTOR)
#endif // #ifndef IMGUI_DISABLE
+1 -1
View File
@@ -450,7 +450,7 @@ static bool ImGui_ImplFreeType_FontBakedInit(ImFontAtlas* atlas, ImFontConfig* s
// (FT_Set_Pixel_Sizes() essentially calls FT_Request_Size() with FT_SIZE_REQUEST_TYPE_NOMINAL)
const float rasterizer_density = src->RasterizerDensity * baked->RasterizerDensity;
FT_Size_RequestRec req;
req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; // [PCSX2 Custom]
req.width = 0;
req.height = (uint32_t)(size * 64 * rasterizer_density);
req.horiResolution = 0;
+415 -175
View File
File diff suppressed because it is too large Load Diff
+138 -91
View File
@@ -1,4 +1,4 @@
// dear imgui, v1.92.8
// dear imgui, v1.92.9b
// (widgets code)
/*
@@ -266,6 +266,8 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
}
}
// Note that all functions taking format strings in the API may be passed ("%s", text) or ("%.*s", text_len, text),
// which will automatically bypass the formatter.
void ImGui::TextUnformatted(const char* text, const char* text_end)
{
TextEx(text, text_end, ImGuiTextFlags_NoWidthForLargeClippedText);
@@ -1272,7 +1274,7 @@ bool ImGui::Checkbox(const char* label, bool* v)
// Range-Selection/Multi-selection support (footer)
if (is_multi_select)
MultiSelectItemFooter(id, &checked, &pressed);
MultiSelectItemFooter(id, &checked, &pressed, ImGuiMultiSelectFlags_CheckboxMode_);
else if (pressed)
checked = !checked;
@@ -1323,7 +1325,7 @@ bool ImGui::CheckboxFlagsT(const char* label, T* flags, T flags_value)
if (!all_on && any_on)
{
ImGuiContext& g = *GImGui;
g.NextItemData.ItemFlags |= ImGuiItemFlags_MixedValue;
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_MixedValue;
pressed = Checkbox(label, &all_on);
}
else
@@ -1575,7 +1577,7 @@ bool ImGui::TextLinkOpenURL(const char* label, const char* url)
bool pressed = TextLink(label);
if (pressed && g.PlatformIO.Platform_OpenInShellFn != NULL)
g.PlatformIO.Platform_OpenInShellFn(&g, url);
SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when we same as label
SetItemTooltip(LocalizeGetMsg(ImGuiLocKey_OpenLink_s), url); // It is more reassuring for user to _always_ display URL when it is the same as the label.
if (BeginPopupContextItem())
{
if (MenuItem(LocalizeGetMsg(ImGuiLocKey_CopyLink)))
@@ -1746,14 +1748,14 @@ void ImGui::SeparatorTextEx(ImGuiID id, const char* label, const char* label_end
const float separator_thickness = style.SeparatorTextBorderSize;
const ImVec2 min_size(label_size.x + extra_w + padding.x * 2.0f, ImMax(label_size.y + padding.y * 2.0f, separator_thickness));
const ImRect bb(pos, ImVec2(window->WorkRect.Max.x, pos.y + min_size.y));
const float text_baseline_y = ImTrunc((bb.GetHeight() - label_size.y) * style.SeparatorTextAlign.y + 0.99999f); //ImMax(padding.y, ImTrunc((style.SeparatorTextSize - label_size.y) * 0.5f));
const float text_baseline_y = ImTrunc((bb.GetHeight() - label_size.y) * style.SeparatorTextAlign.y + 0.999f); //ImMax(padding.y, ImTrunc((style.SeparatorTextSize - label_size.y) * 0.5f));
ItemSize(min_size, text_baseline_y);
if (!ItemAdd(bb, id))
return;
const float sep1_x1 = pos.x;
const float sep2_x2 = bb.Max.x;
const float seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f + 0.99999f);
const float seps_y = ImTrunc((bb.Min.y + bb.Max.y) * 0.5f + 0.999f);
const float label_avail_w = ImMax(0.0f, sep2_x2 - sep1_x1 - padding.x * 2.0f);
const ImVec2 label_pos(pos.x + padding.x + ImMax(0.0f, (label_avail_w - label_size.x - extra_w) * style.SeparatorTextAlign.x), pos.y + text_baseline_y); // FIXME-ALIGN
@@ -3720,8 +3722,9 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
const bool init = (g.TempInputId != id);
if (init)
const bool is_deactivated = (g.InputTextDeactivatedState.ID == id);
const bool is_active = (g.TempInputId == id);
if (!is_active && !is_deactivated)
ClearActiveID();
ImVec2 backup_pos = window->DC.CursorPos;
@@ -3729,13 +3732,13 @@ bool ImGui::TempInputText(const ImRect& bb, ImGuiID id, const char* label, char*
g.LastItemData.ItemFlags |= ImGuiItemFlags_AllowDuplicateId; // Using ImGuiInputTextFlags_MergedItem above will skip ItemAdd() so we poke here.
bool value_changed = InputTextEx(label, NULL, buf, (int)buf_size, bb.GetSize(), flags | ImGuiInputTextFlags_TempInput | ImGuiInputTextFlags_AutoSelectAll, callback, user_data);
KeepAliveID(id); // Not done because of ImGuiInputTextFlags_TempInput
if (init)
if (!is_active && !is_deactivated)
{
// First frame we started displaying the InputText widget, we expect it to take the active id.
IM_ASSERT(g.ActiveId == id);
g.TempInputId = g.ActiveId;
}
if (g.ActiveId != id)
if (is_active && g.ActiveId != id)
g.TempInputId = 0;
window->DC.CursorPos = backup_pos;
return value_changed;
@@ -3760,6 +3763,7 @@ bool ImGui::TempInputScalar(const ImRect& bb, ImGuiID id, const char* label, ImG
ImGuiInputTextFlags flags = ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
g.LastItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited; // Because TempInputText() uses ImGuiInputTextFlags_MergedItem it doesn't submit a new item, so we poke LastItemData.
g.LastItemData.ItemFlags = (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputScalar) ? (g.LastItemData.ItemFlags | ImGuiItemFlags_LiveEditOnInputText) : (g.LastItemData.ItemFlags & ~ImGuiItemFlags_LiveEditOnInputText);
if (!TempInputText(bb, id, label, data_buf, IM_COUNTOF(data_buf), flags))
return false;
@@ -3817,7 +3821,7 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
// Disable the MarkItemEdited() call in InputText but keep ImGuiItemStatusFlags_Edited.
// We call MarkItemEdited() ourselves by comparing the actual data rather than the string.
g.NextItemData.ItemFlags |= ImGuiItemFlags_NoMarkEdited;
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_NoMarkEdited;
flags |= ImGuiInputTextFlags_AutoSelectAll | (ImGuiInputTextFlags)ImGuiInputTextFlags_LocalizeDecimalPoint;
const bool has_step_buttons = (p_step != NULL);
@@ -3839,8 +3843,23 @@ bool ImGui::InputScalar(const char* label, ImGuiDataType data_type, void* p_data
}
// Apply
bool input_edited = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_EditedInternal) != 0; // We would be using 'ret' if ImGuiInputTextFlags_EnterReturnsTrue was not involved.
bool value_changed = input_edited ? DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL) : false;
bool value_changed = false;
if (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputScalar)
{
bool input_edited = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_EditedInternal) != 0; // We would be using 'ret' if ImGuiInputTextFlags_EnterReturnsTrue was not involved.
if (input_edited)
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
}
else
{
//g.LastItemData.StatusFlags &= ~ImGuiItemStatusFlags_Edited;
if (g.DeactivatedItemData.ID == g.LastItemData.ID)
{
//g.DeactivatedItemData.HasBeenEditedBefore = false; // Will be set below by MarkItemEdited()
//if (IsItemDeactivated()) // Should be unnecessary
value_changed = DataTypeApplyFromText(buf, data_type, p_data, format, (flags & ImGuiInputTextFlags_ParseEmptyRefVal) ? p_data_default : NULL);
}
}
// Step buttons
if (has_step_buttons)
@@ -4582,10 +4601,14 @@ void ImGui::InputTextDeactivateHook(ImGuiID id)
{
ImGuiContext& g = *GImGui;
ImGuiInputTextState* state = &g.InputTextState;
if (id == 0 || state->ID != id)
if (id == 0 || state->ID != id || g.ActiveId != id)
return;
if (!state->EditedBefore)
return;
//IMGUI_DEBUG_LOG_ACTIVEID("InputTextDeactivateHook() id = 0x%08X\n", id);
state->EditedBefore = false;
g.InputTextDeactivatedState.ID = state->ID;
g.InputTextDeactivatedState.ElapseFrame = g.FrameCount + 1;
if (state->Flags & ImGuiInputTextFlags_ReadOnly)
{
g.InputTextDeactivatedState.TextA.resize(0); // In theory this data won't be used, but clear to be neat.
@@ -4815,7 +4838,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
const bool user_clicked = hovered && io.MouseClicked[0];
const bool input_requested_by_nav = (g.ActiveId != id) && (g.NavActivateId == id);
const bool input_requested_by_reactivate = (g.InputTextReactivateId == id); // for io.ConfigInputTextEnterKeepActive
const bool input_requested_by_user = (user_clicked) || (g.ActiveId == 0 && (flags & ImGuiInputTextFlags_TempInput));
const bool input_requested_by_user = (user_clicked) || (g.ActiveId == 0 && (flags & ImGuiInputTextFlags_TempInput) && g.InputTextDeactivatedState.ID != id);
const ImGuiID scrollbar_id = (is_multiline && state != NULL) ? GetWindowScrollbarID(draw_window, ImGuiAxis_Y) : 0;
const bool user_scroll_finish = is_multiline && state != NULL && g.ActiveId == 0 && g.ActiveIdPreviousFrame == scrollbar_id;
const bool user_scroll_active = is_multiline && state != NULL && g.ActiveId == scrollbar_id;
@@ -4847,7 +4870,8 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
state->CursorAnimReset();
// Backup state of deactivating item so they'll have a chance to do a write to output buffer on the same frame they report IsItemDeactivatedAfterEdit (#4714)
InputTextDeactivateHook(state->ID);
if (state->ID != id && state->ID == g.ActiveId && (init_make_active && g.ActiveId != id)) //-V560
InputTextDeactivateHook(state->ID); // <-- this is essentially an earlier call to what SetActiveID() would do below.
// Take a copy of the initial buffer value.
// From the moment we focused we are normally ignoring the content of 'buf' (unless we are in read-only mode)
@@ -4974,6 +4998,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (state != NULL && state->ID == id)
{
state->Flags = flags;
//state->LastFrameActive = g.FrameCount;
// Word-wrapping: attempt to keep cursor in view while resizing frame/parent (FIXME-WORDWRAP: would be better to preserve same relative offset)
if (is_wordwrap && state->WrapWidth != wrap_width)
@@ -5171,7 +5196,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
if (!is_new_line)
{
validated = clear_active_id = true;
if (io.ConfigInputTextEnterKeepActive && !is_multiline)
if (io.ConfigInputTextEnterKeepActive && !is_multiline && !is_ctrl_enter && !is_shift_enter)
{
// Queue reactivation, so that e.g. IsItemDeactivatedAfterEdit() will work. (#9001)
state->SelectAll(); // No need to scroll
@@ -5378,18 +5403,33 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
IM_ASSERT(callback_data.BufTextLen == (int)ImStrlen(callback_data.Buf)); // You need to maintain BufTextLen if you change the text!
InputTextReconcileUndoState(state, state->CallbackTextBackup.Data, state->CallbackTextBackup.Size - 1, callback_data.Buf, callback_data.BufTextLen);
state->TextLen = callback_data.BufTextLen; // Assume correct length and valid UTF-8 from user, saves us an extra strlen()
state->EditedBefore = state->EditedThisFrame = true;
state->CursorAnimReset();
}
}
}
// Will copy result string if modified.
// Write back result string if modified.
// FIXME-OPT: Could mark dirty state from the stb_textedit callbacks
if (!is_readonly && strcmp(state->TextSrc, buf) != 0)
if (!is_readonly)
{
apply_new_text = state->TextSrc;
apply_new_text_length = state->TextLen;
value_changed = true;
if (g.LastItemData.ItemFlags & ImGuiItemFlags_LiveEditOnInputText)
{
// Apply when modified
if (strcmp(state->TextSrc, buf) != 0)
{
apply_new_text = state->TextSrc;
apply_new_text_length = state->TextLen;
value_changed = true;
}
}
else
{
// Apply on validation/deactivation, otherwise cancel out previous apply attempts (e.g. revert)
value_changed = ((validated || clear_active_id || revert_edit) && strcmp(state->TextSrc, buf) != 0);
apply_new_text = value_changed ? state->TextSrc : NULL;
apply_new_text_length = value_changed ? state->TextLen : 0;
}
}
}
@@ -5397,13 +5437,15 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// This is used when e.g. losing focus or tabbing out into another InputText() which may already be using the temp buffer.
if (g.InputTextDeactivatedState.ID == id)
{
if (g.ActiveId != id && IsItemDeactivatedAfterEdit() && !is_readonly && strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0)
{
apply_new_text = g.InputTextDeactivatedState.TextA.Data;
apply_new_text_length = g.InputTextDeactivatedState.TextA.Size - 1;
value_changed = true;
//IMGUI_DEBUG_LOG("InputText(): apply Deactivated data for 0x%08X: \"%.*s\".\n", id, apply_new_text_length, apply_new_text);
}
// The state only exists after an Edit. IsItemDeactivatedAfterEdit() is not valid in every code path (see "widgets_inputtext_status_noliveedit" test).
if ((g.ActiveId != id && IsItemDeactivated()) || (g.ActiveId == id && (flags & ImGuiInputTextFlags_TempInput)))
if (!is_readonly && strcmp(g.InputTextDeactivatedState.TextA.Data, buf) != 0)
{
apply_new_text = g.InputTextDeactivatedState.TextA.Data;
apply_new_text_length = g.InputTextDeactivatedState.TextA.Size - 1;
value_changed = true;
//IMGUI_DEBUG_LOG("InputText(): apply Deactivated data for 0x%08X: \"%.*s\".\n", id, apply_new_text_length, apply_new_text);
}
g.InputTextDeactivatedState.ID = 0;
}
@@ -5443,7 +5485,10 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
// Release active ID at the end of the function (so e.g. pressing Return still does a final application of the value)
// Otherwise request text input ahead for next frame.
if (g.ActiveId == id && clear_active_id)
{
state->EditedBefore = false; // Data already applied: avoid InputTextDeactivateHook() taking a record now or later if same id is activated again without editing.
ClearActiveID();
}
// Render frame
if (!is_multiline)
@@ -5641,7 +5686,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
ImVec2 cursor_screen_pos = ImTrunc(draw_pos + cursor_offset - draw_scroll);
ImRect cursor_screen_rect(cursor_screen_pos.x, cursor_screen_pos.y - g.FontSize + 0.5f, cursor_screen_pos.x + 1.0f, cursor_screen_pos.y - 1.5f);
if (cursor_is_visible && cursor_screen_rect.Overlaps(clip_rect))
draw_window->DrawList->AddLineV(cursor_screen_rect.Min.x, cursor_screen_rect.Min.y, cursor_screen_rect.Max.y, GetColorU32(ImGuiCol_InputTextCursor), 1.0f * (float)(int)style._MainScale); // FIXME-DPI: Cursor thickness (#7031)
draw_window->DrawList->AddLineV(cursor_screen_rect.Min.x, cursor_screen_rect.Min.y, cursor_screen_rect.Max.y, GetColorU32(ImGuiCol_InputTextCursor), style.InputTextCursorSize);
// Notify OS of text input position for advanced IME (-1 x offset so that Windows IME can cover our cursor. Bit of an extra nicety.)
// This is required for some backends (SDL3) to start emitting character/text inputs.
@@ -5664,7 +5709,7 @@ bool ImGui::InputTextEx(const char* label, const char* hint, char* buf, int buf_
{
// For focus requests to work on our multiline we need to ensure our child ItemAdd() call specifies the ImGuiItemFlags_Inputable (see #4761, #7870)...
Dummy(ImVec2(0.0f, text_size_y + style.FramePadding.y));
g.NextItemData.ItemFlags |= (ImGuiItemFlags)ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop;
g.NextItemData.ItemFlagsSet |= (ImGuiItemFlags)ImGuiItemFlags_Inputable | ImGuiItemFlags_NoTabStop;
EndChild();
item_data_backup.StatusFlags |= (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_HoveredWindow);
@@ -5749,7 +5794,6 @@ void ImGui::DebugNodeInputTextState(ImGuiInputTextState* state)
// - RenderColorRectWithAlphaCheckerboard() [Internal]
// - ColorPicker4()
// - ColorButton()
// - SetColorEditOptions()
// - ColorTooltip() [Internal]
// - ColorEditOptionsPopup() [Internal]
// - ColorPickerOptionsPopup() [Internal]
@@ -5821,14 +5865,14 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
// Read stored options
if (!(flags & ImGuiColorEditFlags_DisplayMask_))
flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DisplayMask_);
flags |= (g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_DisplayMask_);
if (!(flags & ImGuiColorEditFlags_DataTypeMask_))
flags |= (g.ColorEditOptions & ImGuiColorEditFlags_DataTypeMask_);
flags |= (g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_DataTypeMask_);
if (!(flags & ImGuiColorEditFlags_PickerMask_))
flags |= (g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_);
flags |= (g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_PickerMask_);
if (!(flags & ImGuiColorEditFlags_InputMask_))
flags |= (g.ColorEditOptions & ImGuiColorEditFlags_InputMask_);
flags |= (g.ColorEditOptions & ~(ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_));
flags |= (g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_InputMask_);
flags |= (g.IO.ConfigColorEditFlags & ~(ImGuiColorEditFlags_DisplayMask_ | ImGuiColorEditFlags_DataTypeMask_ | ImGuiColorEditFlags_PickerMask_ | ImGuiColorEditFlags_InputMask_));
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check that only 1 is selected
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected
@@ -6079,7 +6123,7 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImGuiIO& io = g.IO;
const float width = CalcItemWidth();
const bool is_readonly = ((g.NextItemData.ItemFlags | g.CurrentItemFlags) & ImGuiItemFlags_ReadOnly) != 0;
const bool is_readonly = ((g.NextItemData.ItemFlagsSet | g.CurrentItemFlags) & ImGuiItemFlags_ReadOnly) != 0;
g.NextItemData.ClearFlags();
PushID(label);
@@ -6097,13 +6141,13 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
// Read stored options
if (!(flags & ImGuiColorEditFlags_PickerMask_))
flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_PickerMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_PickerMask_;
flags |= ((g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_PickerMask_) ? g.IO.ConfigColorEditFlags : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_PickerMask_;
if (!(flags & ImGuiColorEditFlags_InputMask_))
flags |= ((g.ColorEditOptions & ImGuiColorEditFlags_InputMask_) ? g.ColorEditOptions : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_InputMask_;
flags |= ((g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_InputMask_) ? g.IO.ConfigColorEditFlags : ImGuiColorEditFlags_DefaultOptions_) & ImGuiColorEditFlags_InputMask_;
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check that only 1 is selected
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check that only 1 is selected
if (!(flags & ImGuiColorEditFlags_NoOptions))
flags |= (g.ColorEditOptions & ImGuiColorEditFlags_AlphaBar);
flags |= (g.IO.ConfigColorEditFlags & ImGuiColorEditFlags_AlphaBar);
// Setup
int components = (flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4;
@@ -6125,10 +6169,11 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
ImVec2 wheel_center(picker_pos.x + (sv_picker_size + bars_width)*0.5f, picker_pos.y + sv_picker_size * 0.5f);
// Note: the triangle is displayed rotated with triangle_pa pointing to Hue, but most coordinates stays unrotated for logic.
const bool triangle_rotate = (flags & ImGuiColorEditFlags_PickerNoRotate) == 0;
float triangle_r = wheel_r_inner - (int)(sv_picker_size * 0.027f);
ImVec2 triangle_pa = ImVec2(triangle_r, 0.0f); // Hue point.
ImVec2 triangle_pb = ImVec2(triangle_r * -0.5f, triangle_r * -0.866025f); // Black point.
ImVec2 triangle_pc = ImVec2(triangle_r * -0.5f, triangle_r * +0.866025f); // White point.
ImVec2 triangle_pa = triangle_rotate ? ImVec2(triangle_r, 0.0f) : ImVec2(triangle_r * +0.866f, triangle_r * +0.5f); // Hue point.
ImVec2 triangle_pb = triangle_rotate ? ImVec2(triangle_r * -0.5f, triangle_r * -0.866f) : ImVec2(0.0f, -triangle_r); // Black point.
ImVec2 triangle_pc = triangle_rotate ? ImVec2(triangle_r * -0.5f, triangle_r * +0.866f) : ImVec2(triangle_r * -0.866f, triangle_r * +0.5f); // White point.
float H = col[0], S = col[1], V = col[2];
float R = col[0], G = col[1], B = col[2];
@@ -6163,8 +6208,8 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
H += 1.0f;
value_changed = value_changed_h = true;
}
float cos_hue_angle = ImCos(-H * 2.0f * IM_PI);
float sin_hue_angle = ImSin(-H * 2.0f * IM_PI);
float cos_hue_angle = triangle_rotate ? ImCos(-H * 2.0f * IM_PI) : 1.0f;
float sin_hue_angle = triangle_rotate ? ImSin(-H * 2.0f * IM_PI) : 0.0f;
if (ImTriangleContainsPoint(triangle_pa, triangle_pb, triangle_pc, ImRotate(initial_off, cos_hue_angle, sin_hue_angle)))
{
// Interacting with SV triangle
@@ -6373,6 +6418,11 @@ bool ImGui::ColorPicker4(const char* label, float col[4], ImGuiColorEditFlags fl
draw_list->AddCircleFilled(hue_cursor_pos, hue_cursor_rad, hue_color32, hue_cursor_segments);
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad + 1, col_midgrey, hue_cursor_segments);
draw_list->AddCircle(hue_cursor_pos, hue_cursor_rad, col_white, hue_cursor_segments);
if (triangle_rotate == false)
{
cos_hue_angle = 1.0f;
sin_hue_angle = 0.0f;
}
// Render SV triangle (rotated according to hue)
ImVec2 tra = wheel_center + ImRotate(triangle_pa, cos_hue_angle, sin_hue_angle);
@@ -6523,25 +6573,18 @@ bool ImGui::ColorButton(const char* desc_id, const ImVec4& col, ImGuiColorEditFl
return pressed;
}
// Initialize/override default color options
// FIXME: Could be moved to a simple IO field.
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
// This allowed passing 0 to set default, whereas NewFrame() will assert if one of missing. Abide to old logic.
void ImGui::SetColorEditOptions(ImGuiColorEditFlags flags)
{
ImGuiContext& g = *GImGui;
if ((flags & ImGuiColorEditFlags_DisplayMask_) == 0)
flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DisplayMask_;
if ((flags & ImGuiColorEditFlags_DataTypeMask_) == 0)
flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DataTypeMask_;
if ((flags & ImGuiColorEditFlags_PickerMask_) == 0)
flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_PickerMask_;
if ((flags & ImGuiColorEditFlags_InputMask_) == 0)
flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_InputMask_;
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DisplayMask_)); // Check only 1 option is selected
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_DataTypeMask_)); // Check only 1 option is selected
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_PickerMask_)); // Check only 1 option is selected
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiColorEditFlags_InputMask_)); // Check only 1 option is selected
g.ColorEditOptions = flags;
if ((flags & ImGuiColorEditFlags_DisplayMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DisplayMask_; }
if ((flags & ImGuiColorEditFlags_DataTypeMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_DataTypeMask_; }
if ((flags & ImGuiColorEditFlags_PickerMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_PickerMask_; }
if ((flags & ImGuiColorEditFlags_InputMask_) == 0) { flags |= ImGuiColorEditFlags_DefaultOptions_ & ImGuiColorEditFlags_InputMask_; }
g.IO.ConfigColorEditFlags = flags;
}
#endif
// Note: only access 3 floats if ImGuiColorEditFlags_NoAlpha flag is set.
void ImGui::ColorTooltip(const char* text, const float* col, ImGuiColorEditFlags flags)
@@ -6589,7 +6632,7 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
ImGuiContext& g = *GImGui;
PushItemFlag(ImGuiItemFlags_NoMarkEdited, true);
ImGuiColorEditFlags opts = g.ColorEditOptions;
ImGuiColorEditFlags opts = g.IO.ConfigColorEditFlags;
if (allow_opt_inputs)
{
if (RadioButton("RGB", (opts & ImGuiColorEditFlags_DisplayRGB) != 0)) opts = (opts & ~ImGuiColorEditFlags_DisplayMask_) | ImGuiColorEditFlags_DisplayRGB;
@@ -6629,7 +6672,7 @@ void ImGui::ColorEditOptionsPopup(const float* col, ImGuiColorEditFlags flags)
EndPopup();
}
g.ColorEditOptions = opts;
g.IO.ConfigColorEditFlags = opts;
PopItemFlag();
EndPopup();
}
@@ -6657,7 +6700,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
if (picker_type == 1) picker_flags |= ImGuiColorEditFlags_PickerHueWheel;
ImVec2 backup_pos = GetCursorScreenPos();
if (Selectable("##selectable", false, 0, picker_size)) // By default, Selectable() is closing popup
g.ColorEditOptions = (g.ColorEditOptions & ~ImGuiColorEditFlags_PickerMask_) | (picker_flags & ImGuiColorEditFlags_PickerMask_);
g.IO.ConfigColorEditFlags = (g.IO.ConfigColorEditFlags & ~ImGuiColorEditFlags_PickerMask_) | (picker_flags & ImGuiColorEditFlags_PickerMask_);
SetCursorScreenPos(backup_pos);
ImVec4 previewing_ref_col;
memcpy(&previewing_ref_col, ref_col, sizeof(float) * ((picker_flags & ImGuiColorEditFlags_NoAlpha) ? 3 : 4));
@@ -6669,7 +6712,7 @@ void ImGui::ColorPickerOptionsPopup(const float* ref_col, ImGuiColorEditFlags fl
if (allow_opt_alpha_bar)
{
if (allow_opt_picker) Separator();
CheckboxFlags("Alpha Bar", &g.ColorEditOptions, ImGuiColorEditFlags_AlphaBar);
CheckboxFlags("Alpha Bar", &g.IO.ConfigColorEditFlags, ImGuiColorEditFlags_AlphaBar);
}
PopItemFlag();
EndPopup();
@@ -7114,9 +7157,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
if (hovered || selected)
{
const ImU32 bg_col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false);
RenderFrame(frame_bb.Min, frame_bb.Max, bg_col, false, 0.0f);
}
RenderNavCursor(frame_bb, id, nav_render_cursor_flags);
RenderNavCursor(frame_bb, id, nav_render_cursor_flags, 0.0f);
if (span_all_columns && !span_all_columns_label)
TablePopBackgroundChannel();
if (flags & ImGuiTreeNodeFlags_Bullet)
@@ -7487,6 +7530,11 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
if (selected != was_selected)
g.LastItemData.StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
if (g.ActiveId == id && g.ActiveIdIsJustActivated)
{
g.ActiveIdWasSelected = was_selected;
g.ActiveIdWasSoleSelected = was_selected && (!is_multi_select || g.CurrentMultiSelect->IsSoleOrUnknownSelectionSize);
}
// Render
if (is_visible)
@@ -7496,14 +7544,14 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
{
// Between 1.91.0 and 1.91.4 we made selected Selectable use an arbitrary lerp between _Header and _HeaderHovered. Removed that now. (#8106)
ImU32 col = GetColorU32((held && highlighted) ? ImGuiCol_HeaderActive : highlighted ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
RenderFrame(bb.Min, bb.Max, col, false, style.SelectableRounding);
}
if (g.NavId == id)
{
ImGuiNavRenderCursorFlags nav_render_cursor_flags = ImGuiNavRenderCursorFlags_Compact | ImGuiNavRenderCursorFlags_NoRounding;
ImGuiNavRenderCursorFlags nav_render_cursor_flags = ImGuiNavRenderCursorFlags_Compact;
if (is_multi_select)
nav_render_cursor_flags |= ImGuiNavRenderCursorFlags_AlwaysDraw; // Always show the nav rectangle
RenderNavCursor(bb, id, nav_render_cursor_flags);
RenderNavCursor(bb, id, nav_render_cursor_flags, style.SelectableRounding);
}
}
@@ -8114,6 +8162,7 @@ ImGuiMultiSelectIO* ImGui::BeginMultiSelect(ImGuiMultiSelectFlags flags, int sel
storage->LastSelectionSize = 0;
}
ms->LoopRequestSetAll = request_select_all ? 1 : request_clear ? 0 : -1;
ms->IsSoleOrUnknownSelectionSize = (storage->LastSelectionSize == 1) || (storage->LastSelectionSize == -1);
//ms->PrevSubmittedItem = ImGuiSelectionUserData_Invalid;
if (g.DebugLogFlags & ImGuiDebugLogFlags_EventSelection)
@@ -8217,7 +8266,7 @@ void ImGui::SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_d
if (ImGuiMultiSelectTempData* ms = g.CurrentMultiSelect)
{
// Auto updating RangeSrcPassedBy for cases were clipper is not used (done before ItemAdd() clipping)
g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData | ImGuiItemFlags_IsMultiSelect;
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_HasSelectionUserData | ImGuiItemFlags_IsMultiSelect;
if (ms->IO.RangeSrcItem == selection_user_data)
ms->RangeSrcPassedBy = true;
//ms->PrevSubmittedItem = ms->CurrSubmittedItem; // Can't rely on previous g.NextItemData.SelectionUserData because NextItemData is not restored on nested multi-select.
@@ -8225,7 +8274,7 @@ void ImGui::SetNextItemSelectionUserData(ImGuiSelectionUserData selection_user_d
}
else
{
g.NextItemData.ItemFlags |= ImGuiItemFlags_HasSelectionUserData;
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_HasSelectionUserData;
}
}
@@ -8305,7 +8354,7 @@ void ImGui::MultiSelectItemHeader(ImGuiID id, bool* p_selected, ImGuiButtonFlags
// - Altering selection based on Ctrl/Shift modifiers, both for keyboard and mouse.
// - Record current selection state for RangeSrc
// This is all rather complex, best to run and refer to "widgets_multiselect_xxx" tests in imgui_test_suite.
void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed, ImGuiMultiSelectFlags extra_flags)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
@@ -8325,7 +8374,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
ImGuiSelectionUserData item_data = g.NextItemData.SelectionUserData;
ImGuiMultiSelectFlags flags = ms->Flags;
ImGuiMultiSelectFlags flags = ms->Flags | extra_flags;
const bool is_singleselect = (flags & ImGuiMultiSelectFlags_SingleSelect) != 0;
bool is_ctrl = (ms->KeyMods & ImGuiMod_Ctrl) != 0;
bool is_shift = (ms->KeyMods & ImGuiMod_Shift) != 0;
@@ -8479,7 +8528,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
//IM_ASSERT(storage->HasRangeSrc && storage->HasRangeValue);
if (storage->RangeSrcItem == ImGuiSelectionUserData_Invalid)
storage->RangeSrcItem = item_data;
if ((flags & ImGuiMultiSelectFlags_NoAutoSelect) == 0)
if ((flags & ImGuiMultiSelectFlags_CheckboxMode_) == 0)
{
// Shift+Arrow always select
// Ctrl+Shift+Arrow copy source selection state (already stored by BeginMultiSelect() in storage->RangeSelected)
@@ -8499,7 +8548,7 @@ void ImGui::MultiSelectItemFooter(ImGuiID id, bool* p_selected, bool* p_pressed)
else
{
// Ctrl inverts selection, otherwise always select
if ((flags & ImGuiMultiSelectFlags_NoAutoSelect) == 0)
if ((flags & ImGuiMultiSelectFlags_CheckboxMode_) == 0)
selected = is_ctrl ? !selected : true;
else
selected = !selected;
@@ -8950,7 +8999,7 @@ int ImGui::PlotEx(ImGuiPlotType plot_type, const char* label, float (*values_get
// Tooltip on hover
if (hovered && inner_bb.Contains(g.IO.MousePos))
{
const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.9999f);
const float t = ImClamp((g.IO.MousePos.x - inner_bb.Min.x) / (inner_bb.Max.x - inner_bb.Min.x), 0.0f, 0.999f);
const int v_idx = (int)(t * item_count);
IM_ASSERT(v_idx >= 0 && v_idx < values_count);
@@ -9348,7 +9397,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
return false;
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
ImGuiStyle& style = g.Style;
const ImGuiID id = window->GetID(label);
bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None);
@@ -9380,7 +9429,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
// This is only done for items for the menu set and not the full parent window.
const bool menuset_is_open = IsRootOfOpenMenuSet();
if (menuset_is_open)
PushItemFlag(ImGuiItemFlags_NoWindowHoverableCheck, true);
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_NoWindowHoverableCheck;
// The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu,
// However the final position is going to be different! It is chosen by FindBestWindowPosForPopup().
@@ -9393,6 +9442,8 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
bool pressed;
const float backup_rounding = style.SelectableRounding;
style.SelectableRounding = style.MenuItemRounding;
const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoAutoClosePopups | (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnClick;
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
@@ -9428,6 +9479,7 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
RenderArrow(window->DrawList, ImVec2(text_pos.x + offsets->OffsetMark + extra_w + g.FontSize * 0.30f, text_pos.y), GetColorU32(ImGuiCol_Text), ImGuiDir_Right);
popup_pos = ImVec2(pos.x, text_pos.y - style.WindowPadding.y);
}
style.SelectableRounding = backup_rounding;
if (!enabled)
EndDisabled();
@@ -9440,8 +9492,6 @@ bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled)
}
const bool hovered = (g.HoveredId == id) && enabled && !g.NavHighlightItemUnderNav;
if (menuset_is_open)
PopItemFlag();
bool want_open = false;
bool want_open_nav_init = false;
@@ -9604,7 +9654,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
// See BeginMenuEx() for comments about this.
const bool menuset_is_open = IsRootOfOpenMenuSet();
if (menuset_is_open)
PushItemFlag(ImGuiItemFlags_NoWindowHoverableCheck, true);
g.NextItemData.ItemFlagsSet |= ImGuiItemFlags_NoWindowHoverableCheck;
// We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73),
// but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only.
@@ -9614,6 +9664,8 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
BeginDisabled();
// We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another.
const float backup_rounding = style.SelectableRounding;
style.SelectableRounding = style.MenuItemRounding;
const ImGuiSelectableFlags selectable_flags = (ImGuiSelectableFlags)ImGuiSelectableFlags_SelectOnRelease | (ImGuiSelectableFlags)ImGuiSelectableFlags_SetNavIdOnHover;
ImGuiMenuColumns* offsets = &window->DC.MenuColumns;
if (window->DC.LayoutType == ImGuiLayoutType_Horizontal)
@@ -9636,7 +9688,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
// Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system.)
float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f;
float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f;
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f);
float checkmark_w = IM_TRUNC(g.FontSize * 1.20f); // FIXME: Always accounted for, even in a menu with none, because 'selected' has no neutral setting.
float min_w = offsets->DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame
float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w);
ImVec2 text_pos(pos.x, pos.y + window->DC.CurrLineTextBaseOffset);
@@ -9657,6 +9709,7 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
RenderCheckMark(window->DrawList, text_pos + ImVec2(offsets->OffsetMark + stretch_w + g.FontSize * 0.40f, g.FontSize * 0.134f * 0.5f), GetColorU32(ImGuiCol_Text), g.FontSize * 0.866f);
}
}
style.SelectableRounding = backup_rounding;
// Once dragged, release ActiveId + key ownership. This is to allow the idiom of mouse down a menu, dragging elsewhere, up on some other MenuItem(). (#8233, #9394)
// Could move logic into lower-level ImGuiButtonFlags_AutoReleaseActiveId + ImGuiButtonFlags_AutoReleaseKeyOwner? Easier once we get rid of the Selectable() middle-man here.
@@ -9672,8 +9725,6 @@ bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut
if (!enabled)
EndDisabled();
PopID();
if (menuset_is_open)
PopItemFlag();
return pressed;
}
@@ -10871,13 +10922,9 @@ void ImGui::TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabI
IM_UNUSED(flags);
IM_ASSERT(width > 0.0f);
const float rounding = ImMax(0.0f, ImMin((flags & ImGuiTabItemFlags_Button) ? g.Style.FrameRounding : g.Style.TabRounding, width * 0.5f - 1.0f));
const float y1 = bb.Min.y + 1.0f;
const float y1 = bb.Min.y + 1.0f; // Leave a bit of room in title bars.
const float y2 = bb.Max.y - g.Style.TabBarBorderSize;
draw_list->PathLineTo(ImVec2(bb.Min.x, y2));
draw_list->PathArcToFast(ImVec2(bb.Min.x + rounding, y1 + rounding), rounding, 6, 9);
draw_list->PathArcToFast(ImVec2(bb.Max.x - rounding, y1 + rounding), rounding, 9, 12);
draw_list->PathLineTo(ImVec2(bb.Max.x, y2));
draw_list->PathFillConvex(col);
draw_list->AddRectFilled(bb.Min, ImVec2(bb.Max.x, y2), col, rounding, ImDrawFlags_RoundCornersTop);
if (g.Style.TabBorderSize > 0.0f)
{
draw_list->PathLineTo(ImVec2(bb.Min.x + 0.5f, y2));
-1018
View File
File diff suppressed because it is too large Load Diff
+485
View File
@@ -0,0 +1,485 @@
<Solution>
<Configurations>
<BuildType Name="Debug" />
<BuildType Name="Debug AVX2" />
<BuildType Name="Debug Clang" />
<BuildType Name="Debug Clang AVX2" />
<BuildType Name="Devel" />
<BuildType Name="Devel AVX2" />
<BuildType Name="Devel Clang" />
<BuildType Name="Devel Clang AVX2" />
<BuildType Name="Release" />
<BuildType Name="Release AVX2" />
<BuildType Name="Release Clang" />
<BuildType Name="Release Clang AVX2" />
<Platform Name="ARM64" />
<Platform Name="x64" />
</Configurations>
<Folder Name="/3rdparty/">
<Project Path="3rdparty/ccc/ccc.vcxproj" Id="2589f8ce-ea77-4b73-911e-64074569795b">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/cpuinfo/cpuinfo.vcxproj" Id="7e183337-a7e9-460c-9d3d-568bc9f9bcc1">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/cubeb/cubeb.vcxproj" Id="bf74c473-dc04-44b3-92e8-4145f4e77342">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/d3d12memalloc/d3d12memalloc.vcxproj" Id="d45cec7a-3171-40dd-975d-e1544cf16139">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/demangler/demangler.vcxproj" Id="d31a6dd1-99ca-41d8-a230-1fae913c8989">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/discord-rpc/discord-rpc.vcxproj" Id="e960dfdf-1bd3-4c29-b251-d1a0919c9b09">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/fmt/fmt.vcxproj" Id="449ad25e-424a-4714-babc-68706cdcc33b">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/freesurround/freesurround.vcxproj" Id="1dd0b31f-37f0-4a36-a521-74133aca4737">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/glad/glad.vcxproj" Id="c0293b32-5acf-40f0-aa6c-e6da6f3bf33a">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/imgui/imgui.vcxproj" Id="88fb34ec-845e-4f21-a552-f1573b9ed167">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/libchdr/libchdr.vcxproj" Id="a0d2b3ad-1f72-4ee3-8b5c-f2c358da35f0">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/libzip/libzip.vcxproj" Id="20b2e9fe-f020-42a0-b324-956f5b06ea68">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/lzma/lzma.vcxproj" Id="a4323327-3f2b-4271-83d9-7f9a3c66b6b2">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/rainterface/rainterface.vcxproj" Id="95dd0a0c-d14d-4cff-a593-820ef26efcc8">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/rcheevos/rcheevos.vcxproj" Id="6d5b5ad9-1525-459b-939f-a5e1082af6b3">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/simpleini/simpleini.vcxproj" Id="1ec8b3c0-8fb3-46de-a2e0-a9121203f266">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/soundtouch/SoundTouch.vcxproj" Id="e9b51944-7e6d-4bcd-83f2-7bbd5a46182d">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/vixl/vixl.vcxproj" Id="8906836e-f06e-46e8-b11a-74e5e8c7b8fb">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="*|x64" Project="false" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="3rdparty/zydis/zydis.vcxproj" Id="67d0160c-0fe4-44b9-ac2e-82bbcf4104df">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="*|ARM64" Project="false" />
</Project>
</Folder>
<Project Path="common/common.vcxproj" Id="4639972e-424e-4e13-8b07-ca403c481346">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="pcsx2-gsrunner/pcsx2-gsrunner.vcxproj" Id="bb98bf81-a132-444a-bb81-96d510f433a8">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Project="false" />
</Project>
<Project Path="pcsx2-qt/pcsx2-qt.vcxproj" Id="2a016f21-87ae-4154-8271-1f57e91408e9">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="pcsx2/pcsx2.vcxproj" Id="6c7986c4-3e4d-4dcc-b3c6-6bb12b238995">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
<Project Path="updater/updater.vcxproj" Id="90bbdc04-cc44-4006-b893-06a4fea8ed47">
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
<BuildType Solution="Release|ARM64" Project="Release Clang" />
<Build Solution="Debug AVX2|ARM64" Project="false" />
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
<Build Solution="Debug|ARM64" Project="false" />
<Build Solution="Devel AVX2|ARM64" Project="false" />
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
<Build Solution="Devel|ARM64" Project="false" />
<Build Solution="Release AVX2|ARM64" Project="false" />
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
<Build Solution="Release|ARM64" Project="false" />
</Project>
</Solution>
+21 -3
View File
@@ -4706,6 +4706,7 @@ SCES-50000:
gpuPaletteConversion: 2 # Lots of CLUTs in large textures.
cpuSpriteRenderBW: 1 # Fixes car textures.
cpuSpriteRenderLevel: 1 # Needed for above.
rewriteLargeSTCoords: 1 # Fix reflections on cars.
SCES-50001:
name: "Tekken Tag Tournament"
region: "PAL-M5"
@@ -12966,6 +12967,7 @@ SCUS-97584:
autoFlush: 2
preloadFrameData: 1
nativeScaling: 2 # Fixes post-processing.
halfPixelOffset: 4 # Aligns post bloom.
SCUS-97589:
name: "NBA '08 featuring The Life Vol.3"
region: "NTSC-U"
@@ -20854,6 +20856,9 @@ SLES-52584:
SLES-52585:
name: "Burnout 3 - Takedown"
region: "PAL-F-G-I"
memcardFilters: # Used for storage of network information on the memory card.
- "SLES-52585"
- "PSCD-20001"
clampModes:
vuClampMode: 3 # Fixes buggy lighting in the garage.
gsHWFixes:
@@ -21961,6 +21966,7 @@ SLES-52940:
region: "PAL-M3"
gsHWFixes:
halfPixelOffset: 5 # Fixes double image and aligns glow effects.
nativeScaling: 2 # Fixes depth blur.
SLES-52941:
name: "Gungrave - Overdose"
region: "PAL-M3"
@@ -32168,6 +32174,9 @@ SLKA-25206:
name: "번아웃3 테이크다운"
name-en: "Burnout 3 - Takedown"
region: "NTSC-K"
memcardFilters: # Used for storage of network information on the memory card.
- "SLKA-25206"
- "PSCD-30001"
clampModes:
vuClampMode: 3 # Fixes buggy lighting in the garage.
gsHWFixes:
@@ -35379,6 +35388,7 @@ SLPM-60109:
gpuPaletteConversion: 2 # Lots of CLUTs in large textures.
cpuSpriteRenderBW: 1 # Fixes car textures.
cpuSpriteRenderLevel: 1 # Needed for above.
rewriteLargeSTCoords: 1 # Fix reflections on cars.
SLPM-60112:
name: "フレースヴェルグ [体験版]"
name-sort: "ふれーすヴぇるぐ [たいけんばん]"
@@ -45406,6 +45416,9 @@ SLPM-65719:
name-sort: "ばーんあうと3 ていくだうん"
name-en: "Burnout 3 - Takedown"
region: "NTSC-J"
memcardFilters: # Used for storage of network information on the memory card.
- "SLPM-65719"
- "PSCD-00004"
clampModes:
vuClampMode: 3 # Fixes buggy lighting in the garage.
gsHWFixes:
@@ -45870,6 +45883,7 @@ SLPM-65791:
region: "NTSC-J"
gsHWFixes:
halfPixelOffset: 5 # Fixes double image and aligns glow effects.
nativeScaling: 2 # Fixes depth blur.
SLPM-65793:
name: "SSX3 [EA BEST HITS]"
name-sort: "SSX3 [EA BEST HITS]"
@@ -54797,6 +54811,7 @@ SLPS-20001:
gpuPaletteConversion: 2 # Lots of CLUTs in large textures.
cpuSpriteRenderBW: 1 # Fixes car textures.
cpuSpriteRenderLevel: 1 # Needed for above.
rewriteLargeSTCoords: 1 # Fix reflections on cars.
SLPS-20002:
name: "撞球 ビリヤードマスター2"
name-sort: "どうきゅう びりやーどますたー2"
@@ -60590,7 +60605,6 @@ SLPS-25529:
gsHWFixes:
halfPixelOffset: 4 # Aligns DoF effects.
nativeScaling: 2 # Fixes post effects.
getSkipCount: "GSC_UltramanFightingEvolution"
SLPS-25530:
name: "餓狼伝 Breakblow"
name-sort: "がろうでん Breakblow"
@@ -62328,7 +62342,6 @@ SLPS-25800:
gsHWFixes:
halfPixelOffset: 4 # Aligns DoF effects.
nativeScaling: 2 # Fixes post effects.
getSkipCount: "GSC_UltramanFightingEvolution"
SLPS-25801:
name: "今日からマ王! 眞マ国の休日"
name-sort: "きょうからまおう しんまこくのきゅうじつ"
@@ -63489,6 +63502,7 @@ SLPS-71502:
gpuPaletteConversion: 2 # Lots of CLUTs in large textures.
cpuSpriteRenderBW: 1 # Fixes car textures.
cpuSpriteRenderLevel: 1 # Needed for above.
rewriteLargeSTCoords: 1 # Fix reflections on cars.
SLPS-72501:
name: "ファイナルファンタジーⅩ [MEGA HITS!]"
name-sort: "ふぁいなるふぁんたじー10 [MEGA HITS!]"
@@ -64491,6 +64505,7 @@ SLUS-20002:
gpuPaletteConversion: 2 # Lots of CLUTs in large textures.
cpuSpriteRenderBW: 1 # Fixes car textures.
cpuSpriteRenderLevel: 1 # Needed for above.
rewriteLargeSTCoords: 1 # Fix reflections on cars.
SLUS-20003:
name: "Portal Runner"
region: "NTSC-U"
@@ -69416,6 +69431,7 @@ SLUS-20969:
compat: 5
gsHWFixes:
halfPixelOffset: 5 # Fixes double image and aligns glow effects.
nativeScaling: 2 # Fixes depth blur.
SLUS-20970:
name: "Rumble Roses"
region: "NTSC-U"
@@ -69962,7 +69978,7 @@ SLUS-21050:
compat: 5
memcardFilters: # Used for storage of network information on the memory card.
- "SLUS-21050"
- "PSCD-10088"
- "PSCD10088"
clampModes:
vuClampMode: 3 # Fixes buggy lighting in the garage.
gsHWFixes:
@@ -75948,6 +75964,7 @@ SLUS-29132:
region: "NTSC-U"
gsHWFixes:
halfPixelOffset: 5 # Fixes double image and aligns glow effects.
nativeScaling: 2 # Fixes depth blur.
SLUS-29133:
name: "Namco Transmission Demo Disc Vol.2"
region: "NTSC-U"
@@ -76751,6 +76768,7 @@ TLES-52940:
region: "PAL-E"
gsHWFixes:
halfPixelOffset: 5 # Fixes double image and aligns glow effects.
nativeScaling: 2 # Fixes depth blur.
TLES-53544:
name: "Pro Evolution Soccer 5 Beta Trial Code"
region: "PAL-E"
+6 -1
View File
@@ -403,6 +403,7 @@
030000006d04000011c2000000000000,Logitech WingMan Cordless,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b5,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b2,righttrigger:b7,rightx:a3,righty:a4,x:b4,platform:Windows,
030000006d0400000ac2000000000000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,
03000000380700005645000000000000,Lynx,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000004e3700001101000000000000,M64 Pro Controller,a:b0,x:b1,start:b9,leftshoulder:b3,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,-rightx:b7,+rightx:b8,-righty:b5,+righty:b6,lefttrigger:b2,platform:Windows,
03000000222200006000000000000000,Macally,a:b1,b:b2,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700003888000000000000,Mad Catz Arcade Fightstick TE S Plus PS3,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,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000380700008532000000000000,Mad Catz Arcade Fightstick TE S PS3,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,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -550,7 +551,7 @@
03000000250900000500000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,
030000004c0500006802000000000000,PS3 Controller,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b10,lefttrigger:a3~,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:a4~,rightx:a2,righty:a5,start:b8,x:b3,y:b0,platform:Windows,
030000004f1f00000800000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
03000000632500007505000000000000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000632500007505000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
03000000888800000803000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Windows,
03000000888800000804000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,
030000008f0e00000300000000000000,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
@@ -1023,6 +1024,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006d0400001fc2000000000000,Logitech F710,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
030000006d0400001ac2000004000000,Logitech Precision,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000006d04000018c2000000010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3~,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004e3700001101000000020000,M64 Pro Controller,a:b0,x:b1,start:b9,leftshoulder:b3,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,-rightx:b7,+rightx:b8,-righty:b5,+righty:b6,lefttrigger:b2,platform:Mac OS X,
03000000380700005032000000010000,Mad Catz PS3 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
@@ -1357,6 +1359,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e00008001000011010000,Faceoff Pro Nintendo Switch Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000852100000201000010010000,FF GP1,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
05000000b40400001224000001010000,Flydigi APEX 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b20,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000d73700001424000004010000,Flydigi Direwolf 4,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,paddle1:b12,paddle2:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
@@ -1437,6 +1440,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000341a000005f7000010010000,HuiJia GameCube Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux,
03000000242e0000ff0b000011010000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Linux,
03000000790000004e95000010010000,Hyperkin N64 Adapter,a:b1,b:b2,start:b9,leftshoulder:b7,rightshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightx:a5,righty:a2,dpup:b12,dpdown:b14,dpleft:b15,dpright:b13,platform:Linux,
03000000242e00006a38000010010000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Linux,
03000000242e00008816000001010000,Hyperkin X91,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
03000000f00300008d03000011010000,HyperX Clutch,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,
@@ -1483,6 +1487,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006d04000019c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006d0400000ac2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,rightx:a3,righty:a4,x:b3,y:b4,platform:Linux,
030000006d04000011c2000010010000,Logitech WingMan RumblePad,a:b0,b:b1,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b5,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b10,rightx:a3,righty:a4,start:b8,x:b3,y:b4,platform:Linux,
050000004e3700001101000000020000,M64 Pro Controller,a:b0,x:b1,start:b9,leftshoulder:b3,rightshoulder:b4,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,-rightx:b7,+rightx:b8,-righty:b5,+righty:b6,lefttrigger:b2,platform:Linux,
05000000380700006652000025010000,Mad Catz CTRLR,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000380700008532000010010000,Mad Catz Fightpad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
03000000380700005032000011010000,Mad Catz Fightpad Pro PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+21 -9
View File
@@ -169,6 +169,11 @@ float depth32_to_depth24(float d)
return uint_to_depth24(depth_to_uint(d));
}
float4 primid_to_rgba8(float p)
{
return uint_to_rgba8(asuint(p));
}
#if defined(__ps_copy__)
OUTPUT_TYPE ps_copy(PS_INPUT input) : OUTPUT_SV
{
@@ -323,6 +328,13 @@ OUTPUT_TYPE ps_convert_depth32_depth24(PS_INPUT input) : OUTPUT_SV
}
#endif
#if defined(__ps_convert_primid_rgba8__)
OUTPUT_TYPE ps_convert_primid_rgba8(PS_INPUT input) : OUTPUT_SV
{
return primid_to_rgba8(sample_c(input.t));
}
#endif
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
uint width, height; \
Texture.GetDimensions(width, height); \
@@ -334,7 +346,7 @@ OUTPUT_TYPE ps_convert_depth32_depth24(PS_INPUT input) : OUTPUT_SV
float depthTR = CONVERT_FN(Texture.Load(int3(coords.zy, 0))); \
float depthBL = CONVERT_FN(Texture.Load(int3(coords.xw, 0))); \
float depthBR = CONVERT_FN(Texture.Load(int3(coords.zw, 0))); \
return lerp(lerp(depthTL, depthTR, mix_vals.x), lerp(depthBL, depthBR, mix_vals.x), mix_vals.y);
return floor(lerp(lerp(depthTL, depthTR, mix_vals.x), lerp(depthBL, depthBR, mix_vals.x), mix_vals.y) * exp2(32.0f)) * exp2(-32.0f);
#if defined(__ps_convert_rgba8_depth32__)
OUTPUT_TYPE ps_convert_rgba8_depth32(PS_INPUT input) : OUTPUT_SV
@@ -650,9 +662,9 @@ float ps_primid_image_init_0(PS_INPUT input) : SV_Target
{
float c;
if ((127.5f / 255.0f) < sample_c(input.t).a) // < 0x80 pass (== 0x80 should not pass)
c = float(-1);
c = float(PRIMID_MIN);
else
c = float(0x7FFFFFFF);
c = float(PRIMID_MAX);
return c;
}
#endif
@@ -662,9 +674,9 @@ float ps_primid_image_init_1(PS_INPUT input) : SV_Target
{
float c;
if (sample_c(input.t).a < (127.5f / 255.0f)) // >= 0x80 pass
c = float(-1);
c = float(PRIMID_MIN);
else
c = float(0x7FFFFFFF);
c = float(PRIMID_MAX);
return c;
}
#endif
@@ -674,9 +686,9 @@ float ps_primid_image_init_2(PS_INPUT input) : SV_Target
{
float c;
if ((254.5f / 255.0f) < sample_c(input.t).a) // < 0x80 pass (== 0x80 should not pass)
c = float(-1);
c = float(PRIMID_MIN);
else
c = float(0x7FFFFFFF);
c = float(PRIMID_MAX);
return c;
}
#endif
@@ -686,9 +698,9 @@ float ps_primid_image_init_3(PS_INPUT input) : SV_Target
{
float c;
if (sample_c(input.t).a < (254.5f / 255.0f)) // >= 0x80 pass
c = float(-1);
c = float(PRIMID_MIN);
else
c = float(0x7FFFFFFF);
c = float(PRIMID_MAX);
return c;
}
#endif
+5 -3
View File
@@ -1097,8 +1097,11 @@ void ps_fbmask(inout float4 C, float2 pos_xy)
{
if (PS_FBMASK)
{
float multi = PS_COLCLIP_HW ? 65535.0f : 255.0f;
float4 RT = trunc(RtLoad(int2(pos_xy)) * multi + 0.1f);
float multi_rgb = PS_COLCLIP_HW ? 65535.0f : 255.0f;
float multi_a = PS_RTA_CORRECTION ? 128.0f : 255.0f;
float4 RT = RtLoad(int2(pos_xy));
RT.rgb = trunc(RT.rgb * multi_rgb + 0.1f);
RT.a = round(RT.a * multi_a);
C = (float4)(((uint4)C & ~FbMask) | ((uint4)RT & FbMask));
}
}
@@ -1594,7 +1597,6 @@ if (bad)
output.c1 = o_col1;
#endif
#elif PS_RETURN_COLOR_ROV
o_col0 = (FbMask == 0xFFu) ? RtLoad(input.p.xy) : o_col0; // channel masking
if (!rov_discard_color)
RtWrite(input.p.xy, o_col0);
#endif
+18 -6
View File
@@ -139,6 +139,11 @@ float depth32_to_depth24(float d)
return uint_to_depth24(depth_to_uint(d));
}
vec4 primid_to_rgba8(float p)
{
return uint_to_rgba8(floatBitsToUint(p));
}
#ifdef ps_copy
void ps_copy()
{
@@ -212,6 +217,13 @@ void ps_convert_depth32_depth24()
}
#endif
#ifdef ps_convert_primid_rgba8
void ps_convert_primid_rgba8()
{
OUTPUT = primid_to_rgba8(sample_c());
}
#endif
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
ivec2 dims = textureSize(TextureSampler, 0); \
vec2 top_left_f = PSin_t * vec2(dims) - 0.5f; \
@@ -222,7 +234,7 @@ void ps_convert_depth32_depth24()
float depthTR = CONVERT_FN(texelFetch(TextureSampler, coords.zy, 0)); \
float depthBL = CONVERT_FN(texelFetch(TextureSampler, coords.xw, 0)); \
float depthBR = CONVERT_FN(texelFetch(TextureSampler, coords.zw, 0)); \
OUTPUT = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
OUTPUT = floor(mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y) * exp2(32.0f)) * exp2(-32.0f);
#ifdef ps_convert_rgba8_depth32
void ps_convert_rgba8_depth32()
@@ -615,23 +627,23 @@ void ps_yuv()
void main()
{
o_col0 = vec4(0x7FFFFFFF);
o_col0 = vec4(PRIMID_MAX);
#ifdef ps_primid_image_init_0
if((127.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_1
if(sample_c().a < (127.5f / 255.0f)) // >= 0x80 pass
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_2
if((254.5f / 255.0f) < sample_c().a) // < 0x80 pass (== 0x80 should not pass)
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_3
if(sample_c().a < (254.5f / 255.0f)) // >= 0x80 pass
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
}
#endif
+5 -5
View File
@@ -932,11 +932,11 @@ void ps_fbmask(inout vec4 C)
{
// FIXME do I need special case for 16 bits
#if PS_FBMASK
#if PS_COLCLIP_HW == 1
vec4 RT = trunc(sample_from_rt() * 65535.0f);
#else
vec4 RT = trunc(sample_from_rt() * 255.0f + 0.1f);
#endif
float multi_rgb = PS_COLCLIP_HW != 0 ? 65535.0f : 255.0f;
float multi_a = PS_RTA_CORRECTION != 0 ? 128.0f : 255.0f;
vec4 RT = sample_from_rt();
RT.rgb = trunc(RT.rgb * multi_rgb + 0.1f);
RT.a = round(RT.a * multi_a);
C = vec4((uvec4(C) & ~FbMask) | (uvec4(RT) & FbMask));
#endif
}
+18 -6
View File
@@ -130,6 +130,11 @@ float depth32_to_depth24(float d)
return uint_to_depth24(depth_to_uint(d));
}
vec4 primid_to_rgba8(float p)
{
return uint_to_rgba8(floatBitsToUint(p));
}
#ifdef ps_copy
void ps_copy()
{
@@ -281,6 +286,13 @@ void ps_convert_depth32_depth24()
}
#endif
#ifdef ps_convert_primid_rgba8
void ps_convert_primid_rgba8()
{
OUTPUT = primid_to_rgba8(sample_c(v_tex));
}
#endif
#define SAMPLE_RGBA_DEPTH_BILN(CONVERT_FN) \
ivec2 dims = textureSize(samp0, 0); \
vec2 top_left_f = v_tex * vec2(dims) - 0.5f; \
@@ -291,7 +303,7 @@ void ps_convert_depth32_depth24()
float depthTR = CONVERT_FN(texelFetch(samp0, coords.zy, 0)); \
float depthBL = CONVERT_FN(texelFetch(samp0, coords.xw, 0)); \
float depthBR = CONVERT_FN(texelFetch(samp0, coords.zw, 0)); \
OUTPUT = mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
OUTPUT = floor(mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y) * exp2(32.0f)) * exp2(-32.0f);
#ifdef ps_convert_rgba8_depth32
void ps_convert_rgba8_depth32()
@@ -628,23 +640,23 @@ void ps_yuv()
void main()
{
o_col0 = vec4(0x7FFFFFFF);
o_col0 = vec4(PRIMID_MAX);
#ifdef ps_primid_image_init_0
if((127.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_1
if(sample_c(v_tex).a < (127.5f / 255.0f)) // >= 0x80 pass
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_2
if((254.5f / 255.0f) < sample_c(v_tex).a) // < 0x80 pass (== 0x80 should not pass)
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
#ifdef ps_primid_image_init_3
if(sample_c(v_tex).a < (254.5f / 255.0f)) // >= 0x80 pass
o_col0 = vec4(-1);
o_col0 = vec4(PRIMID_MIN);
#endif
}
#endif
+5 -7
View File
@@ -1448,11 +1448,11 @@ 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
vec4 RT = trunc(sample_from_rt() * 255.0f + 0.1f);
#endif
float multi_rgb = PS_COLCLIP_HW != 0 ? 65535.0f : 255.0f;
float multi_a = PS_RTA_CORRECTION != 0 ? 128.0f : 255.0f;
vec4 RT = sample_from_rt();
RT.rgb = trunc(RT.rgb * multi_rgb + 0.1f);
RT.a = round(RT.a * multi_a);
C = vec4((uvec4(C) & ~FbMask) | (uvec4(RT) & FbMask));
#endif
}
@@ -1966,8 +1966,6 @@ void main()
// Writing back color (result already written to o_col0 for non-ROV)
#if PS_RETURN_COLOR_ROV
o_col0 = mix(o_col0, sample_from_rt(), equal(FbMask, uvec4(0xFFu))); // channel masking
if (!rov_discard_color)
imageStore(RtImageRov, ivec2(gl_FragCoord.xy), o_col0);
#endif
+1 -1
View File
@@ -104,7 +104,7 @@ disable_compiler_warnings_for_target(speex)
# Find the Qt components that we need.
if(ENABLE_QT_UI)
find_package(Qt6 6.10.1 COMPONENTS CoreTools Core GuiTools Gui WidgetsTools Widgets LinguistTools REQUIRED)
find_package(Qt6 6.10 COMPONENTS CoreTools Core GuiTools Gui WidgetsTools Widgets LinguistTools REQUIRED)
if(NOT WIN32 AND NOT APPLE)
if (Qt6_VERSION VERSION_GREATER_EQUAL 6.10.0)
+3 -110
View File
@@ -62,7 +62,6 @@ namespace GSRunner
static bool InitializeConfig();
static void SettingsOverride();
static bool ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& params);
static void DumpStats();
static bool CreatePlatformWindow();
static void DestroyPlatformWindow();
@@ -80,43 +79,11 @@ static std::string s_output_prefix;
static s32 s_loop_count = 1;
static std::optional<bool> s_use_window;
static bool s_no_console = false;
static bool s_perf_enable = false;
// Owned by the GS thread.
static u32 s_dump_frame_number = 0;
static u32 s_loop_number = s_loop_count;
static double s_last_internal_draws = 0;
static double s_last_draws = 0;
static double s_last_render_passes = 0;
static double s_last_barriers = 0;
static double s_last_copies = 0;
static double s_last_uploads = 0;
static double s_last_readbacks = 0;
static double s_last_depth_copies_rov = 0;
static double s_last_draws_rov = 0;
static double s_last_barriers_rov = 0;
static u64 s_total_internal_draws = 0;
static u64 s_total_draws = 0;
static u64 s_total_render_passes = 0;
static u64 s_total_barriers = 0;
static u64 s_total_copies = 0;
static u64 s_total_uploads = 0;
static u64 s_total_readbacks = 0;
static u64 s_total_copies_rov = 0;
static u64 s_total_draws_rov = 0;
static u64 s_total_barriers_rov = 0;
static u32 s_total_frames = 0;
static u32 s_total_drawn_frames = 0;
static bool s_perf_enable = false;
static float s_perf_updates = 0.0f;
static float s_perf_sum_fps = 0.0f;
static float s_perf_sum_internal_fps = 0.0f;
static float s_perf_sum_cpu_thread_usage = 0.0f;
static float s_perf_sum_cpu_thread_time = 0.0f;
static float s_perf_sum_gs_thread_usage = 0.0f;
static float s_perf_sum_gs_thread_time = 0.0f;
static float s_perf_sum_gpu_time = 0.0f;
static float s_perf_sum_gpu_usage = 0.0f;
bool GSRunner::InitializeConfig()
{
@@ -278,39 +245,6 @@ void Host::BeginPresentFrame()
std::string dump_path(fmt::format("{}_frame{:05}.png", s_output_prefix, s_dump_frame_number));
GSQueueSnapshot(dump_path);
}
if (GSIsHardwareRenderer())
{
const u32 last_draws = s_total_internal_draws;
const u32 last_uploads = s_total_uploads;
static constexpr auto update_stat = [](GSPerfMon::counter_t counter, u64& dst, double& last) {
// perfmon resets every 30 frames to zero
const double val = g_perfmon.GetCounter(counter);
dst += static_cast<u64>((val < last) ? val : (val - last));
last = val;
};
update_stat(GSPerfMon::Draw, s_total_internal_draws, s_last_internal_draws);
update_stat(GSPerfMon::DrawCalls, s_total_draws, s_last_draws);
update_stat(GSPerfMon::RenderPasses, s_total_render_passes, s_last_render_passes);
update_stat(GSPerfMon::Barriers, s_total_barriers, s_last_barriers);
update_stat(GSPerfMon::TextureCopies, s_total_copies, s_last_copies);
update_stat(GSPerfMon::TextureUploads, s_total_uploads, s_last_uploads);
update_stat(GSPerfMon::Readbacks, s_total_readbacks, s_last_readbacks);
update_stat(GSPerfMon::TextureCopiesROV, s_total_copies_rov, s_last_depth_copies_rov);
update_stat(GSPerfMon::DrawCallsROV, s_total_draws_rov, s_last_draws_rov);
update_stat(GSPerfMon::BarriersROV, s_total_barriers_rov, s_last_barriers_rov);
const bool idle_frame = s_total_frames && (last_draws == s_total_internal_draws && last_uploads == s_total_uploads);
if (!idle_frame)
s_total_drawn_frames++;
s_total_frames++;
std::atomic_thread_fence(std::memory_order_release);
}
}
void Host::RequestResizeHostDisplay(s32 width, s32 height)
@@ -344,18 +278,6 @@ void Host::OnGameChanged(const std::string& title, const std::string& elf_overri
void Host::OnPerformanceMetricsUpdated()
{
if (s_perf_enable)
{
s_perf_updates += 1.0f;
s_perf_sum_fps += PerformanceMetrics::GetFPS();
s_perf_sum_internal_fps += PerformanceMetrics::GetInternalFPS();
s_perf_sum_cpu_thread_usage += PerformanceMetrics::GetCPUThreadUsage();
s_perf_sum_cpu_thread_time += PerformanceMetrics::GetCPUThreadAverageTime();
s_perf_sum_gs_thread_usage += PerformanceMetrics::GetGSThreadUsage();
s_perf_sum_gs_thread_time += PerformanceMetrics::GetGSThreadAverageTime();
s_perf_sum_gpu_time += PerformanceMetrics::GetGPUAverageTime();
s_perf_sum_gpu_usage += PerformanceMetrics::GetGPUUsage();
}
}
void Host::OnSaveStateLoading(const std::string_view filename)
@@ -655,6 +577,7 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
{
s_loop_count = StringUtil::FromChars<s32>(argv[++i]).value_or(0);
Console.WriteLn("Looping dump playback %d times.", s_loop_count);
s_settings_interface.SetIntValue("EmuCore/GS", "DumpReplayLoopCount", s_loop_count);
continue;
}
else if (CHECK_ARG_PARAM("-renderer"))
@@ -907,34 +830,6 @@ void GSRunner::SettingsOverride()
}
}
void GSRunner::DumpStats()
{
std::atomic_thread_fence(std::memory_order_acquire);
Console.WriteLn(fmt::format("======= HW STATISTICS FOR {} ({}) FRAMES ========", s_total_frames, s_total_drawn_frames));
Console.WriteLn(fmt::format("@HWSTAT@ Draw Calls: {} (avg {})", s_total_draws, static_cast<u64>(std::ceil(s_total_draws / static_cast<double>(s_total_drawn_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Render Passes: {} (avg {})", s_total_render_passes, static_cast<u64>(std::ceil(s_total_render_passes / static_cast<double>(s_total_drawn_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Barriers: {} (avg {})", s_total_barriers, static_cast<u64>(std::ceil(s_total_barriers / static_cast<double>(s_total_drawn_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Copies: {} (avg {})", s_total_copies, static_cast<u64>(std::ceil(s_total_copies / static_cast<double>(s_total_drawn_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Uploads: {} (avg {})", s_total_uploads, static_cast<u64>(std::ceil(s_total_uploads / static_cast<double>(s_total_drawn_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Readbacks: {} (avg {})", s_total_readbacks, static_cast<u64>(std::ceil(s_total_readbacks / static_cast<double>(s_total_drawn_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Copies (ROV): {} (avg {})", s_total_copies_rov, static_cast<u64>(std::ceil(s_total_copies_rov / static_cast<double>(s_total_drawn_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Draws Calls (ROV): {} (avg {})", s_total_draws_rov, static_cast<u64>(std::ceil(s_total_draws_rov / static_cast<double>(s_total_drawn_frames)))));
Console.WriteLn(fmt::format("@HWSTAT@ Barriers (ROV): {} (avg {})", s_total_barriers_rov, static_cast<u64>(std::ceil(s_total_barriers_rov / static_cast<double>(s_total_drawn_frames)))));
if (s_perf_enable)
{
Console.WriteLn(fmt::format("@HWSTAT@ Minimum Frame Time: {:.3f} ms ({:.3f} FPS)", PerformanceMetrics::GetMinimumFrameTime(), 1000.0f / PerformanceMetrics::GetMinimumFrameTime()));
Console.WriteLn(fmt::format("@HWSTAT@ Average Frame Time: {:.3f} ms ({:.3f} FPS)", PerformanceMetrics::GetAverageFrameTime(), 1000.0f / PerformanceMetrics::GetAverageFrameTime()));
Console.WriteLn(fmt::format("@HWSTAT@ Maximum Frame Time: {:.3f} ms ({:.3f} FPS)", PerformanceMetrics::GetMaximumFrameTime(), 1000.0f / PerformanceMetrics::GetMaximumFrameTime()));
Console.WriteLn(fmt::format("@HWSTAT@ CPU Thread Usage: {:.3f} %", s_perf_sum_cpu_thread_usage / s_perf_updates));
Console.WriteLn(fmt::format("@HWSTAT@ GS Thread Usage: {:.3f} %", s_perf_sum_gs_thread_usage / s_perf_updates));
Console.WriteLn(fmt::format("@HWSTAT@ GPU Usage: {:.3f} %", s_perf_sum_gpu_usage / s_perf_updates));
Console.WriteLn(fmt::format("@HWSTAT@ Average CPU Thread Time: {:.3f} ms", s_perf_sum_cpu_thread_time / s_perf_updates));
Console.WriteLn(fmt::format("@HWSTAT@ Average GS Thread Time: {:.3f} ms", s_perf_sum_gs_thread_time / s_perf_updates));
Console.WriteLn(fmt::format("@HWSTAT@ Average GPU Time: {:.3f} ms", s_perf_sum_gpu_time / s_perf_updates));
}
Console.WriteLn("============================================");
}
#ifdef _WIN32
// We can't handle unicode in filenames if we don't use wmain on Win32.
#define main real_main
@@ -948,12 +843,11 @@ static void CPUThreadMain(VMBootParameters* params, std::atomic<int>* ret)
{
// apply new settings (e.g. pick up renderer change)
VMManager::ApplySettings();
GSDumpReplayer::SetIsDumpRunner(true);
GSDumpReplayer::SetIsDumpRunner(true, s_perf_enable);
if (VMManager::Initialize(*params) == VMBootResult::StartupSuccess)
{
// run until end
GSDumpReplayer::SetLoopCount(s_loop_count);
VMManager::SetState(VMState::Running);
if (s_perf_enable)
{
@@ -963,7 +857,6 @@ static void CPUThreadMain(VMBootParameters* params, std::atomic<int>* ret)
while (VMManager::GetState() == VMState::Running)
VMManager::Execute();
VMManager::Shutdown(false);
GSRunner::DumpStats();
ret->store(EXIT_SUCCESS);
}
}
+113 -1
View File
@@ -15,7 +15,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<widget class="QGroupBox" name="groupBoxDrawDumping">
<property name="title">
<string>Draw Dumping</string>
</property>
@@ -240,6 +240,118 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxDumpReplay">
<property name="title">
<string>Dump Replay Options</string>
</property>
<layout class="QFormLayout" name="formLayoutDumpReplay">
<item row="0" column="0" colspan="2">
<layout class="QGridLayout" name="gridLayoutDumpReplay">
<item row="0" column="0">
<widget class="QCheckBox" name="replayUseFrameRange">
<property name="text">
<string>Use Frame Range</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelDumpReplay1">
<property name="text">
<string>Replay Frame Start:</string>
</property>
<property name="buddy">
<cstring>replayFrameStart</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="replayFrameStart">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99999999</number>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelDumpReplay2">
<property name="text">
<string>Replay Frame End:</string>
</property>
<property name="buddy">
<cstring>replayFrameEnd</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="replayFrameEnd">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99999999</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelDumpReplay3">
<property name="text">
<string>Replay Loop Count:</string>
</property>
<property name="buddy">
<cstring>replayLoopCount</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSpinBox" name="replayLoopCount">
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99999999</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBoxPerfMetrics">
<property name="title">
<string>Performance Metrics Options</string>
</property>
<layout class="QFormLayout" name="formLayoutPerfMetrics">
<item row="1" column="0">
<widget class="QLabel" name="labelPerfMetrics1">
<property name="text">
<string>Saved Metrics Capture Time:</string>
</property>
<property name="buddy">
<cstring>savedMetricsCaptureSeconds</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSpinBox" name="savedMetricsCaptureSeconds">
<property name="suffix">
<string> seconds</string>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>99999999</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
+17
View File
@@ -159,6 +159,16 @@ DebugSettingsWidget::DebugSettingsWidget(SettingsWindow* settings_dialog, QWidge
tr("Destination directory for dumps generated by the hardware renderer."));
dialog()->registerWidgetHelp(m_gs.swDumpDirectory, tr("Software Dump Directory"), tr("Default"),
tr("Destination directory for dumps generated by the software renderer."));
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.replayUseFrameRange, "EmuCore/GS", "DumpReplayUseFrameRange", false);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.replayFrameStart, "EmuCore/GS", "DumpReplayFrameStart", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.replayFrameEnd, "EmuCore/GS", "DumpReplayFrameEnd", 0);
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.replayLoopCount, "EmuCore/GS", "DumpReplayLoopCount", 0);
connect(m_gs.replayUseFrameRange, &QCheckBox::checkStateChanged, this, &DebugSettingsWidget::onDumpReplayUseFrameRangeChanged);
onDumpReplayUseFrameRangeChanged();
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.savedMetricsCaptureSeconds, "EmuCore/GS", "SavedMetricsCaptureSeconds", 10);
#ifdef PCSX2_DEVBUILD
//////////////////////////////////////////////////////////////////////////
@@ -268,6 +278,13 @@ void DebugSettingsWidget::onDrawDumpingChanged()
m_gs.swDumpOpen->setEnabled(enabled);
}
void DebugSettingsWidget::onDumpReplayUseFrameRangeChanged()
{
const bool enabled = dialog()->getEffectiveBoolValue("EmuCore/GS", "DumpReplayUseFrameRange", false);
m_gs.replayFrameStart->setEnabled(enabled);
m_gs.replayFrameEnd->setEnabled(enabled);
}
#ifdef PCSX2_DEVBUILD
void DebugSettingsWidget::onLoggingEnableChanged()
{
+1
View File
@@ -23,6 +23,7 @@ public:
private Q_SLOTS:
void onDrawDumpingChanged();
void onDumpReplayUseFrameRangeChanged();
#ifdef PCSX2_DEVBUILD
void onLoggingEnableChanged();
#endif
@@ -33,6 +33,7 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* settings_dialog
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.syncToHostRefreshRate, "EmuCore/GS", "SyncToHostRefreshRate", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useVSyncForTiming, "EmuCore/GS", "UseVSyncForTiming", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.skipPresentingDuplicateFrames, "EmuCore/GS", "SkipDuplicateFrames", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.advancedFrameDisplay, "EmuCore/GS", "AdvancedFrameDisplay", false);
connect(m_ui.optimalFramePacing, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::onOptimalFramePacingChanged);
connect(m_ui.vsync, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::updateUseVSyncForTimingEnabled);
connect(m_ui.syncToHostRefreshRate, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::updateUseVSyncForTimingEnabled);
@@ -155,6 +156,11 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* settings_dialog
"rendered, it just means the GPU has more time to complete it (this is NOT frame skipping). Can smooth out frame time "
"fluctuations when the CPU/GPU are near maximum utilization, but makes frame pacing more inconsistent and can increase "
"input lag. Helps when using frame generation on 25/30fps games."));
dialog()->registerWidgetHelp(m_ui.advancedFrameDisplay, tr("Advanced Frame Display"), tr("Unchecked"),
tr("Displays the newest frame immediately at the beginning of the "
"frame raster time, instead of at the end. Can reduce perceived "
"input lag, but may cause problems with some games, such as "
"Soulcalibur II and Baldur's Gate Dark Alliance II."));
dialog()->registerWidgetHelp(m_ui.manuallySetRealTimeClock, tr("Manually Set Real-Time Clock"), tr("Unchecked"),
tr("Manually set a real-time clock to use for the virtual PlayStation 2 instead of using your OS' system clock."));
dialog()->registerWidgetHelp(m_ui.rtcDateTime, tr("Real-Time Clock"), tr("Current date and time"),
@@ -263,6 +263,13 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="advancedFrameDisplay">
<property name="text">
<string>Advanced Frame Display</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
@@ -271,6 +271,13 @@
</item>
<item row="7" column="0" colspan="2">
<layout class="QGridLayout" name="hwFixesLayout">
<item row="5" column="0">
<widget class="QCheckBox" name="rewriteLargeSTCoords">
<property name="text">
<string>Rewrite Large ST</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="drawBuffering">
<property name="text">
@@ -389,6 +396,7 @@
<tabstop>disableRenderFixes</tabstop>
<tabstop>readTCOnClose</tabstop>
<tabstop>estimateTextureRegion</tabstop>
<tabstop>rewriteLargeSTCoords</tabstop>
</tabstops>
<resources/>
<connections/>
@@ -155,6 +155,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.readTCOnClose, "EmuCore/GS", "UserHacks_ReadTCOnClose", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.estimateTextureRegion, "EmuCore/GS", "UserHacks_EstimateTextureRegion", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.drawBuffering, "EmuCore/GS", "UserHacks_DrawBuffering", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.rewriteLargeSTCoords, "EmuCore/GS", "UserHacks_RewriteLargeSTCoords", false);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_fixes.gpuPaletteConversion, "EmuCore/GS", "paltex", false);
connect(m_fixes.cpuSpriteRenderBW, &QComboBox::currentIndexChanged, this,
&GraphicsSettingsWidget::onCPUSpriteRenderBWChanged);
@@ -636,6 +637,9 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* settings_dialog,
dialog()->registerWidgetHelp(m_fixes.drawBuffering, tr("Draw Buffering"), tr("Unchecked"),
tr("Attempts to reduce draw calls in games which do heavy context switching for blending purposes."));
dialog()->registerWidgetHelp(m_fixes.rewriteLargeSTCoords, tr("Rewrite Large ST"), tr("Unchecked"),
tr("Rewrite large ST coordinates and clamp the values (mainly for Ridge Racer V and Destruction Derby Arena)."));
}
// Upscaling Fixes tab
File diff suppressed because it is too large Load Diff
+28 -25
View File
@@ -136,7 +136,7 @@ namespace Achievements
// Size of the EE physical memory exposed to RetroAchievements.
static u32 GetExposedEEMemorySize();
static bool CreateClient(rc_client_t** client, std::unique_ptr<HTTPDownloader>* http);
static bool CreateClient(rc_client_t** client, std::unique_ptr<HTTPDownloader>* http, const std::string& custom_host);
static void DestroyClient(rc_client_t** client, std::unique_ptr<HTTPDownloader>* http);
static void ClientMessageCallback(const char* message, const rc_client_t* client);
static uint32_t ClientReadMemory(uint32_t address, uint8_t* buffer, uint32_t num_bytes, rc_client_t* client);
@@ -433,28 +433,8 @@ bool Achievements::Initialize()
EnsureCacheDirectoriesExist();
auto lock = GetLock();
pxAssertRel(EmuConfig.Achievements.Enabled, "Achievements are enabled");
pxAssertRel(!s_client && !s_http_downloader, "No client and downloader");
if (!CreateClient(&s_client, &s_http_downloader))
return false;
// Hardcore starts off. We enable it on first boot.
s_hardcore_mode = false;
rc_client_set_event_handler(s_client, ClientEventHandler);
rc_client_set_hardcore_enabled(s_client, s_hardcore_mode);
rc_client_set_encore_mode_enabled(s_client, EmuConfig.Achievements.EncoreMode);
rc_client_set_unofficial_enabled(s_client, EmuConfig.Achievements.UnofficialTestMode);
rc_client_set_spectator_mode_enabled(s_client, EmuConfig.Achievements.SpectatorMode);
// Begin disc identification early, before the login finishes.
if (VMManager::HasValidVM())
IdentifyGame(VMManager::GetDiscCRC(), VMManager::GetCurrentCRC());
const std::string username = Host::GetBaseStringSettingValue("Achievements", "Username");
const std::string custom_host = Host::GetBaseStringSettingValue("Achievements", "Host", "");
// Check the base settings file to see if the token is defined inside. Move if found.
std::string oldToken = Host::GetBaseStringSettingValue("Achievements", "Token");
@@ -474,6 +454,28 @@ bool Achievements::Initialize()
}
const std::string api_token = Host::GetStringSettingValue("Achievements", "Token");
auto lock = GetLock();
pxAssertRel(EmuConfig.Achievements.Enabled, "Achievements are enabled");
pxAssertRel(!s_client && !s_http_downloader, "No client and downloader");
if (!CreateClient(&s_client, &s_http_downloader, custom_host))
return false;
// Hardcore starts off. We enable it on first boot.
s_hardcore_mode = false;
rc_client_set_event_handler(s_client, ClientEventHandler);
rc_client_set_hardcore_enabled(s_client, s_hardcore_mode);
rc_client_set_encore_mode_enabled(s_client, EmuConfig.Achievements.EncoreMode);
rc_client_set_unofficial_enabled(s_client, EmuConfig.Achievements.UnofficialTestMode);
rc_client_set_spectator_mode_enabled(s_client, EmuConfig.Achievements.SpectatorMode);
// Begin disc identification early, before the login finishes.
if (VMManager::HasValidVM())
IdentifyGame(VMManager::GetDiscCRC(), VMManager::GetCurrentCRC());
if (!username.empty() && !api_token.empty())
{
Console.WriteLn("Achievements: Attempting login with user '%s'...", username.c_str());
@@ -496,7 +498,7 @@ u32 Achievements::GetExposedEEMemorySize()
return Ps2MemSize::ExposedRam + Ps2MemSize::Scratch;
}
bool Achievements::CreateClient(rc_client_t** client, std::unique_ptr<HTTPDownloader>* http)
bool Achievements::CreateClient(rc_client_t** client, std::unique_ptr<HTTPDownloader>* http, const std::string& custom_host)
{
*http = HTTPDownloader::Create(Host::GetHTTPUserAgent());
if (!*http)
@@ -524,7 +526,6 @@ bool Achievements::CreateClient(rc_client_t** client, std::unique_ptr<HTTPDownlo
rc_client_set_userdata(new_client, http->get());
const std::string custom_host = Host::GetBaseStringSettingValue("Achievements", "Host", "");
if (!custom_host.empty())
{
Console.WriteLn("Achievements: Using custom host %s", custom_host.c_str());
@@ -1794,6 +1795,8 @@ bool Achievements::CanEnableHardcoreMode()
bool Achievements::Login(const char* username, const char* password, Error* error)
{
const std::string custom_host = Host::GetBaseStringSettingValue("Achievements", "Host", "");
auto lock = GetLock();
// We need to use a temporary client if achievements aren't currently active.
@@ -1807,7 +1810,7 @@ bool Achievements::Login(const char* username, const char* password, Error* erro
};
if (is_temporary_client)
{
if (!CreateClient(&client, &temporary_downloader))
if (!CreateClient(&client, &temporary_downloader, custom_host))
{
Error::SetString(error, "Failed to create client.");
return false;
+7 -4
View File
@@ -468,7 +468,7 @@ u32 cdvdGetElfCRC(const std::string& path)
return elfo.GetCRC();
}
static CDVDDiscType GetPS2ElfName(IsoReader& isor, std::string* name, std::string* version, Error* error)
static CDVDDiscType GetPS2ElfName(IsoReader& isor, std::string* name, std::string* version, std::string* vmode, Error* error)
{
CDVDDiscType retype = CDVDDiscType::Other;
name->clear();
@@ -510,6 +510,7 @@ static CDVDDiscType GetPS2ElfName(IsoReader& isor, std::string* name, std::strin
else if (key == "VMODE")
{
DevCon.WriteLn(Color_Blue, fmt::format("(SYSTEM.CNF) Disc region type = {}", value));
*vmode = value;
}
else if (key == "VER")
{
@@ -574,15 +575,15 @@ static std::string ExecutablePathToSerial(const std::string& path)
return serial;
}
void cdvdGetDiscInfo(std::string* out_serial, std::string* out_elf_path, std::string* out_version, u32* out_crc,
void cdvdGetDiscInfo(std::string* out_serial, std::string* out_elf_path, std::string* out_version, std::string* out_region, u32* out_crc,
CDVDDiscType* out_disc_type)
{
Error error;
IsoReader isor;
std::string elfpath, version;
std::string elfpath, version, vmode;
CDVDDiscType disc_type = CDVDDiscType::Other;
if (!isor.Open(&error) || (disc_type = GetPS2ElfName(isor, &elfpath, &version, &error)) == CDVDDiscType::Other)
if (!isor.Open(&error) || (disc_type = GetPS2ElfName(isor, &elfpath, &version, &vmode, &error)) == CDVDDiscType::Other)
Console.Error(fmt::format("Failed to get ELF name: {}", error.GetDescription()));
// Don't bother parsing it if we don't need the CRC.
@@ -616,6 +617,8 @@ void cdvdGetDiscInfo(std::string* out_serial, std::string* out_elf_path, std::st
*out_version = std::move(version);
if (out_disc_type)
*out_disc_type = disc_type;
if (out_region)
*out_region = vmode;
}
void cdvdReadKey(u8, u16, u32 arg2, u8* key)
+1 -1
View File
@@ -179,7 +179,7 @@ extern void cdvdNewDiskCB();
extern u8 cdvdRead(u8 key);
extern void cdvdWrite(u8 key, u8 rt);
extern void cdvdGetDiscInfo(std::string* out_serial, std::string* out_elf_path, std::string* out_version, u32* out_crc,
extern void cdvdGetDiscInfo(std::string* out_serial, std::string* out_elf_path, std::string* out_version, std::string* out_region, u32* out_crc,
CDVDDiscType* out_disc_type);
extern u32 cdvdGetElfCRC(const std::string& path);
extern bool cdvdLoadElf(ElfObject* elfo, const std::string_view elfpath, bool isPSXElf, Error* error);
+1 -12
View File
@@ -1010,21 +1010,10 @@ set(pcsx2x86Sources
# x86 headers
set(pcsx2x86Headers
x86/BaseblockEx.h
x86/iCOP0.h
x86/iCore.h
x86/iFPU.h
x86/iMMI.h
x86/iR3000A.h
x86/iR5900Arit.h
x86/iR5900AritImm.h
x86/iR5900Branch.h
x86/iR5900.h
x86/iR5900Analysis.h
x86/iR5900Jump.h
x86/iR5900LoadStore.h
x86/iR5900Move.h
x86/iR5900MultDiv.h
x86/iR5900Shift.h
x86/microVU_Alloc.inl
x86/microVU_Analyze.inl
x86/microVU_Branch.inl
@@ -1274,7 +1263,7 @@ function(setup_main_executable target)
if("${file}" MATCHES "^\\.") # Don't copy macOS garbage (mainly Finder's .DS_Store files) into application
continue()
endif()
if (NOT WIN32 AND "${path}" MATCHES "/dx11/") # Don't include unneccessary stuff
if (NOT WIN32 AND "${path}" MATCHES "/dx11/") # Don't include unnecessary stuff
continue()
endif()
if (NOT BUNDLE_EMOJI_FONT AND "${path}" MATCHES "fonts/Twemoji")
+7
View File
@@ -766,6 +766,7 @@ struct Pcsx2Config
DisableFramebufferFetch : 1,
DisableVertexShaderExpand : 1,
SkipDuplicateFrames : 1,
AdvancedFrameDisplay : 1,
OsdShowSpeed : 1,
OsdShowFPS : 1,
OsdShowVPS : 1,
@@ -811,6 +812,7 @@ struct Pcsx2Config
UserHacks_NativePaletteDraw : 1,
UserHacks_EstimateTextureRegion : 1,
UserHacks_DrawBuffering : 1,
UserHacks_RewriteLargeSTCoords : 1,
FXAA : 1,
ShadeBoost : 1,
DumpGSData : 1,
@@ -824,6 +826,7 @@ struct Pcsx2Config
SaveDrawStats : 1,
SaveFrameStats : 1,
SaveHWConfig : 1,
DumpReplayUseFrameRange : 1,
DumpReplaceableTextures : 1,
DumpReplaceableMipmaps : 1,
DumpTexturesWithFMVActive : 1,
@@ -912,6 +915,10 @@ struct Pcsx2Config
int SaveFrameStart = 0;
int SaveFrameCount = -1;
int SaveFrameBy = 1;
int DumpReplayLoopCount = 0;
int DumpReplayFrameStart = 0;
int DumpReplayFrameEnd = 0;
u32 SavedMetricsCaptureSeconds = 10;
s8 ExclusiveFullscreenControl = -1;
GSScreenshotSize ScreenshotSize = GSScreenshotSize::WindowResolution;
+17 -6
View File
@@ -215,7 +215,7 @@ static void vSyncInfoCalc(vSyncTimingInfo* info, double framesPerSecond, u32 sca
// Dynasty Warriors 3 Xtreme Legends - fake save corruption when loading save
// Jak II - random speedups
// Shadow of Rome - FMV audio issues
const bool ntsc_hblank = gsVideoMode != GS_VideoMode::PAL && gsVideoMode != GS_VideoMode::DVD_PAL;
const bool ntsc_hblank = gsVideoMode != GS_VideoMode::PAL && gsVideoMode != GS_VideoMode::DVD_PAL && (gsVideoMode != GS_VideoMode::Uninitialized || framesPerSecond != (Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_PAL / 2));
const u64 HalfFrame = Frame / 2;
const float extra_scanlines = static_cast<float>(IsProgressiveVideoMode()) * (ntsc_hblank ? 0.5f : 1.5f);
const u64 Blank = Scanline * ((ntsc_hblank ? 22.5f : 24.5f) + extra_scanlines);
@@ -307,10 +307,12 @@ double GetVerticalFrequency()
// https://web.archive.org/web/20120629231826fw_/http://ntsc-tv.com/index.html
// https://web.archive.org/web/20200831051302/https://www.hdretrovision.com/240p/
std::string cur_region = VMManager::Internal::GetCurrentRegion();
switch (gsVideoMode)
{
case GS_VideoMode::Uninitialized: // SetGsCrt hasn't executed yet, give some temporary values.
return 60.00;
return (cur_region == "PAL") ? Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_PAL : Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_NTSC;
case GS_VideoMode::PAL:
case GS_VideoMode::DVD_PAL:
return (IsProgressiveVideoMode() == false) ? EmuConfig.GS.FrameratePAL : EmuConfig.GS.FrameratePAL - 0.24f;
@@ -352,9 +354,9 @@ void UpdateVSyncRate(bool force)
{
case GS_VideoMode::Uninitialized: // SYSCALL instruction hasn't executed yet, give some temporary values.
if (gsIsInterlaced)
total_scanlines = SCANLINES_TOTAL_NTSC_I;
total_scanlines = (vertical_frequency == Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_PAL) ? SCANLINES_TOTAL_PAL_I : SCANLINES_TOTAL_NTSC_I;
else
total_scanlines = SCANLINES_TOTAL_NTSC_NI;
total_scanlines = (vertical_frequency == Pcsx2Config::GSOptions::DEFAULT_FRAME_RATE_PAL) ? SCANLINES_TOTAL_PAL_NI : SCANLINES_TOTAL_NTSC_NI;
break;
case GS_VideoMode::PAL:
case GS_VideoMode::DVD_PAL:
@@ -492,9 +494,12 @@ static __fi void VSyncStart(u64 sCycle)
// Don't bother throttling if we're going to pause.
if (!VMManager::Internal::IsExecutionInterrupted())
VMManager::Internal::Throttle();
VMManager::Internal::Throttle(true);
gsPostVsyncStart(); // MUST be after framelimit; doing so before causes funk with frame times!
if (!EmuConfig.GS.AdvancedFrameDisplay)
{
gsPostVsyncStart(); // MUST be after framelimit; doing so before causes funk with frame times!
}
// Poll input after MTGS frame push, just in case it has to stall to catch up.
VMManager::Internal::PollInputOnCPUThread();
@@ -564,6 +569,12 @@ static __fi void GSVSync()
static __fi void VSyncEnd(u64 sCycle)
{
EECNT_LOG(" ================ EE COUNTER VSYNC END (frame: %d) ================", g_FrameCount);
VMManager::Internal::Throttle(false);
if (EmuConfig.GS.AdvancedFrameDisplay)
{
gsPostVsyncStart();
}
g_FrameCount++;
if (!GSSMODE1reg.SINT)
-4
View File
@@ -1068,8 +1068,6 @@ void DEV9readDMA8Mem(u32* pMem, int size)
if (!EmuConfig.DEV9.EthEnable && !EmuConfig.DEV9.HddEnable)
return;
size >>= 1;
DevCon.WriteLn("DEV9: *DEV9readDMA8Mem: size %x", size);
if (dev9.dma_ctrl & SPD_DMA_TO_SMAP)
@@ -1098,8 +1096,6 @@ void DEV9writeDMA8Mem(u32* pMem, int size)
if (!EmuConfig.DEV9.EthEnable && !EmuConfig.DEV9.HddEnable)
return;
size >>= 1;
DevCon.WriteLn("DEV9: *DEV9writeDMA8Mem: size %x", size);
if (dev9.dma_ctrl & SPD_DMA_TO_SMAP)
+2 -1
View File
@@ -174,7 +174,8 @@ The clamp modes are also numerically based.
* cpuSpriteRenderBW [Value between `0` to `10`] {Disabled, 1 (64), 2 (128), 3 (192), 4 (256), 5 (320), 6 (384), 7 (448), 8 (512), 9 (576), 10 (640)} Default: Off (`0`)
* cpuSpriteRenderLevel [`0` or `1` or `2`] {Sprites only, Sprites/Triangles, Blended Sprites/Triangles} Default: Off unless cpuSpriteRenderBW has value other than Off then it is 'Sprites only' (`0`)
* estimateTextureRegion [`0` or `1`] {Off, On} Default: Off (`0`)
* drawBuffering [`0` or `1`] {Off, On} Default: Off (`0`)
* drawBuffering [`0` or `1`] {Off, On} Default: Off (`0`)
* rewriteLargeSTCoords [`0` or `1`] {Off, On} Default: Off (`0`)
* getSkipCount {`GSC` with suffix } {None unless specific game GSC} Default: Disabled (`0`) unless valid variable name (ex. GSC_PolyphonyDigitalGames, GSC_UrbanReign, ...)
* gpuPaletteConversion [`0` or `1`] {Off, On} Default: Off (`0`)
* gpuTargetCLUT [`0` or `1` or `2`] {Disabled, Enabled (Exact Match), Enabled (Check Inside Target)} Default: Disabled (`0`)
+6 -1
View File
@@ -204,7 +204,12 @@
"minimum": 0,
"maximum": 1
},
"drawBuffering": {
"drawBuffering": {
"type": "integer",
"minimum": 0,
"maximum": 1
},
"rewriteLargeSTCoords": {
"type": "integer",
"minimum": 0,
"maximum": 1
+41
View File
@@ -13,6 +13,7 @@
#include "GS/GSPerfMon.h"
#include "GS/GSUtil.h"
#include "GS/MultiISA.h"
#include "GS/GSPerfMon.h"
#include "Host.h"
#include "Input/InputManager.h"
#include "MTGS.h"
@@ -491,6 +492,23 @@ void GSStopGSDump()
g_gs_renderer->StopGSDump();
}
void GSStartSavingMetrics(u32 seconds)
{
if (g_gs_renderer)
g_gs_renderer->StartSavingMetrics(seconds);
}
void GSDumpSavedMetrics()
{
if (g_gs_renderer)
g_gs_renderer->DumpSavedMetrics();
}
bool GSIsSavingMetrics()
{
return g_gs_renderer && g_gs_renderer->IsSavingMetrics();
}
bool GSBeginCapture(std::string filename)
{
if (g_gs_renderer)
@@ -565,6 +583,11 @@ void GSSetVSyncMode(GSVSyncMode mode, bool allow_present_throttle)
g_gs_device->SetVSyncMode(mode, allow_present_throttle);
}
void GSResetStats()
{
g_perfmon.Reset();
}
bool GSWantsExclusiveFullscreen()
{
if (!g_gs_device || !g_gs_device->SupportsExclusiveFullscreen())
@@ -1226,6 +1249,24 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphic
GSStopGSDump();
});
}},
{"GSStartSavingMetricsVariableFrames", TRANSLATE_NOOP("Hotkeys", "Graphics"),
TRANSLATE_NOOP("Hotkeys", "Start Saving Performance Metrics (Press & Hold)"),
[](s32 pressed) {
MTGS::RunOnGSThread([pressed]() {
if (pressed > 0)
GSStartSavingMetrics(UINT32_MAX);
else
GSDumpSavedMetrics();
});
}},
{"GSStartSavingMetricsFixedFrames", TRANSLATE_NOOP("Hotkeys", "Graphics"),
TRANSLATE_NOOP("Hotkeys", "Start Saving Performance Metrics (Capture Timer)"),
[](s32 pressed) {
MTGS::RunOnGSThread([pressed]() {
if (pressed > 0 && !GSIsSavingMetrics())
GSStartSavingMetrics(GSConfig.SavedMetricsCaptureSeconds);
});
}},
{"ToggleSoftwareRendering", TRANSLATE_NOOP("Hotkeys", "Graphics"),
TRANSLATE_NOOP("Hotkeys", "Toggle Software Rendering"),
[](s32 pressed) {
+4
View File
@@ -76,6 +76,9 @@ std::string GSGetBaseSnapshotFilename();
std::string GSGetBaseVideoFilename();
void GSQueueSnapshot(const std::string& path, u32 gsdump_frames = 0);
void GSStopGSDump();
void GSStartSavingMetrics(float time);
void GSDumpSavedMetrics();
bool GSIsSavingMetrics();
bool GSBeginCapture(std::string filename);
void GSEndCapture();
void GSPresentCurrentFrame();
@@ -86,6 +89,7 @@ bool GSHasDisplayWindow();
void GSResizeDisplayWindow(u32 width, u32 height, float scale);
void GSUpdateDisplayWindow();
void GSSetVSyncMode(GSVSyncMode mode, bool allow_present_throttle);
void GSResetStats();
GSRendererType GSGetCurrentRenderer();
bool GSIsHardwareRenderer();
+1
View File
@@ -531,6 +531,7 @@ REG_END2
__forceinline bool IsOpaque() const { return ((A == B || (C == 2 && FIX == 0)) && D == 0) || (A == 0 && B == D && C == 2 && FIX == 0x80); }
__forceinline bool IsOpaque(int amin, int amax) const { return ((A == B || amax == 0) && D == 0) || (A == 0 && B == D && amin == 0x80 && amax == 0x80); }
__forceinline bool IsCd() const { return (A == B) && (D == 1); }
__forceinline bool IsAdditive() const { return (A == 0 && B == 2 && (C != 2 || FIX != 0) && D == 1); }
// output will be Cd, Cs is discarded
__forceinline bool IsCdOutput() const { return (C == 2 && D != 1 && FIX == 0x00); }
+165 -3
View File
@@ -105,7 +105,6 @@ GSState::GSState()
s_n = 0;
s_transfer_n = 0;
memset(&m_v, 0, sizeof(m_v));
memset(m_mem.m_vm8, 0, m_mem.m_vmsize);
@@ -2504,6 +2503,11 @@ u32 GSState::CalcMask(int exp, int max_exp)
return (1 << std::min(amount, 23)) - 1;
}
void GSState::IncDraw()
{
s_n++;
}
void GSState::FlushPrim()
{
if (m_index->tail > 0)
@@ -2526,7 +2530,7 @@ void GSState::FlushPrim()
GSVertex buff[2];
GSVertexBuff& vtx_buff = *m_vertex;
GSIndexBuff& idx_buff = *m_index;
s_n++;
IncDraw();
const u32 head = vtx_buff.head;
const u32 tail = vtx_buff.tail;
@@ -6838,6 +6842,159 @@ GIFRegTEX0 GSState::GetTex0Layer(u32 lod)
return TEX0;
}
// Fix large ST coorindates that may cause graphical glitches.
template <u32 primclass>
void GSState::RewriteVerticesIfLargeSTImpl(const GSVector4& large_val, bool check_clamp_mode)
{
// Need to be texture mapping with ST and not have so many vertices that rewritten indices will overflow.
if (PRIM->TME && PRIM->FST == 0)
{
const float tw = static_cast<float>(1 << m_context->TEX0.TW);
const float th = static_cast<float>(1 << m_context->TEX0.TH);
const GSVector4 tsize = GSVector4(tw, th, 1.0f, 1.0f);
// Only rewrite big/small S or T when the clamping mode is CLAMP or REGION_CLAMP (if requested).
const GIFRegCLAMP& clamp = m_context->CLAMP;
const GSVector4 clamp_mask =
check_clamp_mode ?
GSVector4::cast(GSVector4i(
(clamp.WMS == CLAMP_CLAMP || clamp.WMS == CLAMP_REGION_CLAMP) ? 0xFFFFFFFF : 0,
(clamp.WMT == CLAMP_CLAMP || clamp.WMT == CLAMP_REGION_CLAMP) ? 0xFFFFFFFF : 0,
0,
0)) :
GSVector4::cast(GSVector4i::cxpr(0xFFFFFFFF));
const GSVector4 tex_bbox = m_vt.m_min.t.xyxy(m_vt.m_max.t) / tsize.xyxy();
const bool large_st = ((tex_bbox.abs() >= large_val) & clamp_mask).mask() || m_vt.nan.value;
if (large_st)
{
GL_PUSH("Large ST detected, rewriting vertices.");
if (m_index->tail > UINT16_MAX)
{
GL_INS("Too many vertices to rewrite safely, exiting.");
DevCon.Warning("Large ST detected but too many vertices to rewrite safely.");
return;
}
constexpr int n = GSUtil::GetClassVertexCount(primclass);
// Make sure the copy buffer is large enough.
while (m_max_vertex_count < m_index->tail)
GrowVertexBuffer();
GSVertex* RESTRICT vertex = m_vertex->buff;
GSVertex* RESTRICT vertex_copy = m_vertex->buff_copy;
u16* RESTRICT index = m_index->buff;
const int count = static_cast<int>(m_index->tail);
for (int i = 0; i < count; i += n)
{
GSVector4 stcq[n];
// Load STQ for this primitive.
for (int j = 0; j < n; j++)
stcq[j] = GSVector4::cast(GSVector4i(vertex[index[i + j]].m[0]));
// Perform Q division and see which values need to be rewritten.
GSVector4 uv[n];
GSVector4 small{}, big{}, nan{};
for (int j = 0; j < n; j++)
{
// For sprites always use Q of second vertex.
const GSVector4 q = primclass == GS_SPRITE_CLASS ? stcq[1].wwww() : stcq[j].wwww();
uv[j] = (stcq[j] / q).xyzw(GSVector4::zero());
small |= (uv[j] <= -large_val);
big |= (uv[j] >= large_val);
nan |= (uv[j] != uv[j]);
}
// Get the new values for fields that will be rewritten.
// The follows rules are used:
// 1. If there are small values but not big or nans, make all vertices small.
// 2. If there are big values but not small or nans, make all vertices big.
// 3. If there are both big and small values, or nans, make all vertices zero.
GSVector4 uv_new = GSVector4::zero();
uv_new = uv_new.blend32(-large_val, small);
uv_new = uv_new.blend32(large_val, big);
uv_new = uv_new.blend32(GSVector4::zero(), (small & big) | nan);
const GSVector4 rewrite = (((small | big) & clamp_mask) | nan).xyxy(GSVector4::zero());
// If both S and T are rewritten, no point in keeping Q. Just set it to 1.0f;
if ((rewrite.mask() & 3) == 3)
{
for (int j = 0; j < n; j++)
stcq[j] = stcq[j].template insert32<0, 3>(GSVector4::m_one);
}
// Rewrite the fields that require it and write to the copy buffer.
for (int j = 0; j < n; j++)
{
// For sprites always use Q of second vertex.
const GSVector4 q = (primclass == GS_SPRITE_CLASS) ? stcq[1].wwww() : stcq[j].wwww();
stcq[j] = stcq[j].blend32(uv_new * q, rewrite);
vertex_copy[i + j].m[0] = GSVector4i::cast(stcq[j]);
vertex_copy[i + j].m[1] = vertex[index[i + j]].m[1];
index[i + j] = i + j;
}
}
// Swap the buffers and fix the counts.
std::swap(m_vertex->buff, m_vertex->buff_copy);
m_vertex->head = m_vertex->next = m_vertex->tail = m_index->tail;
// Recalculate ST min/max/eq in the vertex trace.
GSVector4 tmin = GSVector4::cxpr(FLT_MAX);
GSVector4 tmax = GSVector4::cxpr(-FLT_MAX);
for (int i = 0; i < count; i += n)
{
for (int j = 0; j < n; j++)
{
GSVector4 stcq = GSVector4::cast(GSVector4i(m_vertex->buff[i + j].m[0]));
const float q = (primclass == GS_SPRITE_CLASS) ? m_vertex->buff[i + 1].RGBAQ.Q : stcq.w;
stcq = (stcq / q).xyzw(stcq);
tmin = tmin.min(stcq);
tmax = tmax.max(stcq);
}
}
m_vt.m_min.t = tmin.xyww() * tsize;
m_vt.m_max.t = tmax.xyww() * tsize;
m_vt.m_eq.stq = (m_vt.m_min.t == m_vt.m_max.t).mask();
// Dump vertices if needed.
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()) && GSConfig.SaveInfo)
{
DumpVertices(GetDrawDumpPath("%05d_vertices_st_rewrite.txt", s_n));
}
}
}
}
void GSState::RewriteVerticesIfLargeST(const GSVector4& large_val, bool check_clamp_mode)
{
switch (m_vt.m_primclass)
{
case GS_POINT_CLASS:
RewriteVerticesIfLargeSTImpl<GS_POINT_CLASS>(large_val, check_clamp_mode);
break;
case GS_LINE_CLASS:
RewriteVerticesIfLargeSTImpl<GS_LINE_CLASS>(large_val, check_clamp_mode);
break;
case GS_SPRITE_CLASS:
RewriteVerticesIfLargeSTImpl<GS_SPRITE_CLASS>(large_val, check_clamp_mode);
break;
case GS_TRIANGLE_CLASS:
RewriteVerticesIfLargeSTImpl<GS_TRIANGLE_CLASS>(large_val, check_clamp_mode);
break;
default:
pxFail("Invalid primclass"); // Impossible
break;
}
}
// GSTransferBuffer
GSState::GSTransferBuffer::GSTransferBuffer()
@@ -7012,7 +7169,12 @@ GSVector2i GSState::GSPCRTCRegs::GetResolution()
if (!GSConfig.PCRTCOffsets)
{
if (PCRTCDisplays[0].enabled && PCRTCDisplays[1].enabled)
if (!PCRTCDisplays[0].enabled && !PCRTCDisplays[1].enabled)
{
const int shift = is_full_height ? 1 : 0;
resolution = {offsets.x, offsets.y << shift};
}
else if (PCRTCDisplays[0].enabled && PCRTCDisplays[1].enabled)
{
const GSVector4i combined_size = PCRTCDisplays[0].displayRect.runion(PCRTCDisplays[1].displayRect);
resolution = { combined_size.width(), combined_size.height() };
+8 -3
View File
@@ -318,9 +318,11 @@ public:
static u64 s_last_transfer_draw_n;
static u64 s_transfer_n;
GSPerfMon m_perfmon_frame; // Track stat across a frame.
GSPerfMon m_perfmon_draw; // Track stat across a draw.
GSPerfMon m_perfmon_frame; // Track stats across a frame.
GSPerfMon m_perfmon_draw; // Track stats across a draw.
void IncDraw();
static constexpr u32 STATE_VERSION = 9;
#define PRIM_REG_MASK 0x7FF
@@ -541,6 +543,9 @@ public:
bool SpriteDrawWithoutGaps();
void CalculatePrimitiveCoversWithoutGaps();
GIFRegTEX0 GetTex0Layer(u32 lod);
template <u32 primclass>
void RewriteVerticesIfLargeSTImpl(const GSVector4& large_val, bool check_clamp_mode);
void RewriteVerticesIfLargeST(const GSVector4& large_val, bool check_clamp_mode);
};
// We put this in the header because of Multi-ISA.
+2
View File
@@ -49,6 +49,7 @@ const char* ShaderEntryPoint(ShaderConvert value)
case ShaderConvert::RGB5A1_TO_DEPTH16: return "ps_convert_rgb5a1_depth16";
case ShaderConvert::DEPTH32_TO_DEPTH24: return "ps_convert_depth32_depth24";
case ShaderConvert::DEPTH_COPY: return "ps_depth_copy";
case ShaderConvert::PRIMID_TO_RGBA8: return "ps_convert_primid_rgba8";
case ShaderConvert::DOWNSAMPLE_COPY: return "ps_downsample_copy";
case ShaderConvert::RGBA_TO_8I: return "ps_convert_rgba_8i";
case ShaderConvert::RGB5A1_TO_8I: return "ps_convert_rgb5a1_8i";
@@ -109,6 +110,7 @@ const char* ShaderConvertName(ShaderConvert shader)
ENTRY(RGBA8_TO_DEPTH16);
ENTRY(RGB5A1_TO_DEPTH16);
ENTRY(DEPTH32_TO_DEPTH24);
ENTRY(PRIMID_TO_RGBA8);
ENTRY(DOWNSAMPLE_COPY);
ENTRY(RGBA_TO_8I);
ENTRY(RGB5A1_TO_8I);
+17 -3
View File
@@ -59,6 +59,7 @@ enum class ShaderConvert
RGBA8_TO_DEPTH16,
RGB5A1_TO_DEPTH16,
DEPTH32_TO_DEPTH24,
PRIMID_TO_RGBA8,
DOWNSAMPLE_COPY,
RGBA_TO_8I,
RGB5A1_TO_8I,
@@ -122,6 +123,7 @@ static inline constexpr bool HasColorOutput(ShaderConvert shader)
case ShaderConvert::DEPTH32_TO_RGBA8:
case ShaderConvert::DEPTH32_TO_RGB8:
case ShaderConvert::DEPTH16_TO_RGB5A1:
case ShaderConvert::PRIMID_TO_RGBA8:
case ShaderConvert::DOWNSAMPLE_COPY:
case ShaderConvert::RGBA_TO_8I:
case ShaderConvert::RGB5A1_TO_8I:
@@ -162,6 +164,7 @@ static inline constexpr bool HasFloat32Input(ShaderConvert shader)
case ShaderConvert::DEPTH32_TO_RGB8:
case ShaderConvert::DEPTH16_TO_RGB5A1:
case ShaderConvert::DEPTH32_TO_DEPTH24:
case ShaderConvert::PRIMID_TO_RGBA8:
return true;
default:
return false;
@@ -375,6 +378,13 @@ public:
return ShaderEntryPoint(Shader());
}
constexpr ShaderConvertSelector SetShader(ShaderConvert shader = ShaderConvert::COPY)
{
ShaderConvertSelector tmp = *this;
tmp.fields.shader = static_cast<u32>(shader);
return tmp;
}
constexpr ShaderConvertSelector SetMask(u8 mask = 0xf) const
{
ShaderConvertSelector tmp = *this;
@@ -446,7 +456,7 @@ public:
};
static inline ShaderConvertSelector GetConvertShader(GSTexture::Format src, GSTexture::Format dst,
u32 src_bpp = 32, u32 dst_bpp = 32, u8 mask = 0xf)
u32 src_bpp = 32, u32 dst_bpp = 32, u8 mask = 0xf, Filter linear = Nearest)
{
ShaderConvert shader = static_cast<ShaderConvert>(-1);
switch (src)
@@ -455,7 +465,7 @@ static inline ShaderConvertSelector GetConvertShader(GSTexture::Format src, GSTe
switch (dst)
{
case GSTexture::Format::Color:
pxAssert(src_bpp == 32 && dst_bpp == 32);
pxAssert(src_bpp == dst_bpp);
shader = ShaderConvert::COPY; // bpp is handled by mask
break;
case GSTexture::Format::DepthColor:
@@ -526,12 +536,16 @@ static inline ShaderConvertSelector GetConvertShader(GSTexture::Format src, GSTe
pxAssert(false);
}
break;
case GSTexture::Format::PrimID:
pxAssert(dst == GSTexture::Format::Color);
shader = ShaderConvert::PRIMID_TO_RGBA8;
break;
default:
pxAssert(false);
break;
}
return ShaderConvertSelector(shader, mask, dst == GSTexture::Format::DepthStencil);
return ShaderConvertSelector(shader, mask, dst == GSTexture::Format::DepthStencil, linear);
}
static inline ShaderConvertSelector GetConvertShader(const GSTexture* src, const GSTexture* dst, u32 src_bpp, u32 dst_bpp, u8 mask = 0xf)
+42 -14
View File
@@ -87,12 +87,6 @@ bool GSRenderer::Merge(int field)
int y_offset[3] = { 0, 0, 0 };
const bool feedback_merge = m_regs->EXTWRITE.WRITE == 1;
if (!PCRTCDisplays.PCRTCDisplays[0].enabled && !PCRTCDisplays.PCRTCDisplays[1].enabled)
{
m_real_size = GSVector2i(0, 0);
return false;
}
// Need to do this here, if the user has Anti-Blur enabled, these offsets can get wiped out/changed.
const bool game_deinterlacing = (PCRTCDisplays.PCRTCDisplays[0].prevFramebufferOffsets.y != PCRTCDisplays.PCRTCDisplays[0].framebufferOffsets.y) !=
(PCRTCDisplays.PCRTCDisplays[1].prevFramebufferOffsets.y != PCRTCDisplays.PCRTCDisplays[1].framebufferOffsets.y);
@@ -136,8 +130,6 @@ bool GSRenderer::Merge(int field)
if (!tex[0] && !tex[1])
{
m_real_size = GSVector2i(0, 0);
// Clear out the MAD buffer as some remnants of the previously shown frame came be left over, causing a flash for one frame.
if (GSConfig.InterlaceMode == GSInterlaceMode::Automatic || GSConfig.InterlaceMode >= GSInterlaceMode::AdaptiveTFF)
{
@@ -149,13 +141,19 @@ bool GSRenderer::Merge(int field)
mad_tex = nullptr;
}
}
return false;
// Both circuits off still outputs BGCOLOR on real hardware.
if (PCRTCDisplays.PCRTCDisplays[0].enabled || PCRTCDisplays.PCRTCDisplays[1].enabled)
{
m_real_size = GSVector2i(0, 0);
return false;
}
}
s_n++;
IncDraw();
GSVector4 src_gs_read[2];
GSVector4 dst[3];
GSVector4 src_gs_read[2] = {};
GSVector4 dst[3] = {};
// Use offset for bob deinterlacing always, extra offset added later for FFMD mode.
const bool scanmask_frame = m_scanmask_used && abs(PCRTCDisplays.PCRTCDisplays[0].displayRect.y - PCRTCDisplays.PCRTCDisplays[1].displayRect.y) != 1;
@@ -226,7 +224,7 @@ bool GSRenderer::Merge(int field)
m_real_size = GSVector2i(fs.x, fs.y);
if ((tex[0] == tex[1]) && (src_gs_read[0] == src_gs_read[1]).alltrue() && (dst[0] == dst[1]).alltrue() &&
if ((tex[0] || tex[1]) && (tex[0] == tex[1]) && (src_gs_read[0] == src_gs_read[1]).alltrue() && (dst[0] == dst[1]).alltrue() &&
(PCRTCDisplays.PCRTCDisplays[0].displayRect == PCRTCDisplays.PCRTCDisplays[1].displayRect).alltrue() &&
(PCRTCDisplays.PCRTCDisplays[0].framebufferRect == PCRTCDisplays.PCRTCDisplays[1].framebufferRect).alltrue() &&
!feedback_merge && !m_regs->PMODE.SLBG)
@@ -238,7 +236,7 @@ bool GSRenderer::Merge(int field)
const u32 c = (m_regs->BGCOLOR.U32[0] & 0x00FFFFFFu) | (m_regs->PMODE.ALP << 24);
g_gs_device->Merge(tex, src_gs_read, dst, fs, m_regs->PMODE, m_regs->EXTBUF, c);
if (isReallyInterlaced() && GSConfig.InterlaceMode != GSInterlaceMode::Off)
if ((tex[0] || tex[1]) && isReallyInterlaced() && GSConfig.InterlaceMode != GSInterlaceMode::Off)
{
const float offset = is_bob ? (tex[1] ? tex_scale[1] : tex_scale[0]) : 0.0f;
@@ -526,6 +524,9 @@ bool GSRenderer::BeginPresentFrame(bool frame_skip)
{
Host::BeginPresentFrame();
if (GSDumpReplayer::IsReplayingDump())
GSDumpReplayer::UpdateGSStats();
const GSDevice::PresentResult res = g_gs_device->BeginPresent(frame_skip);
if (res == GSDevice::PresentResult::FrameSkipped)
{
@@ -807,6 +808,10 @@ void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
}
}
// metrics
if (m_saving_metrics && !PerformanceMetrics::IsSavingMetrics())
DumpSavedMetrics();
// capture
if (GSCapture::IsCapturingVideo())
{
@@ -955,6 +960,29 @@ void GSRenderer::StopGSDump()
m_dump_frames = 0;
}
void GSRenderer::StartSavingMetrics(u32 seconds)
{
m_saving_metrics = true;
PerformanceMetrics::StartSavingMetrics(seconds);
Host::AddKeyedOSDMessage("GSMetrics",
fmt::format(TRANSLATE_FS("GS", "Started saving performance metrics{}"),
(0 < seconds && seconds < UINT32_MAX) ? fmt::format(" ({} seconds)", seconds) : ""),
Host::OSD_INFO_DURATION);
}
void GSRenderer::DumpSavedMetrics()
{
m_saving_metrics = false;
PerformanceMetrics::DumpSavedMetrics();
Host::AddKeyedOSDMessage("GSMetrics", fmt::format(TRANSLATE_FS("GS", "Logging saved performance metrics")),
Host::OSD_INFO_DURATION);
}
bool GSRenderer::IsSavingMetrics()
{
return m_saving_metrics;
}
void GSRenderer::PresentCurrentFrame()
{
if (BeginPresentFrame(false))
+4
View File
@@ -19,6 +19,7 @@ private:
std::string m_snapshot;
u32 m_dump_frames = 0;
u32 m_skipped_duplicate_frames = 0;
bool m_saving_metrics = false;
// Tracking draw counters for idle frame detection.
u64 m_last_draw_n = 0;
@@ -56,6 +57,9 @@ public:
void QueueSnapshot(const std::string& path, const u32 gsdump_frames);
void StopGSDump();
void StartSavingMetrics(u32 seconds);
void DumpSavedMetrics();
bool IsSavingMetrics();
void PresentCurrentFrame();
bool BeginCapture(std::string filename, const GSVector2i& size = GSVector2i(0, 0));
void EndCapture();
+11
View File
@@ -63,4 +63,15 @@ enum class PS_ROV_DEPTH : uint32_t
READ_ONLY = 2,
};
#if defined(__METAL_VERSION__)
#define CONSTANT constant
#else
#define CONSTANT
#endif
static constexpr CONSTANT int PRIMID_MAX = (1 << 24) - 1;
static constexpr CONSTANT int PRIMID_MIN = -1;
#undef CONSTANT
} // namespace GSShader
+1 -1
View File
@@ -44,7 +44,7 @@ bool GSTexture::Save(const std::string& fn)
{
// Depth textures need special treatment - we have a stencil component.
// Just re-use the existing conversion shader instead.
if (m_format == Format::DepthStencil || m_format == Format::DepthColor)
if (m_format == Format::DepthStencil || m_format == Format::DepthColor || m_format == Format::PrimID)
{
GSTexture* temp = g_gs_device->CreateRenderTarget(GetWidth(), GetHeight(), Format::Color, false);
if (!temp)
+30 -3
View File
@@ -249,6 +249,8 @@ bool GSDevice11::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
ShaderMacro sm_ps;
sm_ps.AddMacro("PIXEL_SHADER", 1);
sm_ps.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX);
sm_ps.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN);
sm_ps.AddMacro("HAS_BILN", static_cast<int>(shader.Biln()));
sm_ps.AddMacro("HAS_STENCIL_OUTPUT", static_cast<int>(shader.StencilOutput()));
sm_ps.AddMacro("HAS_INTEGER_OUTPUT", static_cast<int>(shader.IntegerOutputBpp() != 0));
@@ -582,6 +584,8 @@ bool GSDevice11::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
const std::string entry_point_macro = WrapEntryPointMacro(entry_point);
ShaderMacro sm_ps;
sm_ps.AddMacro("PIXEL_SHADER", 1);
sm_ps.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX);
sm_ps.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN);
sm_ps.AddMacro(entry_point_macro.c_str(), 1);
m_date.primid_init_ps[i] = m_shader_cache.GetPixelShader(m_dev.get(), *convert_hlsl, sm_ps.GetPtr(), entry_point.c_str());
if (!m_date.primid_init_ps[i])
@@ -1094,6 +1098,14 @@ GSDevice::PresentResult GSDevice11::BeginPresent(bool frame_skip)
m_state.rtv = m_swap_chain_rtv.get();
m_state.rtv->AddRef();
m_state.current_rt = nullptr;
if (m_state.dsv_as_rtv)
{
m_state.dsv_as_rtv->Release();
m_state.dsv_as_rtv = nullptr;
}
m_state.current_ds_as_rt = nullptr;
if (m_state.dsv)
{
m_state.dsv->Release();
@@ -1101,6 +1113,20 @@ GSDevice::PresentResult GSDevice11::BeginPresent(bool frame_skip)
}
m_state.current_ds = nullptr;
if (m_state.rt_uav)
{
m_state.rt_uav->Release();
m_state.rt_uav = nullptr;
}
m_state.current_rt_uav = nullptr;
if (m_state.ds_uav)
{
m_state.ds_uav->Release();
m_state.ds_uav = nullptr;
}
m_state.current_ds_uav = nullptr;
g_perfmon.Put(GSPerfMon::RenderPasses, 1);
const GSVector2i size = GetWindowSize();
@@ -2359,7 +2385,7 @@ void GSDevice11::RenderImGui()
{
ImGui::Render();
const ImDrawData* draw_data = ImGui::GetDrawData();
if (draw_data->CmdListsCount == 0)
if (draw_data->CmdLists.Size == 0)
return;
UpdateImGuiTextures();
@@ -2393,7 +2419,7 @@ void GSDevice11::RenderImGui()
PSSetSamplerState(m_convert.ln.get());
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (int n = 0; n < draw_data->CmdLists.Size; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -2926,7 +2952,7 @@ void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds_as_rt, GSTextur
m_state.dsv_as_rtv->Release();
if (dsv_as_rtv)
dsv_as_rtv->AddRef();
m_state.rtv = dsv_as_rtv;
m_state.dsv_as_rtv = dsv_as_rtv;
m_state.current_ds_as_rt = ds_as_rt;
}
if (m_state.dsv != dsv)
@@ -2984,6 +3010,7 @@ void GSDevice11::OMSetRenderTargets(GSTexture* rt, GSTexture* ds_as_rt, GSTextur
{
const GSVector2i size =
rt ? rt->GetSize() :
ds_as_rt ? ds_as_rt->GetSize() :
ds ? ds->GetSize() :
(rt_uav_tex && rt_uav_tex != m_null_texture) ? rt_uav_tex->GetSize() :
ds_uav_tex->GetSize();
+70 -48
View File
@@ -289,16 +289,12 @@ bool GSDevice12::CreateDevice(u32& vendor_id)
// Create the actual device.
// Intel Haswell DX12 support is specific:
// Newerest drivers have dx12 support disabled so the last driver to support dx12 is 15.40.42.5063.
// Newer drivers have dx12 support disabled so the last driver to support dx12 is 15.40.42.5063.
// Shader cache must be also disabled, and make sure Debug Device option is disabled as well.
// Let's enable it on dev/debug for testing purposes so we don't have to change this all the time.
// Let's enable it for testing purposes so we don't have to change this all the time, and
// might be handy for the tweakers that want to run dx12.
// TODO: Find out the status of Broadwell.
#ifdef PCSX2_DEVBUILD
hr = D3D12CreateDevice(m_adapter.get(), D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
#else
const bool isIntel = (vendor_id == 0x163C || vendor_id == 0x8086 || vendor_id == 0x8087);
hr = D3D12CreateDevice(m_adapter.get(), isIntel ? D3D_FEATURE_LEVEL_12_0 : D3D_FEATURE_LEVEL_11_0, IID_PPV_ARGS(&m_device));
#endif
if (FAILED(hr))
{
@@ -488,36 +484,8 @@ void GSDevice12::MoveToNextCommandList()
if (res.sampler_allocator.ShouldReset())
res.sampler_allocator.Reset();
if (res.has_timestamp_query)
{
// readback timestamp from the last time this cmdlist was used.
// we don't need to worry about disjoint in dx12, the frequency is reliable within a single cmdlist.
const u32 offset = (m_current_command_list * (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST));
const D3D12_RANGE read_range = {offset, offset + (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST)};
void* map;
HRESULT hr = m_timestamp_query_buffer->Map(0, &read_range, &map);
if (SUCCEEDED(hr))
{
u64 timestamps[2];
std::memcpy(timestamps, static_cast<const u8*>(map) + offset, sizeof(timestamps));
m_accumulated_gpu_time +=
static_cast<float>(static_cast<double>(timestamps[1] - timestamps[0]) / m_timestamp_frequency);
const D3D12_RANGE write_range = {};
m_timestamp_query_buffer->Unmap(0, &write_range);
}
else
{
Console.Warning("D3D12: Map() for timestamp query failed: %08X", hr);
}
}
res.has_timestamp_query = m_gpu_timing_enabled;
if (m_gpu_timing_enabled)
{
res.command_lists[1].list4->EndQuery(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST);
}
ReadGPUTiming();
StartGPUTiming();
if (res.pipeline_statistics_query == QueryState::Ready)
{
@@ -587,15 +555,7 @@ bool GSDevice12::ExecuteCommandList(WaitType wait_for_completion)
m_vertex_constant_buffer.FlushMemory();
m_pixel_constant_buffer.FlushMemory();
if (res.has_timestamp_query)
{
// write the timestamp back at the end of the cmdlist
res.command_lists[1].list4->EndQuery(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
(m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST) + 1);
res.command_lists[1].list4->ResolveQueryData(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST, NUM_TIMESTAMP_QUERIES_PER_CMDLIST,
m_timestamp_query_buffer.get(), m_current_command_list * (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST));
}
EndGPUTiming();
if ((res.pipeline_statistics_query == QueryState::Querying) || (res.pipeline_statistics_query == QueryState::Ready))
{
@@ -857,6 +817,64 @@ bool GSDevice12::SetGPUPipelineStatisticsEnabled(bool enabled)
return true;
}
void GSDevice12::StartGPUTiming()
{
if (m_gpu_timing_enabled)
{
CommandListResources& res = m_command_lists[m_current_command_list];
res.command_lists[1].list4->EndQuery(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST);
res.timestamp_query_state = QueryState::Querying;
}
}
void GSDevice12::EndGPUTiming()
{
CommandListResources& res = m_command_lists[m_current_command_list];
if (res.timestamp_query_state == QueryState::Querying)
{
// write the timestamp back at the end of the cmdlist
if (InRenderPass())
EndRenderPass(); // Can't end query in a render pass
res.command_lists[1].list4->EndQuery(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
(m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST) + 1);
res.command_lists[1].list4->ResolveQueryData(m_timestamp_query_heap.get(), D3D12_QUERY_TYPE_TIMESTAMP,
m_current_command_list * NUM_TIMESTAMP_QUERIES_PER_CMDLIST, NUM_TIMESTAMP_QUERIES_PER_CMDLIST,
m_timestamp_query_buffer.get(), m_current_command_list * (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST));
res.timestamp_query_state = QueryState::Ready;
}
}
void GSDevice12::ReadGPUTiming()
{
CommandListResources& res = m_command_lists[m_current_command_list];
if (res.timestamp_query_state == QueryState::Ready)
{
// readback timestamp from the last time this cmdlist was used.
// we don't need to worry about disjoint in dx12, the frequency is reliable within a single cmdlist.
const u32 offset = (m_current_command_list * (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST));
const D3D12_RANGE read_range = { offset, offset + (sizeof(u64) * NUM_TIMESTAMP_QUERIES_PER_CMDLIST) };
void* map;
HRESULT hr = m_timestamp_query_buffer->Map(0, &read_range, &map);
if (SUCCEEDED(hr))
{
u64 timestamps[2];
std::memcpy(timestamps, static_cast<const u8*>(map) + offset, sizeof(timestamps));
m_accumulated_gpu_time +=
static_cast<float>(static_cast<double>(timestamps[1] - timestamps[0]) / m_timestamp_frequency);
const D3D12_RANGE write_range = {};
m_timestamp_query_buffer->Unmap(0, &write_range);
}
else
{
Console.Warning("D3D12: Map() for timestamp query failed: %08X", hr);
}
res.timestamp_query_state = QueryState::None;
}
}
bool GSDevice12::AllocatePreinitializedGPUBuffer(u32 size, ID3D12Resource** gpu_buffer,
D3D12MA::Allocation** gpu_allocation, const std::function<void(void*)>& fill_callback)
{
@@ -2361,7 +2379,7 @@ void GSDevice12::RenderImGui()
{
ImGui::Render();
const ImDrawData* draw_data = ImGui::GetDrawData();
if (draw_data->CmdListsCount == 0)
if (draw_data->CmdLists.Size == 0)
return;
UpdateImGuiTextures();
@@ -2402,7 +2420,7 @@ void GSDevice12::RenderImGui()
// this is for presenting, we don't want to screw with the viewport/scissor set by display
m_dirty_flags &= ~(DIRTY_FLAG_RENDER_TARGET | DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR);
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (int n = 0; n < draw_data->CmdLists.Size; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
@@ -2877,6 +2895,8 @@ bool GSDevice12::CompileConvertPipelines()
ShaderMacro sm;
sm.AddMacro("PIXEL_SHADER", 1);
sm.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX);
sm.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN);
sm.AddMacro("HAS_BILN", static_cast<int>(shader.Biln()));
sm.AddMacro("HAS_STENCIL_OUTPUT", static_cast<int>(shader.StencilOutput()));
sm.AddMacro("HAS_INTEGER_OUTPUT", static_cast<int>(shader.IntegerOutputBpp() != 0));
@@ -2930,6 +2950,8 @@ bool GSDevice12::CompileConvertPipelines()
ShaderMacro sm;
sm.AddMacro("PIXEL_SHADER", "1");
sm.AddMacro("PRIMID_MAX", GSShader::PRIMID_MAX);
sm.AddMacro("PRIMID_MIN", GSShader::PRIMID_MIN);
sm.AddMacro(entry_point_macro.c_str(), "1");
ComPtr<ID3DBlob> ps(m_shader_cache.GetPixelShader(*source, sm.GetPtr(), entry_point.c_str()));
+4 -2
View File
@@ -191,7 +191,6 @@ public:
void UploadIndices(D3D12StreamBuffer& buffer, const void* index, size_t count);
private:
// For pipeline statistics
enum class QueryState
{
None,
@@ -209,7 +208,7 @@ private:
std::vector<std::pair<D3D12DescriptorHeapManager&, u32>> pending_descriptors;
u64 ready_fence_value = 0;
bool init_command_list_used = false;
bool has_timestamp_query = false;
QueryState timestamp_query_state = QueryState::None;
QueryState pipeline_statistics_query = QueryState::None;
};
@@ -524,6 +523,9 @@ public:
void EndPresent() override;
bool SetGPUTimingEnabled(bool enabled) override;
void StartGPUTiming();
void EndGPUTiming();
void ReadGPUTiming();
float GetAndResetAccumulatedGPUTime() override;
bool SetGPUPipelineStatisticsEnabled(bool enabled) override;
-17
View File
@@ -607,20 +607,6 @@ bool GSHwHack::GSC_TalesOfLegendia(GSRendererHW& r, int& skip)
return true;
}
bool GSHwHack::GSC_UltramanFightingEvolution(GSRendererHW& r, int& skip)
{
if (skip == 0)
{
if (!s_nativeres && RTME && RFBP == 0x2a00 && RFPSM == PSMZ24 && RTBP0 == 0x1c00 && RTPSM == PSMZ24)
{
// Don't enable hack on native res if crc is below aggressive.
skip = 5; // blur
}
}
return true;
}
bool GSHwHack::GSC_TalesofSymphonia(GSRendererHW& r, int& skip)
{
if (skip == 0)
@@ -1468,9 +1454,6 @@ const GSHwHack::Entry<GSRendererHW::GSC_Ptr> GSHwHack::s_get_skip_count_function
// Depth Issue
CRC_F(GSC_BurnoutGames),
// Upscaling hacks
CRC_F(GSC_UltramanFightingEvolution),
};
const GSHwHack::Entry<GSRendererHW::OI_Ptr> GSHwHack::s_before_draw_functions[] = {
-1
View File
@@ -18,7 +18,6 @@ public:
static bool GSC_BlackAndBurnoutSky(GSRendererHW& r, int& skip);
static bool GSC_MidnightClub3(GSRendererHW& r, int& skip);
static bool GSC_TalesOfLegendia(GSRendererHW& r, int& skip);
static bool GSC_UltramanFightingEvolution(GSRendererHW& r, int& skip);
static bool GSC_TalesofSymphonia(GSRendererHW& r, int& skip);
static bool GSC_UrbanReign(GSRendererHW& r, int& skip);
static bool GSC_BlueTongueGames(GSRendererHW& r, int& skip);
+41 -29
View File
@@ -2901,6 +2901,15 @@ void GSRendererHW::Draw()
// First pass texture shuffle detection using context/vertices.
DetectTextureShuffle();
// Ridge Racer V and Destruction Derby Arena have large ST coordinates in reflection map draws that cause
// speckled artifacts on cars. Detect and rewrite such vertices here.
if (GSConfig.UserHacks_RewriteLargeSTCoords)
{
// The threshold is chosen to be low enough to fix the artifacts in Ridge Racer V and Destruction Derby Arena
// while not breaking anything.
RewriteVerticesIfLargeST(GSVector4::cxpr(16.0f), false);
}
// When the format is 24bit (Z or C), DATE ceases to function.
// It was believed that in 24bit mode all pixels pass because alpha doesn't exist
@@ -3526,13 +3535,14 @@ void GSRendererHW::Draw()
const u32 color_mask = (m_vt.m_max.c > GSVector4i::zero()).mask();
const bool texture_function_color = m_cached_ctx.TEX0.TFX == TFX_DECAL || (color_mask & 0xFFF) || (m_cached_ctx.TEX0.TFX > TFX_DECAL && (color_mask & 0xF000));
const bool texture_function_alpha = m_cached_ctx.TEX0.TFX != TFX_MODULATE || (color_mask & 0xF000);
const bool req_color = (is_possible_channel_shuffle && channel_shuffle_targets != ChannelFetch_ALPHA) || (!is_possible_channel_shuffle && ((texture_function_color && (!PRIM->ABE || GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp < 16 || (NeedsBlending() && IsUsingCsInBlend())) && (possible_shuffle || (m_cached_ctx.FRAME.FBMSK & (fm_mask & 0x00FFFFFF)) != (fm_mask & 0x00FFFFFF))) || need_aem_color));
const bool alpha_used = (GSUtil::GetChannelMask(m_context->TEX0.PSM) == 0x8 || (m_context->TEX0.TCC && texture_function_alpha)) && ((NeedsBlending() && IsUsingAsInBlend()) || (m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.ATST > ATST_ALWAYS) || (possible_shuffle || (m_cached_ctx.FRAME.FBMSK & (fm_mask & 0xFF000000)) != (fm_mask & 0xFF000000)));
const bool req_alpha = (is_possible_channel_shuffle && channel_shuffle_targets == ChannelFetch_ALPHA) || (!is_possible_channel_shuffle && (GSUtil::GetChannelMask(m_context->TEX0.PSM) & 0x8) && alpha_used);
const bool color_used = (is_possible_channel_shuffle && channel_shuffle_targets != ChannelFetch_ALPHA) || (!is_possible_channel_shuffle && ((texture_function_color && (!PRIM->ABE || (NeedsBlending() && IsUsingCsInBlend())) && ((m_cached_ctx.FRAME.FBMSK & (fm_mask & 0x00FFFFFF)) != (fm_mask & 0x00FFFFFF))) || need_aem_color));
const bool alpha_used = (is_possible_channel_shuffle && channel_shuffle_targets == ChannelFetch_ALPHA) || (!is_possible_channel_shuffle && (m_context->TEX0.TCC && texture_function_alpha) && ((NeedsBlending() && IsUsingAsInBlend()) || (m_cached_ctx.TEST.ATE && m_cached_ctx.TEST.ATST > ATST_ALWAYS) || (m_cached_ctx.FRAME.FBMSK & (fm_mask & 0xFF000000)) != (fm_mask & 0xFF000000)));
const bool req_color = (GSUtil::GetChannelMask(m_context->TEX0.PSM) & 0x7) && color_used;
const bool req_alpha = (GSUtil::GetChannelMask(m_context->TEX0.PSM) == 0x8 && (color_used || alpha_used)) || ((GSUtil::GetChannelMask(m_context->TEX0.PSM) & 0x8) && alpha_used);
// TODO: Be able to send an alpha of 1.0 (blended with vertex alpha maybe?) so we can avoid sending the texture, since we don't always need it.
// Example games: Evolution Snowboarding, Final Fantasy Dirge of Cerberus, Red Dead Revolver, Stuntman, Tony Hawk's Underground 2, Ultimate Spider-Man.
if (!req_color && !alpha_used)
if (!req_color && !req_alpha)
{
m_process_texture = false;
possible_shuffle = false;
@@ -7689,26 +7699,17 @@ void GSRendererHW::ConfigureROV(bool color_rov, bool depth_rov)
if (color_rov)
{
// FbMask setup
if (m_conf.colormask.wrgba != 0)
if (m_conf.colormask.wrgba != 0 && m_conf.colormask.wrgba != 0xF)
{
if (!m_conf.ps.fbmask)
m_conf.cb_ps.FbMask = GSVector4i::zero();
const GSVector4i fbmask = GSVector4i(m_conf.colormask.wr ? 0 : 0xFF, m_conf.colormask.wg ? 0 : 0xFF,
m_conf.colormask.wb ? 0 : 0xFF, m_conf.colormask.wa ? 0 : 0xFF);
if (!m_conf.ps.fbmask)
{
// Don't enable FB mask emulation, just use the mask for ROV.
m_conf.cb_ps.FbMask = fbmask;
}
else
{
m_conf.cb_ps.FbMask |= fbmask;
}
m_conf.ps.fbmask = true;
m_conf.cb_ps.FbMask |= fbmask;
GL_INS("ROV: FbMask={R=%x, G=%x, B=%x, A=%x}",
m_conf.cb_ps.FbMask.r, m_conf.cb_ps.FbMask.g, m_conf.cb_ps.FbMask.b, m_conf.cb_ps.FbMask.a);
}
else
{
m_conf.ps.no_color = true;
}
// Blend setup
if (m_conf.IsBlending())
@@ -9826,8 +9827,12 @@ bool GSRendererHW::CanUseSwPrimRender(bool no_rt, bool no_ds, bool draw_sprite_t
return false;
}
}
if (PRIM->ABE && m_vt.m_eq.rgba == 0xffff && !m_context->ALPHA.IsOpaque(GetAlphaMinMax().min, GetAlphaMinMax().max))
const u32 frame_mask = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk;
const u32 alpha_mask = ((m_cached_ctx.FRAME.FBMSK & frame_mask) & 0xFF000000);
const u32 rgb_mask = ((m_cached_ctx.FRAME.FBMSK & frame_mask) & 0x00FFFFFF);
const bool difficult_fbmsk = m_cached_ctx.FRAME.FBMSK != 0 && (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16 || (alpha_mask != 0 && alpha_mask != (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk & 0xFF000000)) ||
(rgb_mask != 0 && rgb_mask != (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk & 0x00FFFFFF)));
if (difficult_fbmsk || (PRIM->ABE && m_vt.m_eq.rgba == 0xffff && !m_context->ALPHA.IsOpaque(GetAlphaMinMax().min, GetAlphaMinMax().max)))
{
GSTextureCache::Target* rt = g_texture_cache->GetTargetWithSharedBits(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.PSM);
@@ -10690,7 +10695,7 @@ int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
tex_size.y = std::min(tex_size.y, 1 << m_cached_ctx.TEX0.TH);
const bool is_target_src = src && src->m_from_target;
const bool is_recursive = m_cached_ctx.FRAME.Block() == m_cached_ctx.TEX0.TBP0;
// Try to catch cases of stupid draws like Manhunt and Syphon Filter where they sample a single pixel.
// Also make sure it's grabbing most of the texture.
if (tex_size.x == 0 || tex_size.y == 0 || draw_size.x == 0 || draw_size.y == 0)
@@ -10704,19 +10709,22 @@ int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
const GSDrawingContext& next_ctx = m_env.CTXT[m_env.PRIM.CTXT];
const bool next_tex0_is_draw = m_env.PRIM.TME && next_ctx.TEX0.TBP0 == m_cached_ctx.FRAME.Block() && next_ctx.TEX1.MMAG == 1;
if (!PRIM->TME || (m_context->TEX1.MMAG != 1 && !next_tex0_is_draw) || m_vt.m_primclass < GS_TRIANGLE_CLASS || m_cached_ctx.FRAME.Block() == m_cached_ctx.TEX0.TBP0 ||
if (!PRIM->TME || (m_context->TEX1.MMAG != 1 && !next_tex0_is_draw) || m_vt.m_primclass < GS_TRIANGLE_CLASS ||
(is_recursive && !m_r.rintersect(GSVector4i(m_vt.m_min.t.x, m_vt.m_min.t.y, m_vt.m_max.t.x, m_vt.m_max.t.y)).rempty()) || // Same target with overlap.
IsMipMapDraw() || GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp <= 8)
return 0;
const bool is_smaller = draw_size.x <= (tex_size.x * 0.75f) && draw_size.y <= (tex_size.y * 0.75f);
const bool is_smaller_and_writing_back = draw_size.x < tex_size.x && draw_size.y < tex_size.y && next_ctx.FRAME.Block() == m_cached_ctx.TEX0.TBP0 && next_ctx.TEX0.TBP0 == m_cached_ctx.FRAME.Block();
// Should usually be 2x but some games like Monster House goes from 512x448 -> 128x128
const bool is_downscale = m_cached_ctx.TEX0.TBW >= m_cached_ctx.FRAME.FBW && draw_size.x <= (tex_size.x * 0.75f) && draw_size.y <= (tex_size.y * 0.75f);
const bool is_downscale = m_cached_ctx.TEX0.TBW >= m_cached_ctx.FRAME.FBW && (is_smaller || is_smaller_and_writing_back);
// Check we're getting most of the texture and not just stenciling a part of it.
// Only allow non-bilineared downscales if it's most of the target (misdetections of shadows in Naruto, Transformers etc), otherwise it's fine.
const GSVector4i src_valid = src->m_from_target ? src->m_from_target->m_valid : src->m_valid_rect;
const GSVector2i tex_size_half = GSVector2i((src->GetRegion().HasX() ? src->GetRegionSize().x : src_valid.width()) / 2, (src->GetRegion().HasY() ? src->GetRegionSize().y : src_valid.height()) / 2);
const bool possible_downscale = m_context->TEX1.MMIN == 1 || !src->m_from_target || src->m_from_target->m_downscaled || GSConfig.UserHacks_NativeScaling > GSNativeScaling::Aggressive || tex_size.x >= tex_size_half.x || tex_size.y >= tex_size_half.y;
if (is_downscale && (draw_size.x >= PCRTCDisplays.GetResolution().x || !possible_downscale))
if (is_downscale && (draw_size.x >= PCRTCDisplays.GetResolution().x || !possible_downscale || is_recursive))
return 0;
const bool is_upscale = m_cached_ctx.TEX0.TBW <= m_cached_ctx.FRAME.FBW && ((draw_size.x / tex_size.x) >= 4 || (draw_size.y / tex_size.y) >= 4);
@@ -10725,7 +10733,7 @@ int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
const bool no_gaps_or_single_sprite = (is_downscale || is_upscale) && (no_gaps || (m_vt.m_primclass == GS_SPRITE_CLASS && SpriteDrawWithoutGaps()));
const bool dst_discarded = IsDiscardingDstRGB() || IsDiscardingDstAlpha();
if (no_gaps_or_single_sprite && ((is_upscale && !m_context->ALPHA.IsOpaque()) ||
if (!is_recursive && no_gaps_or_single_sprite && ((is_upscale && !m_context->ALPHA.IsOpaque()) ||
(is_downscale && (dst_discarded || (PRIM->ABE && m_context->ALPHA.C == 2 && m_context->ALPHA.FIX == 255)))))
{
GL_INS("HW: %s draw detected - from %dx%d to %dx%d draw %lld", is_downscale ? "Downscale" : "Upscale", tex_size.x, tex_size.y, draw_size.x, draw_size.y, s_n);
@@ -10733,7 +10741,8 @@ int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
}
// Last ditched check if it's doing a lot of small draws exactly the same which could be recursive lighting bloom.
if (m_vt.m_primclass == GS_SPRITE_CLASS && m_index->tail > 2 && !no_gaps_or_single_sprite && m_context->TEX1.MMAG == 1 && !m_context->ALPHA.IsOpaque())
if (m_vt.m_primclass == GS_SPRITE_CLASS && m_index->tail > 2 && !no_gaps_or_single_sprite && m_context->TEX1.MMAG == 1 && is_target_src && (m_cached_ctx.TEST.ZTST == ZTST_ALWAYS || m_cached_ctx.TEST.ZTE == 0) &&
!m_context->ALPHA.IsOpaque() && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp)
{
GSVertex* v = &m_vertex->buff[0];
float tw = 1 << src->m_TEX0.TW;
@@ -10744,7 +10753,10 @@ int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
const int first_x = (v[1].XYZ.X - v[0].XYZ.X) >> 4;
const int first_y = (v[1].XYZ.Y - v[0].XYZ.Y) >> 4;
if (first_x > first_u && first_y > first_v && !no_resize && std::abs(draw_size.x - first_x) <= 4 && std::abs(draw_size.y - first_y) <= 4)
const u32 half_color_mask = (m_vt.m_min.c == GSVector4i(64, 64, 64, 64)).mask() & 0xfff;
const bool possible_fake_bilinear = no_resize && PRIM->ABE && m_context->ALPHA.IsAdditive() && m_cached_ctx.TEX0.TFX == TFX_MODULATE && m_vt.m_eq.rgba && half_color_mask == 0xfff;
if (first_x >= first_u && first_y >= first_v && (!no_resize || possible_fake_bilinear) && ((draw_size.x != first_x && draw_size.y != first_y) || (tex_size.x != first_u && tex_size.y != first_v)) && std::abs(draw_size.x - first_x) <= 4 && std::abs(draw_size.y - first_y) <= 4)
{
for (u32 i = 2; i < m_index->tail; i += 2)
{
@@ -10753,14 +10765,14 @@ int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
const int next_x = (v[i + 1].XYZ.X - v[i].XYZ.X) >> 4;
const int next_y = (v[i + 1].XYZ.Y - v[i].XYZ.Y) >> 4;
if (std::abs(draw_size.x - next_x) > 4 || std::abs(draw_size.y - next_y) > 4)
if (std::abs(draw_size.x - next_x) > 4 || std::abs(draw_size.y - next_y) > 4 || (draw_size.x == next_x && tex_size.x == next_u) || (draw_size.y == next_y && tex_size.y == next_v))
break;
if (next_u != first_u || next_v != first_v || next_x != first_x || next_y != first_y)
break;
if (i + 2 >= m_index->tail)
return 2;
return (is_target_src && src->m_from_target->m_downscaled) ? -1 : 2;
}
}
}
+13 -1
View File
@@ -545,7 +545,19 @@ bool GSRendererHWFunctions::SwPrimRender(GSRendererHW& hw, bool invalidate_tc, b
static_cast<GSSingleRasterizer*>(hw.m_sw_rasterizer.get())->Draw(data);
if (invalidate_tc)
g_texture_cache->InvalidateVideoMem(context->offset.fb, bbox);
{
GSOffset frame_offs = context->offset.fb;
if (GSLocalMemory::m_psm[context->FRAME.PSM].trbpp == 32 && context->FRAME.FBMSK)
{
if (context->FRAME.FBMSK == 0xFF000000)
frame_offs = GSRendererHW::GetInstance()->m_mem.GetOffset(context->FRAME.Block(), context->FRAME.FBW, PSMCT24);
else if (context->FRAME.FBMSK == 0x00FFFFFF)
frame_offs = GSRendererHW::GetInstance()->m_mem.GetOffset(context->FRAME.Block(), context->FRAME.FBW, PSMT8H);
}
g_texture_cache->InvalidateVideoMem(frame_offs, bbox);
}
// Jak does sw prim render, then draws to the same target, and it needs to be uploaded.
if (add_ee_transfer)
+23 -11
View File
@@ -1734,6 +1734,11 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
if (found_t && (bw != t->m_TEX0.TBW || t->m_TEX0.PSM != psm))
match = false;
// Situations where font has been uploaded to the alpha channel and they use a different buffer width, this can't currently be translated correctly.
const GSLocalMemory::psm_t req_psm = GSLocalMemory::m_psm[psm];
if (!possible_shuffle && req_psm.trbpp <= 8 && req_psm.bpp == 32 && t->m_TEX0.TBW != bw && static_cast<int>(bw * 64) != t->m_valid.z && r.w > req_psm.pgs.y)
match = false;
// Different swizzle, different width, and dirty, so probably not what we want.
// DevCon.Warning("Expected %x Got %x shuffle %d draw %d", psm, t_psm, possible_shuffle, GSState::s_n);
if (match)
@@ -7282,6 +7287,9 @@ GSTexture* GSTextureCache::LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVec
else if (GSConfig.UserHacks_GPUTargetCLUTMode == GSGPUTargetCLUTMode::InsideTarget &&
t->m_TEX0.TBP0 < CBP && t->m_end_block >= CBP)
{
// If it's more than one group of 4 blocks, it's probably going to fail, horribly.
if ((size.x > GSLocalMemory::m_psm[CPSM].bs.x || size.y > GSLocalMemory::m_psm[CPSM].bs.y) && (CBP & 0x3) != (t->m_TEX0.TBP0 & 0x3))
continue;
// Somewhere within this target, can we find it?
const GSVector4i rc(0, 0, size.x, size.y);
SurfaceOffset so = ComputeSurfaceOffset(CBP, std::max<u32>(CBW, 0), CPSM, rc, t);
@@ -7294,7 +7302,7 @@ GSTexture* GSTextureCache::LookupPaletteSource(u32 CBP, u32 CPSM, u32 CBW, GSVec
}
else
{
// Not inside this target, skip.
// Not inside this target or not aligned, skip.
continue;
}
@@ -7955,14 +7963,17 @@ void GSTextureCache::Target::Update(bool cannot_scale)
// Bilinear filtering this is probably not a good thing, at least in native, but upscaling Nearest can be gross and messy.
// It's needed for depth, though.. filtering depth doesn't make much sense, but SMT3 needs it..
const bool upscaled = (m_scale != 1.0f);
const bool is_depth = m_type == DepthStencil;
const bool override_linear = (upscaled && GSConfig.UserHacks_BilinearHack == GSBilinearDirtyMode::ForceBilinear);
const bool linear = (m_type == RenderTarget && upscaled && GSConfig.UserHacks_BilinearHack != GSBilinearDirtyMode::ForceNearest);
const bool linear = (upscaled && ((!is_depth && GSConfig.UserHacks_BilinearHack != GSBilinearDirtyMode::ForceNearest) || is_depth));
GSDevice::MultiStretchRect* drects = static_cast<GSDevice::MultiStretchRect*>(
alloca(sizeof(GSDevice::MultiStretchRect) * static_cast<u32>(m_dirty.size())));
u32 ndrects = 0;
const GSOffset off(g_gs_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, m_TEX0.PSM));
// There are cases where the alpha gets populated with font data, and the target has previously been PSMCT32 (or will be) so we need to make sure it gets filled in.
const u32 psm = (m_TEX0.PSM == PSMCT24) ? PSMCT32 : m_TEX0.PSM;
const GSOffset off(g_gs_renderer->m_mem.GetOffset(m_TEX0.TBP0, m_TEX0.TBW, psm));
const u32 bpp = GSLocalMemory::m_psm[m_TEX0.PSM].bpp;
std::pair<u8, u8> alpha_minmax = {255, 0};
@@ -7985,7 +7996,7 @@ void GSTextureCache::Target::Update(bool cannot_scale)
const GSVector4i t_r(read_r - t_offset);
if (mapped)
{
if ((m_TEX0.PSM & 0xf) != PSMCT24 && m_dirty[i].rgba.c.a && bpp >= 16)
if (((m_TEX0.PSM & 0xf) != PSMCT24 || m_valid_alpha_high || m_valid_alpha_low) && m_dirty[i].rgba.c.a && bpp >= 16)
{
// TODO: Only read once in 32bit and copy to the mapped texture. Bit out of scope of this PR and not a huge impact.
const int pitch = VectorAlign(read_r.width() * sizeof(u32));
@@ -8004,7 +8015,7 @@ void GSTextureCache::Target::Update(bool cannot_scale)
const int pitch = VectorAlign(read_r.width() * sizeof(u32));
g_gs_renderer->m_mem.ReadTexture(off, read_r, s_unswizzle_buffer, pitch, TEXA);
if ((m_TEX0.PSM & 0xf) != PSMCT24 && m_dirty[i].rgba.c.a && bpp >= 16)
if (((m_TEX0.PSM & 0xf) != PSMCT24 || m_valid_alpha_high || m_valid_alpha_low) &&m_dirty[i].rgba.c.a && bpp >= 16)
{
std::pair<u8, u8> new_alpha_minmax = GSGetRGBA8AlphaMinMax(s_unswizzle_buffer, read_r.width(), read_r.height(), pitch);
alpha_minmax.first = std::min(alpha_minmax.first, new_alpha_minmax.first);
@@ -8018,7 +8029,7 @@ void GSTextureCache::Target::Update(bool cannot_scale)
drect.src = t;
drect.src_rect = GSVector4(update_r - t_offset) / t_sizef;
drect.dst_rect = GSVector4(update_r) * GSVector4(m_scale);
drect.filter = BilnIf(linear && (m_dirty[i].req_linear || override_linear));
drect.filter = BilnIf(linear && (is_depth || m_dirty[i].req_linear || override_linear));
// Copy the new GS memory content into the destination texture.
if (m_type == RenderTarget)
@@ -8047,12 +8058,13 @@ void GSTextureCache::Target::Update(bool cannot_scale)
m_rt_alpha_scale = true;
}
const bool linear = upscaled && GSConfig.UserHacks_BilinearHack != GSBilinearDirtyMode::ForceNearest;
// No need to sort here, it's all the one texture.
const ShaderConvertSelector shader = (m_type == RenderTarget) ?
(m_rt_alpha_scale ? ShaderConvert::RTA_CORRECTION : ShaderConvert::COPY) :
GetConvertShader(GSTexture::Format::Color, m_texture->GetFormat(), bpp, bpp, linear);
ShaderConvertSelector shader = GetConvertShader(GSTexture::Format::Color, m_texture->GetFormat(), bpp, bpp, 0xF, drects[0].filter);
if (m_type == RenderTarget && m_rt_alpha_scale && shader.Shader() == ShaderConvert::COPY)
{
shader = shader.SetShader(ShaderConvert::RTA_CORRECTION);
}
g_gs_device->DrawMultiStretchRects(drects, ndrects, m_texture, shader);
}
+2 -2
View File
@@ -2751,7 +2751,7 @@ static simd::float4 ToSimd(const ImVec4& vec)
void GSDeviceMTL::RenderImGui(ImDrawData* data)
{
if (data->CmdListsCount == 0)
if (data->CmdLists.Size == 0)
return;
UpdateImGuiTextures();
simd::float4 transform;
@@ -2774,7 +2774,7 @@ void GSDeviceMTL::RenderImGui(ImDrawData* data)
simd::float2 clip_scale = ToSimd(data->FramebufferScale); // (1,1) unless using retina display which are often (2,2)
ImTextureID last_tex = reinterpret_cast<ImTextureID>(nullptr);
for (int i = 0; i < data->CmdListsCount; i++)
for (int i = 0; i < data->CmdLists.Size; i++)
{
const ImDrawList* cmd_list = data->CmdLists[i];
size_t vtx_size = cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);
+15 -10
View File
@@ -112,22 +112,22 @@ fragment void ps_datm0(float4 p [[position]], DirectReadTextureIn<float> tex)
fragment float4 ps_primid_init_datm1(float4 p [[position]], DirectReadTextureIn<float> tex)
{
return tex.read(p).a < (127.5f / 255.f) ? -1 : FLT_MAX;
return tex.read(p).a < (127.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX;
}
fragment float4 ps_primid_init_datm0(float4 p [[position]], DirectReadTextureIn<float> tex)
{
return tex.read(p).a > (127.5f / 255.f) ? -1 : FLT_MAX;
return tex.read(p).a > (127.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX;
}
fragment float4 ps_primid_rta_init_datm1(float4 p [[position]], DirectReadTextureIn<float> tex)
{
return tex.read(p).a < (254.5f / 255.f) ? -1 : FLT_MAX;
return tex.read(p).a < (254.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX;
}
fragment float4 ps_primid_rta_init_datm0(float4 p [[position]], DirectReadTextureIn<float> tex)
{
return tex.read(p).a > (254.5f / 255.f) ? -1 : FLT_MAX;
return tex.read(p).a > (254.5f / 255.f) ? GSShader::PRIMID_MIN : GSShader::PRIMID_MAX;
}
fragment float4 ps_rta_correction(ConvertShaderData data [[stage_in]], ConvertPSRes res)
@@ -175,11 +175,6 @@ fragment float4 ps_convert_depth16_rgb5a1(ConvertShaderData data [[stage_in]], C
return convert_depth16_rgba8(res.sample(data.t)) / 255.f;
}
fragment float ps_convert_float32_depth_to_color(ConvertShaderData data [[stage_in]], ConvertPSDepthRes res)
{
return res.sample(data.t);
}
fragment float4 ps_downsample_copy(ConvertShaderData data [[stage_in]],
texture2d<float> texture [[texture(GSMTLTextureIndexNonHW)]],
constant GSMTLDownsamplePSUniform& uniform [[buffer(GSMTLBufferIndexUniforms)]])
@@ -260,7 +255,7 @@ struct ConvertToDepthRes
float depthTR = convert(texture.read(coords.zy));
float depthBL = convert(texture.read(coords.xw));
float depthBR = convert(texture.read(coords.zw));
return mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y);
return floor(mix(mix(depthTL, depthTR, mix_vals.x), mix(depthBL, depthBR, mix_vals.x), mix_vals.y) * 0x1p32) * 0x1p-32;
}
template <float (&convert)(half4)>
@@ -273,6 +268,16 @@ struct ConvertToDepthRes
}
};
static float4 primid_to_rgba8(float p)
{
return float4(as_type<uchar4>(p)) / 255.f;
}
fragment float4 ps_convert_primid_rgba8(ConvertShaderData data [[stage_in]], ConvertPSDepthOrColorRes res)
{
return primid_to_rgba8(res.sample(data.t));
}
fragment DepthOrColorOut ps_depth_copy(ConvertShaderData data [[stage_in]], ConvertPSDepthOrColorRes res)
{
return res.sample(data.t);
+7 -5
View File
@@ -1304,8 +1304,12 @@ struct PSMain
{
if (PS_FBMASK)
{
float multi = PS_COLCLIP_HW ? 65535.0 : 255.5;
C = float4((uint4(int4(C)) & (cb.fbmask ^ 0xff)) | (uint4(current_color * float4(multi, multi, multi, 255)) & cb.fbmask));
float multi_rgb = PS_COLCLIP_HW ? 65535.0 : 255.5;
float multi_a = PS_RTA_CORRECTION ? 128.0 : 255.0;
float4 RT = current_color;
RT.rgb = RT.rgb * multi_rgb;
RT.a = round(RT.a * multi_a);
C = float4((uint4(int4(C)) & (cb.fbmask ^ 0xff)) | (uint4(RT) & cb.fbmask));
}
}
@@ -1769,7 +1773,7 @@ fragment MainPSOut ps_main(
main.current_depth = ds_tex.read(coord).x;
}
if (NEEDS_RT || (PS_ROV_COLOR && any(cb.fbmask == 0xff)))
if (NEEDS_RT)
{
if (PS_ROV_COLOR)
{
@@ -1797,8 +1801,6 @@ fragment MainPSOut ps_main(
ds_rov.write(out.depth, coord);
if (PS_ROV_COLOR && !main.color_discarded)
{
if (!PS_FBMASK)
out.c0 = select(out.c0, main.current_color, cb.fbmask == 0xff);
if (ROV_NEEDS_R32)
rt_u32.write(pack_float_to_unorm4x8(out.c0), coord);
else
+9 -3
View File
@@ -432,6 +432,8 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
const char* name = shader.EntryPoint();
std::string macro;
macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX);
macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN);
macro += fmt::format("#define HAS_BILN {}\n", static_cast<int>(shader.Biln()));
macro += fmt::format("#define HAS_STENCIL_OUTPUT {}\n", static_cast<int>(shader.StencilOutput()));
macro += fmt::format("#define HAS_INTEGER_OUTPUT {}\n", static_cast<int>(shader.IntegerOutputBpp() != 0));
@@ -609,9 +611,13 @@ bool GSDeviceOGL::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
for (size_t i = 0; i < std::size(m_date.primid_ps); i++)
{
std::string macro;
macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX);
macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN);
const std::string ps(GetShaderSource(
fmt::format("ps_primid_image_init_{}", i),
GL_FRAGMENT_SHADER, *convert_glsl));
GL_FRAGMENT_SHADER, *convert_glsl, macro));
m_shader_cache.GetProgram(&m_date.primid_ps[i], m_convert.vs, ps);
m_date.primid_ps[i].SetFormattedName("PrimID Destination Alpha Init %d", i);
}
@@ -2506,7 +2512,7 @@ void GSDeviceOGL::RenderImGui()
{
ImGui::Render();
const ImDrawData* draw_data = ImGui::GetDrawData();
if (draw_data->CmdListsCount == 0)
if (draw_data->CmdLists.Size == 0)
return;
UpdateImGuiTextures();
@@ -2537,7 +2543,7 @@ void GSDeviceOGL::RenderImGui()
GSVector4i last_scissor = GSVector4i::xffffffff();
// Render command lists
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (int n = 0; n < draw_data->CmdLists.Size; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
+18 -136
View File
@@ -287,125 +287,6 @@ void ConvertVertexBuffer(const GSDrawingContext* RESTRICT ctx, GSVertexSW* RESTR
}
}
// Fix ST coordinates that would overflow the rasterizer fixed point format by rewriting the vertices.
template <u32 primclass>
void GSRendererSW::RewriteVerticesIfSTOverflow()
{
if (PRIM->TME && PRIM->FST == 0)
{
const GSVector4 tsize = GSVector4(
static_cast<float>(1 << m_context->TEX0.TW),
static_cast<float>(1 << m_context->TEX0.TH),
1.0f,
1.0f);
// SW rasterizer stores UV in 1.15.16 format so clamp to +/- (2^15 - 2) (-2 so bilinear doesn't overflow).
// Do the division by texture size here to avoid divisions for each vertex.
const GSVector4 OVERFLOW_VAL = GSVector4::cxpr(static_cast<float>((1 << 15) - 2)) / tsize;
// Only rewrite big/small S or T when the clamping mode is CLAMP or REGION_CLAMP.
const GSVector4i clamp_mode = GSVector4i(
(m_context->CLAMP.WMS == CLAMP_CLAMP || m_context->CLAMP.WMS == CLAMP_REGION_CLAMP) ? 0xFFFFFFFF : 0,
(m_context->CLAMP.WMT == CLAMP_CLAMP || m_context->CLAMP.WMT == CLAMP_REGION_CLAMP) ? 0xFFFFFFFF : 0,
0,
0);
const bool st_overflow =
((GSVector4i::cast(m_vt.m_min.t <= -OVERFLOW_VAL * tsize) & clamp_mode).mask() & 3) ||
((GSVector4i::cast(m_vt.m_max.t >= OVERFLOW_VAL * tsize) & clamp_mode).mask() & 3) ||
m_vt.nan.value;
if (st_overflow)
{
constexpr int n = GSUtil::GetClassVertexCount(primclass);
// Make sure the copy buffer is large enough.
while (m_max_vertex_count < m_index->tail)
GrowVertexBuffer();
GSVertex* RESTRICT vertex = m_vertex->buff;
GSVertex* RESTRICT vertex_copy = m_vertex->buff_copy;
u16* RESTRICT index = m_index->buff;
for (int i = 0; i < static_cast<int>(m_index->tail); i += n)
{
GSVector4 stcq[n];
// Load STQ for this primitive.
for (int j = 0; j < n; j++)
stcq[j] = GSVector4::cast(GSVector4i(vertex[index[i + j]].m[0]));
// Perform Q division and see which values need to be rewritten.
GSVector4 uv[n];
GSVector4i small{}, big{}, nan{};
for (int j = 0; j < n; j++)
{
// For sprites always use Q of second vertex.
const GSVector4 q = primclass == GS_SPRITE_CLASS ? stcq[1].wwww() : stcq[j].wwww();
uv[j] = (stcq[j] / q).xyzw(GSVector4::zero());
small |= GSVector4i::cast(uv[j] <= -OVERFLOW_VAL);
big |= GSVector4i::cast(uv[j] >= OVERFLOW_VAL);
nan |= GSVector4i::cast(uv[j] != uv[j]);
}
// Get the new values for fields that will be rewritten.
// The follows rules are used:
// 1. If there are small values but not big or nans, make all vertices small.
// 2. If there are big values but not small or nans, make all vertices big.
// 3. If there are both big and small values, or nans, make all vertices zero.
GSVector4 uv_new = GSVector4::zero();
uv_new = uv_new.blend32(-OVERFLOW_VAL, GSVector4::cast(small));
uv_new = uv_new.blend32(OVERFLOW_VAL, GSVector4::cast(big));
uv_new = uv_new.blend32(GSVector4::zero(), GSVector4::cast((small & big) | nan));
const GSVector4i rewrite = (((small | big) & clamp_mode) | nan).upl64(GSVector4i::zero());
// If both S and T are rewritten, no point in keeping Q. Just set it to 1.0f;
if ((GSVector4::cast(rewrite).mask() & 3) == 3)
{
for (int j = 0; j < n; j++)
stcq[j] = stcq[j].template insert32<0, 3>(GSVector4::m_one);
}
// Rewrite the fields that require it and write to the copy buffer.
for (int j = 0; j < n; j++)
{
// For sprites always use Q of second vertex.
const GSVector4 q = (primclass == GS_SPRITE_CLASS) ? stcq[1].wwww() : stcq[j].wwww();
stcq[j] = stcq[j].blend32(uv_new * q, GSVector4::cast(rewrite));
vertex_copy[i + j].m[0] = GSVector4i::cast(stcq[j]);
vertex_copy[i + j].m[1] = vertex[index[i + j]].m[1];
index[i + j] = i + j;
}
}
// Swap the buffers and fix the counts.
std::swap(m_vertex->buff, m_vertex->buff_copy);
m_vertex->head = m_vertex->next = m_vertex->tail = m_index->tail;
// Recalculate ST min/max/eq in the vertex trace.
GSVector4 tmin = GSVector4::cxpr(FLT_MAX);
GSVector4 tmax = GSVector4::cxpr(-FLT_MAX);
for (int i = 0; i < static_cast<int>(m_index->tail); i += n)
{
for (int j = 0; j < n; j++)
{
GSVector4 stcq = GSVector4::cast(GSVector4i(m_vertex->buff[i + j].m[0]));
const float Q = (primclass == GS_SPRITE_CLASS) ? stcq.w : m_vertex->buff[i + 1].RGBAQ.Q;
stcq = (stcq / Q).xyzw(stcq);
tmin = tmin.min(stcq);
tmax = tmax.max(stcq);
}
}
m_vt.m_min.t = tmin.xyww() * tsize;
m_vt.m_max.t = tmax.xyww() * tsize;
m_vt.m_eq.stq = (m_vt.m_min.t == m_vt.m_max.t).mask();
}
}
}
void GSVertexSWInitStatic()
{
#define InitCVB4(P, T, F, Q) GSVertexSW::s_cvb[P][T][F][Q] = ConvertVertexBuffer<P, T, F, Q>;
@@ -427,24 +308,25 @@ MULTI_ISA_UNSHARED_END
void GSRendererSW::Draw()
{
const GSDrawingContext* context = m_context;
switch (m_vt.m_primclass)
if (!GSConfig.UserHacks_RewriteLargeSTCoords)
{
case GS_POINT_CLASS:
RewriteVerticesIfSTOverflow<GS_POINT_CLASS>();
break;
case GS_LINE_CLASS:
RewriteVerticesIfSTOverflow<GS_LINE_CLASS>();
break;
case GS_TRIANGLE_CLASS:
RewriteVerticesIfSTOverflow<GS_TRIANGLE_CLASS>();
break;
case GS_SPRITE_CLASS:
RewriteVerticesIfSTOverflow<GS_SPRITE_CLASS>();
break;
default:
pxFailRel("Unknown primitive class.");
break;
// SW rasterizer stores UV in 1.15.16 format so clamp to +/- (2^15 - 2) (-2 so bilinear doesn't overflow).
// Also only do this for CLAMP and CLAMP_REGION modes to reduce the performance impact.
const GSVector4 tsize = GSVector4(
static_cast<float>(1 << m_context->TEX0.TW),
static_cast<float>(1 << m_context->TEX0.TH),
1.0f,
1.0f);
// Large value is given in terms of normalized ST / Q coordinates.
const GSVector4 large_val = GSVector4::cxpr(static_cast<float>((1 << 15) - 2)) / tsize;
RewriteVerticesIfLargeST(large_val, true);
}
else
{
// More sensitive as the rewrite threshold is lower and we do it for all clamp mode.
// The performance cost will also be higher.
RewriteVerticesIfLargeST(GSVector4::cxpr(16.0f), false);
}
auto data = m_vertex_heap.make_shared<SharedData>().cast<GSRasterizerData>();
+85 -55
View File
@@ -1153,6 +1153,77 @@ bool GSDeviceVK::SetGPUPipelineStatisticsEnabled(bool enabled)
return (enabled == m_gpu_pipeline_statistics_enabled);
}
void GSDeviceVK::StartGPUTiming(u32 index)
{
if (m_gpu_timing_enabled || m_spin_timer)
{
FrameResources& resources = m_frame_resources[index];
vkCmdResetQueryPool(resources.command_buffers[1], m_timestamp_query_pool, index * 2, 2);
vkCmdWriteTimestamp(
resources.command_buffers[1], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, m_timestamp_query_pool, index * 2);
resources.timestamp_query_state = QueryState::Querying;
}
}
void GSDeviceVK::EndGPUTiming(u32 index)
{
FrameResources& resources = m_frame_resources[index];
const bool wants_timestamp = m_gpu_timing_enabled || m_spin_timer;
if (wants_timestamp && resources.timestamp_query_state == QueryState::Querying)
{
vkCmdWriteTimestamp(m_current_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, m_timestamp_query_pool,
m_current_frame * 2 + 1);
resources.timestamp_query_state = QueryState::Ready;
}
}
void GSDeviceVK::ReadGPUTiming(u32 index)
{
FrameResources& resources = m_frame_resources[index];
const bool wants_timestamps = m_gpu_timing_enabled || resources.spin_id >= 0;
if (wants_timestamps && resources.timestamp_query_state == QueryState::Ready)
{
std::array<u64, 2> timestamps;
const VkResult res =
vkGetQueryPoolResults(m_device, m_timestamp_query_pool, index * 2, static_cast<u32>(timestamps.size()),
sizeof(u64) * timestamps.size(), timestamps.data(), sizeof(u64), VK_QUERY_RESULT_64_BIT);
if (res == VK_SUCCESS)
{
// if we didn't write the timestamp at the start of the cmdbuffer (just enabled timing), the first TS will be zero
if (timestamps[0] > 0 && m_gpu_timing_enabled)
{
const double ns_diff =
(timestamps[1] - timestamps[0]) * static_cast<double>(m_device_properties.limits.timestampPeriod);
m_accumulated_gpu_time += ns_diff / 1000000.0;
}
if (resources.spin_id >= 0)
{
if (m_optional_extensions.vk_ext_calibrated_timestamps && timestamps[1] > 0)
{
const u64 end = timestamps[1] * m_spin_timestamp_scale + m_spin_timestamp_offset;
m_spin_manager.DrawCompleted(resources.spin_id, resources.submit_timestamp, end);
}
else if (!m_optional_extensions.vk_ext_calibrated_timestamps && timestamps[0] > 0)
{
const u64 begin = timestamps[0] * m_spin_timestamp_scale;
const u64 end = timestamps[1] * m_spin_timestamp_scale;
m_spin_manager.DrawCompleted(resources.spin_id, begin, end);
}
}
}
else
{
LOG_VULKAN_ERROR(res, "vkGetQueryPoolResults failed: ");
}
resources.timestamp_query_state = QueryState::None;
}
}
void GSDeviceVK::ScanForCommandBufferCompletion()
{
for (u32 check_index = (m_current_frame + 1) % NUM_COMMAND_BUFFERS; check_index != m_current_frame;
@@ -1222,12 +1293,7 @@ void GSDeviceVK::SubmitCommandBuffer(VKSwapChain* present_swap_chain)
}
}
bool wants_timestamp = m_gpu_timing_enabled || m_spin_timer;
if (wants_timestamp && resources.timestamp_written)
{
vkCmdWriteTimestamp(m_current_command_buffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, m_timestamp_query_pool,
m_current_frame * 2 + 1);
}
EndGPUTiming(m_current_frame);
if (resources.pipeline_statistics_query == QueryState::Querying)
{
@@ -1363,43 +1429,7 @@ void GSDeviceVK::CommandBufferCompleted(u32 index)
it();
resources.cleanup_resources.clear();
bool wants_timestamps = m_gpu_timing_enabled || resources.spin_id >= 0;
if (wants_timestamps && resources.timestamp_written)
{
std::array<u64, 2> timestamps;
VkResult res =
vkGetQueryPoolResults(m_device, m_timestamp_query_pool, index * 2, static_cast<u32>(timestamps.size()),
sizeof(u64) * timestamps.size(), timestamps.data(), sizeof(u64), VK_QUERY_RESULT_64_BIT);
if (res == VK_SUCCESS)
{
// if we didn't write the timestamp at the start of the cmdbuffer (just enabled timing), the first TS will be zero
if (timestamps[0] > 0 && m_gpu_timing_enabled)
{
const double ns_diff =
(timestamps[1] - timestamps[0]) * static_cast<double>(m_device_properties.limits.timestampPeriod);
m_accumulated_gpu_time += ns_diff / 1000000.0;
}
if (resources.spin_id >= 0)
{
if (m_optional_extensions.vk_ext_calibrated_timestamps && timestamps[1] > 0)
{
u64 end = timestamps[1] * m_spin_timestamp_scale + m_spin_timestamp_offset;
m_spin_manager.DrawCompleted(resources.spin_id, resources.submit_timestamp, end);
}
else if (!m_optional_extensions.vk_ext_calibrated_timestamps && timestamps[0] > 0)
{
u64 begin = timestamps[0] * m_spin_timestamp_scale;
u64 end = timestamps[1] * m_spin_timestamp_scale;
m_spin_manager.DrawCompleted(resources.spin_id, begin, end);
}
}
}
else
{
LOG_VULKAN_ERROR(res, "vkGetQueryPoolResults failed: ");
}
}
ReadGPUTiming(index);
}
void GSDeviceVK::MoveToNextCommandBuffer()
@@ -1434,13 +1464,7 @@ void GSDeviceVK::ActivateCommandBuffer(u32 index)
if (res != VK_SUCCESS)
LOG_VULKAN_ERROR(res, "vkBeginCommandBuffer failed: ");
bool wants_timestamp = m_gpu_timing_enabled || m_spin_timer;
if (wants_timestamp)
{
vkCmdResetQueryPool(resources.command_buffers[1], m_timestamp_query_pool, index * 2, 2);
vkCmdWriteTimestamp(
resources.command_buffers[1], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, m_timestamp_query_pool, index * 2);
}
StartGPUTiming(index);
if (resources.pipeline_statistics_query == QueryState::Ready)
{
@@ -1471,7 +1495,6 @@ void GSDeviceVK::ActivateCommandBuffer(u32 index)
resources.fence_counter = m_next_fence_counter++;
resources.init_buffer_used = false;
resources.timestamp_written = wants_timestamp;
m_current_frame = index;
m_current_command_buffer = resources.command_buffers[1];
@@ -4200,6 +4223,8 @@ bool GSDeviceVK::CompileConvertPipelines()
gpb.SetColorWriteMask(0, shader.Mask());
std::string macro;
macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX);
macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN);
macro += fmt::format("#define HAS_BILN {}\n", static_cast<int>(shader.Biln()));
macro += fmt::format("#define HAS_STENCIL_OUTPUT {}\n", static_cast<int>(shader.StencilOutput()));
macro += fmt::format("#define HAS_INTEGER_OUTPUT {}\n", static_cast<int>(shader.IntegerOutputBpp() != 0));
@@ -4267,9 +4292,14 @@ bool GSDeviceVK::CompileConvertPipelines()
for (u32 datm = 0; datm < 4; datm++)
{
std::string macro;
macro += fmt::format("#define PRIMID_MAX {}\n", GSShader::PRIMID_MAX);
macro += fmt::format("#define PRIMID_MIN {}\n", GSShader::PRIMID_MIN);
const std::string source_with_header = macro + *source;
const std::string entry_point(StringUtil::StdStringFromFormat("ps_primid_image_init_%d", datm));
VkShaderModule ps =
GetUtilityFragmentShader(*source, entry_point.c_str());
VkShaderModule ps = GetUtilityFragmentShader(source_with_header, entry_point.c_str());
if (ps == VK_NULL_HANDLE)
return false;
@@ -4645,7 +4675,7 @@ void GSDeviceVK::RenderImGui()
{
ImGui::Render();
const ImDrawData* draw_data = ImGui::GetDrawData();
if (draw_data->CmdListsCount == 0)
if (draw_data->CmdLists.Size == 0)
return;
UpdateImGuiTextures();
@@ -4668,7 +4698,7 @@ void GSDeviceVK::RenderImGui()
// this is for presenting, we don't want to screw with the viewport/scissor set by display
m_dirty_flags &= ~(DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR);
for (int n = 0; n < draw_data->CmdListsCount; n++)
for (int n = 0; n < draw_data->CmdLists.Size; n++)
{
const ImDrawList* cmd_list = draw_data->CmdLists[n];
+4 -2
View File
@@ -209,7 +209,6 @@ private:
void CalibrateSpinTimestamp();
u64 GetCPUTimestamp();
// For pipeline statistics
enum class QueryState
{
None,
@@ -228,7 +227,7 @@ private:
u32 submit_timestamp = 0;
bool init_buffer_used = false;
bool needs_fence_wait = false;
bool timestamp_written = false;
QueryState timestamp_query_state = QueryState::None;
QueryState pipeline_statistics_query = QueryState::None;
std::vector<std::function<void()>> cleanup_resources;
@@ -575,6 +574,9 @@ public:
bool IsPresenting() const;
bool SetGPUTimingEnabled(bool enabled) override;
void StartGPUTiming(u32 index);
void EndGPUTiming(u32 index);
void ReadGPUTiming(u32 index);
float GetAndResetAccumulatedGPUTime() override;
bool SetGPUPipelineStatisticsEnabled(bool enabled) override;
+2 -2
View File
@@ -104,9 +104,9 @@ std::unique_ptr<GSTextureVK> GSTextureVK::Create(Usage usage, Format format, int
if (format == Format::UNorm8)
{
// for r8 textures, swizzle it across all 4 components. the shaders depend on it being in alpha.. why?
// UNorm8 wants value in alpha, not red.
static constexpr const VkComponentMapping r8_swizzle = {
VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_R };
VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_R };
vci.components = r8_swizzle;
}
+164 -11
View File
@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
// SPDX-License-Identifier: GPL-3.0+
#include "PerformanceMetrics.h"
#include "GS/GSPerfMon.h"
#include "GS.h"
#include "GS/GSLzma.h"
#include "GSDumpReplayer.h"
@@ -27,6 +29,7 @@
#include "common/Timer.h"
#include <atomic>
#include <cinttypes>
static void GSDumpReplayerCpuReserve();
static void GSDumpReplayerCpuShutdown();
@@ -46,6 +49,19 @@ static bool s_needs_state_loaded = false;
static u64 s_frame_ticks = 0;
static u64 s_next_frame_time = 0;
static bool s_is_dump_runner = false;
static bool s_dump_perf_metrics = true;
static bool s_use_frame_range = false;
static bool s_init_frame_range = false;
static u32 s_frame_start = 0;
static u32 s_frame_end = 0;
static u32 s_frame_start_packet = 0;
static u32 s_frame_end_packet = 0;
static GSPerfMon s_total_gs_stats;
static GSPerfMon s_last_g_perfmon;
static u64 s_total_frames = 0;
static u64 s_total_drawn_frames = 0;
R5900cpu GSDumpReplayerCpu = {
GSDumpReplayerCpuReserve,
@@ -70,9 +86,10 @@ bool GSDumpReplayer::IsRunner()
return s_is_dump_runner;
}
void GSDumpReplayer::SetIsDumpRunner(bool is_runner)
void GSDumpReplayer::SetIsDumpRunner(bool is_runner, bool dump_perf)
{
s_is_dump_runner = is_runner;
s_dump_perf_metrics = dump_perf;
}
void GSDumpReplayer::SetLoopCount(s32 loop_count)
@@ -85,6 +102,13 @@ int GSDumpReplayer::GetLoopCount()
return s_dump_loop_count;
}
void GSDumpReplayer::SetFrameRange(bool use, u32 start, u32 end)
{
s_use_frame_range = use;
s_frame_start = start;
s_frame_end = end;
}
bool GSDumpReplayer::Initialize(const char* filename, Error* error)
{
Common::Timer timer;
@@ -145,6 +169,8 @@ void GSDumpReplayer::Shutdown()
{
Console.WriteLn("(GSDumpReplayer) Shutting down.");
DumpStats();
Cpu = nullptr;
psxCpu = nullptr;
CpuVU0 = nullptr;
@@ -196,6 +222,13 @@ void GSDumpReplayerCpuReset()
s_needs_state_loaded = true;
s_current_packet = 0;
s_dump_frame_number = 0;
s_total_gs_stats.Reset();
s_last_g_perfmon.Reset();
s_init_frame_range = false;
s_frame_start_packet = 0;
s_frame_end_packet = 0;
s_total_frames = 0;
s_total_drawn_frames = 0;
}
static void GSDumpReplayerLoadInitialState()
@@ -256,17 +289,10 @@ static void GSDumpReplayerFrameLimit()
s_next_frame_time = std::max(now, s_next_frame_time + s_frame_ticks);
}
void GSDumpReplayerCpuStep()
void AdvanceNextLoop()
{
if (s_needs_state_loaded)
{
GSDumpReplayerLoadInitialState();
s_needs_state_loaded = false;
}
const GSDumpFile::GSData& packet = s_dump_file->GetPackets()[s_current_packet];
s_current_packet = (s_current_packet + 1) % static_cast<u32>(s_dump_file->GetPackets().size());
if (s_current_packet == 0)
const bool end_of_dump = (s_current_packet == static_cast<u32>(s_dump_file->GetPackets().size()));
if (end_of_dump || (s_init_frame_range && s_current_packet > s_frame_end_packet))
{
s_dump_frame_number = 0;
if (s_dump_loop_count > 0)
@@ -277,6 +303,55 @@ void GSDumpReplayerCpuStep()
s_dump_running = false;
}
}
}
void UpdateFrameRangePacketsOnVSync()
{
if (s_use_frame_range && !s_init_frame_range)
{
if (s_dump_frame_number == s_frame_start)
{
// +1 since the current packet is the previous frame VSync packet.
s_frame_start_packet = s_current_packet + 1;
}
else if (s_dump_frame_number >= s_frame_end && s_frame_end > s_frame_start)
{
// Current packet is the VSync packet of the last frame we want to loop over.
s_frame_end_packet = s_current_packet;
s_init_frame_range = true;
}
}
}
void CheckFrameRange()
{
if (s_init_frame_range)
{
if (s_current_packet > s_frame_end_packet || s_current_packet < s_frame_start_packet)
{
s_dump_frame_number = s_frame_start;
s_current_packet = s_frame_start_packet;
}
}
else if (s_current_packet == static_cast<u32>(s_dump_file->GetPackets().size()))
{
// This will run if the frame range goes past the end of the dump.
s_frame_end_packet = s_current_packet;
s_init_frame_range = true;
}
}
void GSDumpReplayerCpuStep()
{
if (s_needs_state_loaded)
{
GSDumpReplayerLoadInitialState();
s_needs_state_loaded = false;
PerformanceMetrics::StartSavingMetrics(UINT32_MAX);
}
// Get the next packet.
const GSDumpFile::GSData& packet = s_dump_file->GetPackets()[s_current_packet];
switch (packet.id)
{
@@ -323,6 +398,7 @@ void GSDumpReplayerCpuStep()
if (VMManager::Internal::IsExecutionInterrupted())
GSDumpReplayerExitExecution();
Host::PumpMessagesOnCPUThread();
UpdateFrameRangePacketsOnVSync();
}
break;
@@ -343,6 +419,18 @@ void GSDumpReplayerCpuStep()
}
break;
}
// Increment the packet counter.
s_current_packet++;
// Increment the loop counter.
AdvanceNextLoop();
// Adjust packet index based on the frame range we're replaying.
CheckFrameRange();
// Loop packet index.
s_current_packet %= static_cast<u32>(s_dump_file->GetPackets().size());
}
void GSDumpReplayerCpuExecute()
@@ -404,3 +492,68 @@ void GSDumpReplayer::RenderUI()
#undef DRAW_LINE
}
static void UpdateSingleGSStat(GSPerfMon::counter_t counter)
{
const double curr = g_perfmon.GetCounter(counter);
const double last = s_last_g_perfmon.GetCounter(counter);
// GSPerfMon resets every 30 frames to zero.
s_total_gs_stats.Put(counter, curr < last ? curr : (curr - last));
};
void GSDumpReplayer::UpdateGSStats()
{
// Called on GS thread.
if (GSIsHardwareRenderer())
{
const double last_draws = s_total_gs_stats.GetCounter(GSPerfMon::Draw);
const double last_uploads = s_total_gs_stats.GetCounter(GSPerfMon::TextureUploads);
UpdateSingleGSStat(GSPerfMon::Draw);
UpdateSingleGSStat(GSPerfMon::DrawCalls);
UpdateSingleGSStat(GSPerfMon::RenderPasses);
UpdateSingleGSStat(GSPerfMon::Barriers);
UpdateSingleGSStat(GSPerfMon::TextureCopies);
UpdateSingleGSStat(GSPerfMon::TextureUploads);
UpdateSingleGSStat(GSPerfMon::Readbacks);
UpdateSingleGSStat(GSPerfMon::TextureCopiesROV);
UpdateSingleGSStat(GSPerfMon::DrawCallsROV);
UpdateSingleGSStat(GSPerfMon::BarriersROV);
s_last_g_perfmon = g_perfmon;
const bool idle_frame = s_total_frames > 0 &&
s_total_gs_stats.GetCounter(GSPerfMon::Draw) == last_draws &&
s_total_gs_stats.GetCounter(GSPerfMon::TextureUploads) == last_uploads;
if (!idle_frame)
s_total_drawn_frames++;
s_total_frames++;
std::atomic_thread_fence(std::memory_order_release);
}
}
static void DumpStatAndAvg(const char* format, double stat)
{
Console.WriteLn(format, static_cast<u64>(stat), static_cast<u64>(std::ceil(stat / static_cast<double>(s_total_drawn_frames))));
}
void GSDumpReplayer::DumpStats()
{
std::atomic_thread_fence(std::memory_order_acquire);
Console.WriteLnFmt("======= HW STATISTICS FOR {} ({}) FRAMES ========", s_total_frames, s_total_drawn_frames);
DumpStatAndAvg("@HWSTAT@ Draw Calls: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::DrawCalls));
DumpStatAndAvg("@HWSTAT@ Render Passes: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::RenderPasses));
DumpStatAndAvg("@HWSTAT@ Barriers: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::Barriers));
DumpStatAndAvg("@HWSTAT@ Copies: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::TextureCopies));
DumpStatAndAvg("@HWSTAT@ Uploads: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::TextureUploads));
DumpStatAndAvg("@HWSTAT@ Readbacks: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::Readbacks));
DumpStatAndAvg("@HWSTAT@ Copies (ROV): %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::TextureCopiesROV));
DumpStatAndAvg("@HWSTAT@ Draws Calls (ROV): %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::DrawCallsROV));
DumpStatAndAvg("@HWSTAT@ Barriers (ROV): %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::BarriersROV));
if (s_dump_perf_metrics)
PerformanceMetrics::DumpSavedMetrics();
Console.WriteLnFmt("============================================");
}
+6 -1
View File
@@ -16,7 +16,8 @@ namespace GSDumpReplayer
void SetLoopCount(s32 loop_count = 0);
int GetLoopCount();
bool IsRunner();
void SetIsDumpRunner(bool is_runner);
void SetIsDumpRunner(bool is_runner, bool dump_perf = true);
void SetFrameRange(bool use, u32 start, u32 end);
bool Initialize(const char* filename, Error* error = nullptr);
bool ChangeDump(const char* filename);
@@ -28,4 +29,8 @@ namespace GSDumpReplayer
u32 GetFrameNumber();
void RenderUI();
void UpdateGSStats();
void DumpStats();
} // namespace GSDumpReplayer
+8
View File
@@ -376,6 +376,7 @@ static const char* s_gs_hw_fix_names[] = {
"nativePaletteDraw",
"estimateTextureRegion",
"drawBuffering",
"rewriteLargeSTCoords",
"PCRTCOffsets",
"PCRTCOverscan",
"trilinearFiltering",
@@ -622,6 +623,9 @@ bool GameDatabaseSchema::GameEntry::configMatchesHWFix(const Pcsx2Config::GSOpti
case GSHWFixId::DrawBuffering:
return (static_cast<int>(config.UserHacks_DrawBuffering) == value);
case GSHWFixId::RewriteLargeSTCoords:
return (static_cast<int>(config.UserHacks_RewriteLargeSTCoords) == value);
case GSHWFixId::PCRTCOffsets:
return (static_cast<int>(config.PCRTCOffsets) == value);
@@ -793,6 +797,10 @@ void GameDatabaseSchema::GameEntry::applyGSHardwareFixes(Pcsx2Config::GSOptions&
config.UserHacks_DrawBuffering = (value > 0);
break;
case GSHWFixId::RewriteLargeSTCoords:
config.UserHacks_RewriteLargeSTCoords = (value > 0);
break;
case GSHWFixId::PCRTCOffsets:
config.PCRTCOffsets = (value > 0);
break;
+1
View File
@@ -61,6 +61,7 @@ namespace GameDatabaseSchema
NativePaletteDraw,
EstimateTextureRegion,
DrawBuffering,
RewriteLargeSTCoords,
PCRTCOffsets,
PCRTCOverscan,
+1 -1
View File
@@ -267,7 +267,7 @@ bool GameList::GetIsoSerialAndCRC(const std::string& path, s32* disc_type, std::
// TODO: we could include the version in the game list?
*disc_type = DoCDVDdetectDiskType();
cdvdGetDiscInfo(serial, nullptr, nullptr, crc, nullptr);
cdvdGetDiscInfo(serial, nullptr, nullptr, nullptr, crc, nullptr);
DoCDVDclose();
return true;
}
+1 -1
View File
@@ -412,7 +412,7 @@ namespace FullscreenUI
void DrawMemoryCardSettingsPage();
void DrawNetworkHDDSettingsPage();
void DrawFoldersSettingsPage();
void DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& settings_lock);
void DrawAchievementsSettingsPage();
void DrawControllerSettingsPage();
void DrawHotkeySettingsPage();
void DrawAdvancedSettingsPage();
+64 -55
View File
@@ -1984,7 +1984,7 @@ void FullscreenUI::DrawSettingsWindow()
break;
case SettingsPage::Achievements:
DrawAchievementsSettingsPage(lock);
DrawAchievementsSettingsPage();
break;
case SettingsPage::Controller:
@@ -2658,6 +2658,13 @@ void FullscreenUI::DrawEmulationSettingsPage()
SetSettingsChanged(bsi);
}
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_ANGLES_RIGHT, "Advanced Frame Display"),
FSUI_CSTR("Displays the newest frame immediately at the beginning of the "
"frame raster time, instead of at the end. Can reduce perceived "
"input lag, but may cause problems with some games, such as "
"Soulcalibur II and Baldur's Gate Dark Alliance II. "),
"EmuCore/GS", "AdvancedFrameDisplay", false);
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_ARROWS_SPIN, "Vertical Sync (VSync)"), FSUI_CSTR("Synchronizes frame presentation with host refresh."),
"EmuCore/GS", "VsyncEnable", false);
@@ -3236,6 +3243,9 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_CROP, "Estimate Texture Region"),
FSUI_CSTR("Attempts to reduce the texture size when games do not set it themselves (e.g. Snowblind games)."), "EmuCore/GS",
"UserHacks_EstimateTextureRegion", false, manual_hw_fixes);
DrawToggleSetting(bsi, FSUI_CSTR("Rewrite Large ST"),
FSUI_CSTR("Rewrite large ST coordinates and clamp the values."), "EmuCore/GS",
"UserHacks_RewriteLargeSTCoords", false, manual_hw_fixes);
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_PALETTE, "GPU Palette Conversion"),
FSUI_CSTR("When enabled GPU converts colormap-textures, otherwise the CPU will. It is a trade-off between GPU and CPU."),
"EmuCore/GS", "paltex", false, manual_hw_fixes);
@@ -4560,15 +4570,9 @@ void FullscreenUI::DrawAchievementsLoginWindow()
Host::SetBaseBoolSettingValue("Achievements", "ChallengeMode", true);
Host::CommitBaseSettingChanges();
VMManager::ApplySettings();
Host::RunOnCPUThread([]() { VMManager::ApplySettings(); });
bool has_active_game;
{
auto lock = Achievements::GetLock();
has_active_game = Achievements::HasActiveGame();
}
if (has_active_game)
if (VMManager::HasValidVM())
{
OpenConfirmMessageDialog(FSUI_STR("Reset System"),
FSUI_STR("Hardcore mode will not be enabled until the system is reset. Do you want to reset the system now?"),
@@ -4590,10 +4594,9 @@ void FullscreenUI::DrawAchievementsLoginWindow()
{
Host::SetBaseBoolSettingValue("Achievements", "Enabled", true);
Host::CommitBaseSettingChanges();
VMManager::ApplySettings();
Host::RunOnCPUThread([]() { VMManager::ApplySettings(); });
prompt_hardcore();
}
prompt_hardcore();
});
}
else
@@ -4687,7 +4690,7 @@ void FullscreenUI::DrawAchievementsLoginWindow()
ImGui::PopStyleVar(2);
}
void FullscreenUI::DrawAchievementsSettingsPage(std::unique_lock<std::mutex>& settings_lock)
void FullscreenUI::DrawAchievementsSettingsPage()
{
#ifdef ENABLE_RAINTEGRATION
if (Achievements::IsUsingRAIntegration())
@@ -5923,16 +5926,16 @@ TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when a game is started.");
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when you minimize the window or switch to another application, and unpauses when you switch back.");
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when a controller with bindings is disconnected.");
TRANSLATE_NOOP("FullscreenUI", "Pauses the emulator when you open the quick menu, and unpauses when you close it.");
TRANSLATE_NOOP("FullscreenUI", "Display a modal dialog when a save state load/save operation fails.");
TRANSLATE_NOOP("FullscreenUI", "Displays a modal dialog when a save state load/save operation fails.");
TRANSLATE_NOOP("FullscreenUI", "Determines whether a prompt will be displayed to confirm shutting down the emulator/game when the hotkey is pressed.");
TRANSLATE_NOOP("FullscreenUI", "Automatically saves the emulator state when powering down or exiting. You can then resume directly from where you left off next time.");
TRANSLATE_NOOP("FullscreenUI", "Creates a backup copy of a save state if it already exists when the save is created. The backup copy has a .backup suffix");
TRANSLATE_NOOP("FullscreenUI", "Changes which gamepad button glyph set is used in Big Picture UI and input binding displays.");
TRANSLATE_NOOP("FullscreenUI", "Integration");
TRANSLATE_NOOP("FullscreenUI", "Shows the game you are currently playing as part of your profile on Discord.");
TRANSLATE_NOOP("FullscreenUI", "Shows the game you are currently playing as part of your profile in Discord.");
TRANSLATE_NOOP("FullscreenUI", "Game Display");
TRANSLATE_NOOP("FullscreenUI", "Automatically switches to fullscreen mode when a game is started.");
TRANSLATE_NOOP("FullscreenUI", "Switches between full screen and windowed when the window is double-clicked.");
TRANSLATE_NOOP("FullscreenUI", "Allows switching in and out of fullscreen mode by double-clicking the game window.");
TRANSLATE_NOOP("FullscreenUI", "Hides the mouse pointer/cursor when the emulator is in fullscreen mode.");
TRANSLATE_NOOP("FullscreenUI", "Automatically starts Big Picture Mode instead of the regular Qt interface when PCSX2 launches.");
TRANSLATE_NOOP("FullscreenUI", "Operations");
@@ -5941,7 +5944,7 @@ TRANSLATE_NOOP("FullscreenUI", "BIOS Configuration");
TRANSLATE_NOOP("FullscreenUI", "Changes the BIOS image used to start future sessions.");
TRANSLATE_NOOP("FullscreenUI", "BIOS Selection");
TRANSLATE_NOOP("FullscreenUI", "Fast Boot Options");
TRANSLATE_NOOP("FullscreenUI", "Skips the intro screen, and bypasses region checks.");
TRANSLATE_NOOP("FullscreenUI", "Patches the BIOS to skip the console's boot animation.");
TRANSLATE_NOOP("FullscreenUI", "Removes emulation speed throttle until the game starts to reduce startup time.");
TRANSLATE_NOOP("FullscreenUI", "Speed Control");
TRANSLATE_NOOP("FullscreenUI", "Sets the speed when running without fast forwarding.");
@@ -5953,11 +5956,11 @@ TRANSLATE_NOOP("FullscreenUI", "Makes the emulated Emotion Engine skip cycles. H
TRANSLATE_NOOP("FullscreenUI", "Generally a speedup on CPUs with 4 or more cores. Safe for most games, but a few are incompatible and may hang.");
TRANSLATE_NOOP("FullscreenUI", "Pins emulation threads to CPU cores to potentially improve performance/frame time variance.");
TRANSLATE_NOOP("FullscreenUI", "Enables loading cheats from pnach files.");
TRANSLATE_NOOP("FullscreenUI", "Enables access to files from the host: namespace in the virtual machine.");
TRANSLATE_NOOP("FullscreenUI", "Fast disc access, less loading times. Not recommended.");
TRANSLATE_NOOP("FullscreenUI", "Allows games and homebrew to access files / folders directly on the host computer.");
TRANSLATE_NOOP("FullscreenUI", "Fast disc access, shorter loading times. Check HDLoader compatibility lists for games that are known to have issues with this.");
TRANSLATE_NOOP("FullscreenUI", "Loads the disc image into RAM before starting the virtual machine.");
TRANSLATE_NOOP("FullscreenUI", "Real-Time Clock");
TRANSLATE_NOOP("FullscreenUI", "Uses a fixed date/time for the virtual PS2 instead of the host clock. Applied on boot only.");
TRANSLATE_NOOP("FullscreenUI", "Manually set a real-time clock to use for the virtual PlayStation 2 instead of using your OS' system clock.");
TRANSLATE_NOOP("FullscreenUI", "Calendar year for the virtual PS2 RTC.");
TRANSLATE_NOOP("FullscreenUI", "Month of the year (1-12).");
TRANSLATE_NOOP("FullscreenUI", "Day of the month (1-31).");
@@ -5967,6 +5970,7 @@ TRANSLATE_NOOP("FullscreenUI", "Second of the minute (0-59).");
TRANSLATE_NOOP("FullscreenUI", "Frame Pacing / Latency Control");
TRANSLATE_NOOP("FullscreenUI", "Sets the number of frames which can be queued.");
TRANSLATE_NOOP("FullscreenUI", "Synchronize EE and GS threads after each frame. Lowest input latency, but increases system requirements.");
TRANSLATE_NOOP("FullscreenUI", "Displays the newest frame immediately at the beginning of the frame raster time, instead of at the end. Can reduce perceived input lag, but may cause problems with some games, such as Soulcalibur II and Baldur's Gate Dark Alliance II. ");
TRANSLATE_NOOP("FullscreenUI", "Synchronizes frame presentation with host refresh.");
TRANSLATE_NOOP("FullscreenUI", "Speeds up emulation so that the guest refresh rate matches the host.");
TRANSLATE_NOOP("FullscreenUI", "Disables PCSX2's internal frame timing, and uses host vsync instead.");
@@ -5975,7 +5979,7 @@ TRANSLATE_NOOP("FullscreenUI", "Selects the API used to render the emulated GS."
TRANSLATE_NOOP("FullscreenUI", "Display");
TRANSLATE_NOOP("FullscreenUI", "Selects the aspect ratio to display the game content at.");
TRANSLATE_NOOP("FullscreenUI", "Selects the aspect ratio for display when a FMV is detected as playing.");
TRANSLATE_NOOP("FullscreenUI", "Selects the algorithm used to convert the PS2's interlaced output to progressive for display.");
TRANSLATE_NOOP("FullscreenUI", "Determines the deinterlacing method to be used on the interlaced screen of the emulated console.\nAutomatic should be able to correctly deinterlace most games, but if you see visibly shaky graphics, try one of the other options.");
TRANSLATE_NOOP("FullscreenUI", "Disables interlacing offset which may reduce blurring in some situations.");
TRANSLATE_NOOP("FullscreenUI", "Determines the resolution at which screenshots will be saved.");
TRANSLATE_NOOP("FullscreenUI", "Selects the format which will be used to save screenshots.");
@@ -5984,33 +5988,34 @@ TRANSLATE_NOOP("FullscreenUI", "%d%%");
TRANSLATE_NOOP("FullscreenUI", "Increases or decreases the virtual picture size vertically.");
TRANSLATE_NOOP("FullscreenUI", "Crops the image, while respecting aspect ratio.");
TRANSLATE_NOOP("FullscreenUI", "%dpx");
TRANSLATE_NOOP("FullscreenUI", "Enables loading widescreen patches from pnach files.");
TRANSLATE_NOOP("FullscreenUI", "Enables loading no-interlacing patches from pnach files.");
TRANSLATE_NOOP("FullscreenUI", "Automatically loads and applies widescreen patches on game start. Can cause issues.");
TRANSLATE_NOOP("FullscreenUI", "Automatically loads and applies no-interlacing patches on game start. Can cause issues.");
TRANSLATE_NOOP("FullscreenUI", "Smooths out the image when upscaling the console to the screen.");
TRANSLATE_NOOP("FullscreenUI", "Adds padding to the display area to ensure that the ratio between pixels on the host to pixels in the console is an integer number. May result in a sharper image in some 2D games.");
TRANSLATE_NOOP("FullscreenUI", "Enables PCRTC Offsets which position the screen as the game requests.");
TRANSLATE_NOOP("FullscreenUI", "Enables the option to show the overscan area on games which draw more than the safe area of the screen.");
TRANSLATE_NOOP("FullscreenUI", "Enables internal Anti-Blur hacks. Less accurate to PS2 rendering but will make a lot of games look less blurry.");
TRANSLATE_NOOP("FullscreenUI", "Enables internal Anti-Blur hacks. Less accurate than PS2 rendering but will make a lot of games look less blurry.");
TRANSLATE_NOOP("FullscreenUI", "Rendering");
TRANSLATE_NOOP("FullscreenUI", "Multiplies the render resolution by the specified factor (upscaling).");
TRANSLATE_NOOP("FullscreenUI", "Selects where bilinear filtering is utilized when rendering textures.");
TRANSLATE_NOOP("FullscreenUI", "Selects where trilinear filtering is utilized when rendering textures.");
TRANSLATE_NOOP("FullscreenUI", "Selects where anisotropic filtering is utilized when rendering textures.");
TRANSLATE_NOOP("FullscreenUI", "Reduces texture aliasing at extreme viewing angles.");
TRANSLATE_NOOP("FullscreenUI", "Selects the type of dithering applies when the game requests it.");
TRANSLATE_NOOP("FullscreenUI", "Determines the level of accuracy when emulating blend modes not supported by the host graphics API.");
TRANSLATE_NOOP("FullscreenUI", "Enables emulation of the GS's edge anti-aliasing (AA1).");
TRANSLATE_NOOP("FullscreenUI", "Enables AA1 (PS2 antialiasing), which some games require to render correctly. This may result in a heavy performance penalty.");
TRANSLATE_NOOP("FullscreenUI", "Enables accurate alpha testing, which some games require to render correctly. This may require more draw calls and result in a speed penalty.");
TRANSLATE_NOOP("FullscreenUI", "Enables emulation of the GS's texture mipmapping.");
TRANSLATE_NOOP("FullscreenUI", "Enables mipmapping, which some games require to render correctly. Mipmapping uses progressively lower resolution variants of textures at progressively further distances to reduce processing load and avoid visual artifacts.");
TRANSLATE_NOOP("FullscreenUI", "Enables Rasterizer Ordered View (ROV), which allows feedback loops to be executed with fewer draw calls. Can improve performance in feedback heavy games with higher accuracy settings.");
TRANSLATE_NOOP("FullscreenUI", "Number of threads to use in addition to the main GS thread for rasterization.");
TRANSLATE_NOOP("FullscreenUI", "Force a primitive flush when a framebuffer is also an input texture.");
TRANSLATE_NOOP("FullscreenUI", "Hardware Fixes");
TRANSLATE_NOOP("FullscreenUI", "Disables automatic hardware fixes, allowing you to set fixes manually.");
TRANSLATE_NOOP("FullscreenUI", "Uses software renderer to draw texture decompression-like sprites.");
TRANSLATE_NOOP("FullscreenUI", "The maximum target memory width that will allow the CPU Sprite Renderer to activate on.");
TRANSLATE_NOOP("FullscreenUI", "Determines filter level for CPU sprite render.");
TRANSLATE_NOOP("FullscreenUI", "Uses software renderer to draw texture CLUT points/sprites.");
TRANSLATE_NOOP("FullscreenUI", "Try to detect when a game is drawing its own color palette and then renders it on the GPU with special handling.");
TRANSLATE_NOOP("FullscreenUI", "Object range to skip drawing.");
TRANSLATE_NOOP("FullscreenUI", "Tries to detect when a game is drawing its own color palette and then renders it in software, instead of on the GPU.");
TRANSLATE_NOOP("FullscreenUI", "Tries to detect when a game is drawing its own color palette and then renders it on the GPU with special handling.");
TRANSLATE_NOOP("FullscreenUI", "Completely skips drawing surfaces from the starting index up to the ending index.");
TRANSLATE_NOOP("FullscreenUI", "Forces a primitive flush when a framebuffer is also an input texture. Fixes some processing effects such as the shadows in the Jak series and radiosity in GTA:SA.");
TRANSLATE_NOOP("FullscreenUI", "Convert 4-bit and 8-bit framebuffer on the CPU instead of the GPU.");
TRANSLATE_NOOP("FullscreenUI", "Disable the support of depth buffers in the texture cache.");
TRANSLATE_NOOP("FullscreenUI", "This option disables multiple safe features.");
@@ -6020,19 +6025,21 @@ TRANSLATE_NOOP("FullscreenUI", "Removes texture cache entries when there is any
TRANSLATE_NOOP("FullscreenUI", "Allows the texture cache to reuse as an input texture the inner portion of a previous framebuffer.");
TRANSLATE_NOOP("FullscreenUI", "Flushes all targets in the texture cache back to local memory when shutting down.");
TRANSLATE_NOOP("FullscreenUI", "Attempts to reduce the texture size when games do not set it themselves (e.g. Snowblind games).");
TRANSLATE_NOOP("FullscreenUI", "Rewrite Large ST");
TRANSLATE_NOOP("FullscreenUI", "Rewrite large ST coordinates and clamp the values.");
TRANSLATE_NOOP("FullscreenUI", "When enabled GPU converts colormap-textures, otherwise the CPU will. It is a trade-off between GPU and CPU.");
TRANSLATE_NOOP("FullscreenUI", "Attempts to reduce draw calls in games which do heavy context switching for blending purposes.");
TRANSLATE_NOOP("FullscreenUI", "Truncate 32-bit depth values to 24 bits. Helps games struggling with Z-fighting.");
TRANSLATE_NOOP("FullscreenUI", "Upscaling Fixes");
TRANSLATE_NOOP("FullscreenUI", "Adjusts vertices relative to upscaling.");
TRANSLATE_NOOP("FullscreenUI", "Attempt to do rescaling at native resolution.");
TRANSLATE_NOOP("FullscreenUI", "Might fix some misaligned fog, bloom, or blend effect.");
TRANSLATE_NOOP("FullscreenUI", "Emulates native PS2 coordinate scaling behavior when upscaling to reduce misalignment artifacts and seams in games that draw custom 2D elements.");
TRANSLATE_NOOP("FullscreenUI", "Adjusts sprite coordinates.");
TRANSLATE_NOOP("FullscreenUI", "Can smooth out textures due to be bilinear filtered when upscaling. E.g. Brave sun glare.");
TRANSLATE_NOOP("FullscreenUI", "Adjusts target texture offsets.");
TRANSLATE_NOOP("FullscreenUI", "Fixes issues with upscaling (vertical lines) in some games.");
TRANSLATE_NOOP("FullscreenUI", "Replaces multiple post-processing sprites with a larger single sprite.");
TRANSLATE_NOOP("FullscreenUI", "Replaces post-processing multiple paving sprites by a single fat sprite. It reduces various upscaling lines.");
TRANSLATE_NOOP("FullscreenUI", "Lowers the GS precision to avoid gaps between pixels when upscaling. Fixes the text on Wild Arms games.");
TRANSLATE_NOOP("FullscreenUI", "Can fix some broken effects which rely on pixel perfect precision.");
TRANSLATE_NOOP("FullscreenUI", "Forces palette texture draws to render at native resolution.");
TRANSLATE_NOOP("FullscreenUI", "Texture Replacement");
TRANSLATE_NOOP("FullscreenUI", "Loads replacement textures where available and user-provided.");
TRANSLATE_NOOP("FullscreenUI", "Loads replacement textures on a worker thread, reducing microstutter when replacements are enabled.");
@@ -6043,7 +6050,7 @@ TRANSLATE_NOOP("FullscreenUI", "Dumps replaceable textures to disk. Will reduce
TRANSLATE_NOOP("FullscreenUI", "Includes mipmaps when dumping textures.");
TRANSLATE_NOOP("FullscreenUI", "Allows texture dumping when FMVs are active. You should not enable this.");
TRANSLATE_NOOP("FullscreenUI", "Post-Processing");
TRANSLATE_NOOP("FullscreenUI", "Enables FXAA post-processing shader.");
TRANSLATE_NOOP("FullscreenUI", "Applies the FXAA anti-aliasing algorithm to improve the visual quality of games.");
TRANSLATE_NOOP("FullscreenUI", "Enables FidelityFX Contrast Adaptive Sharpening.");
TRANSLATE_NOOP("FullscreenUI", "Determines the intensity the sharpening effect in CAS post-processing.");
TRANSLATE_NOOP("FullscreenUI", "Filters");
@@ -6052,7 +6059,7 @@ TRANSLATE_NOOP("FullscreenUI", "Adjusts brightness. 50 is normal.");
TRANSLATE_NOOP("FullscreenUI", "Adjusts contrast. 50 is normal.");
TRANSLATE_NOOP("FullscreenUI", "Adjusts gamma. 50 is normal.");
TRANSLATE_NOOP("FullscreenUI", "Adjusts saturation. 50 is normal.");
TRANSLATE_NOOP("FullscreenUI", "Applies a shader which replicates the visual effects of different styles of television set.");
TRANSLATE_NOOP("FullscreenUI", "Applies a shader which replicates the visual effects of different styles of television sets.");
TRANSLATE_NOOP("FullscreenUI", "Advanced");
TRANSLATE_NOOP("FullscreenUI", "Skips displaying frames that don't change in 25/30fps games. Can improve speed, but increase input lag/make frame pacing worse.");
TRANSLATE_NOOP("FullscreenUI", "Forces the use of FIFO over Mailbox presentation, i.e. double buffering instead of triple buffering. Usually results in worse frame pacing.");
@@ -6061,7 +6068,7 @@ TRANSLATE_NOOP("FullscreenUI", "Displays additional, very high upscaling multipl
TRANSLATE_NOOP("FullscreenUI", "Changes synchronization behavior for GS downloads.");
TRANSLATE_NOOP("FullscreenUI", "Overrides the driver's heuristics for enabling exclusive fullscreen, or direct flip/scanout.");
TRANSLATE_NOOP("FullscreenUI", "Forces texture barrier functionality to the specified value.");
TRANSLATE_NOOP("FullscreenUI", "Sets the compression algorithm for GS dumps.");
TRANSLATE_NOOP("FullscreenUI", "Change the compression algorithm used when creating a GS dump.");
TRANSLATE_NOOP("FullscreenUI", "Prevents the usage of framebuffer fetch when supported by host GPU.");
TRANSLATE_NOOP("FullscreenUI", "Prevents the loading and saving of shaders/pipelines to disk.");
TRANSLATE_NOOP("FullscreenUI", "Falls back to the CPU for expanding sprites/lines.");
@@ -6072,10 +6079,10 @@ TRANSLATE_NOOP("FullscreenUI", "Uploads full textures to the GPU on use, rather
TRANSLATE_NOOP("FullscreenUI", "Determines what frame rate NTSC games run at.");
TRANSLATE_NOOP("FullscreenUI", "Determines what frame rate PAL games run at.");
TRANSLATE_NOOP("FullscreenUI", "On-Screen Display");
TRANSLATE_NOOP("FullscreenUI", "Determines how large the on-screen messages and monitors are.");
TRANSLATE_NOOP("FullscreenUI", "Determines the distance in pixels from the edges of the screen for OSD elements.");
TRANSLATE_NOOP("FullscreenUI", "Scales the size of the onscreen OSD from 50% to 500%.");
TRANSLATE_NOOP("FullscreenUI", "Sets the distance in pixels from the edges of the screen for OSD elements.");
TRANSLATE_NOOP("FullscreenUI", "Determines where on-screen display messages are positioned.");
TRANSLATE_NOOP("FullscreenUI", "Determines where performance statistics are positioned.");
TRANSLATE_NOOP("FullscreenUI", "Position of a variety of on-screen performance data points as selected by the user.");
TRANSLATE_NOOP("FullscreenUI", "Select OSD Font");
TRANSLATE_NOOP("FullscreenUI", "Use default bundled font");
TRANSLATE_NOOP("FullscreenUI", "Draws OSD text with heavier weight for improved readability.");
@@ -6088,16 +6095,16 @@ TRANSLATE_NOOP("FullscreenUI", "Shows the current system CPU and GPU information
TRANSLATE_NOOP("FullscreenUI", "Shows statistics about the emulated GS such as primitives and draw calls.");
TRANSLATE_NOOP("FullscreenUI", "Shows the host's CPU utilization based on threads.");
TRANSLATE_NOOP("FullscreenUI", "Shows the host's GPU utilization.");
TRANSLATE_NOOP("FullscreenUI", "Shows indicators when fast forwarding, pausing, and other abnormal states are active.");
TRANSLATE_NOOP("FullscreenUI", "Shows icon indicators for emulation states such as Pausing, Turbo, Fast-Forward, and Slow-Motion.");
TRANSLATE_NOOP("FullscreenUI", "Shows debug information about the renderer.");
TRANSLATE_NOOP("FullscreenUI", "Shows the host's GPU pipeline statistics.");
TRANSLATE_NOOP("FullscreenUI", "Shows a visual history of frame times.");
TRANSLATE_NOOP("FullscreenUI", "Shows the current configuration in the bottom-right corner of the display.");
TRANSLATE_NOOP("FullscreenUI", "Shows the amount of currently active patches/cheats on the bottom-right corner of the display.");
TRANSLATE_NOOP("FullscreenUI", "Shows GPU vertex shader and pixels shader invocations.");
TRANSLATE_NOOP("FullscreenUI", "Displays a graph showing the average frametimes.");
TRANSLATE_NOOP("FullscreenUI", "Displays various settings and the current values of those settings in the bottom-right corner of the display.");
TRANSLATE_NOOP("FullscreenUI", "Shows the amount of currently active patches/cheats in the bottom-right corner of the display.");
TRANSLATE_NOOP("FullscreenUI", "Shows the current controller state of the system in the bottom-left corner of the display.");
TRANSLATE_NOOP("FullscreenUI", "Shows the status of the currently active video capture.");
TRANSLATE_NOOP("FullscreenUI", "Shows the status of the currently active input recording.");
TRANSLATE_NOOP("FullscreenUI", "Shows the number of dumped and loaded texture replacements on the OSD.");
TRANSLATE_NOOP("FullscreenUI", "Shows the status of the currently active video capture in the top-right corner of the display.");
TRANSLATE_NOOP("FullscreenUI", "Shows the status of the currently active input recording in the top-right corner of the display.");
TRANSLATE_NOOP("FullscreenUI", "Shows the status of the number of dumped and loaded texture replacements in the top-right corner of the display.");
TRANSLATE_NOOP("FullscreenUI", "Displays warnings when settings are enabled which may break games.");
TRANSLATE_NOOP("FullscreenUI", "Audio Control");
TRANSLATE_NOOP("FullscreenUI", "Controls the volume of the audio played on the host at normal speed.");
@@ -6106,7 +6113,7 @@ TRANSLATE_NOOP("FullscreenUI", "Prevents the emulator from producing any audible
TRANSLATE_NOOP("FullscreenUI", "Backend Settings");
TRANSLATE_NOOP("FullscreenUI", "Determines how audio frames produced by the emulator are submitted to the host.");
TRANSLATE_NOOP("FullscreenUI", "Determines how audio is expanded from stereo to surround for supported games.");
TRANSLATE_NOOP("FullscreenUI", "Changes when SPU samples are generated relative to system emulation.");
TRANSLATE_NOOP("FullscreenUI", "When the emulation isn't running at 100% speed, adjusts the tempo of the audio\nwhich produces much nicer sound during fast-forward/slowdown.");
TRANSLATE_NOOP("FullscreenUI", "Determines the amount of audio buffered before being pulled by the host API.");
TRANSLATE_NOOP("FullscreenUI", "%d ms");
TRANSLATE_NOOP("FullscreenUI", "Determines how much latency there is between the audio being picked up by the host API, and played through speakers.");
@@ -6154,14 +6161,14 @@ TRANSLATE_NOOP("FullscreenUI", "When enabled and logged in, PCSX2 will scan for
TRANSLATE_NOOP("FullscreenUI", "\"Challenge\" mode for achievements, including leaderboard tracking. Disables save state, cheats, and slowdown functions.");
TRANSLATE_NOOP("FullscreenUI", "When enabled, PCSX2 will assume all achievements are locked and not send any unlock notifications to the server.");
TRANSLATE_NOOP("FullscreenUI", "When enabled, each session will behave as if no achievements have been unlocked.");
TRANSLATE_NOOP("FullscreenUI", "When enabled, PCSX2 will list achievements from unofficial sets. These achievements are not tracked by RetroAchievements.");
TRANSLATE_NOOP("FullscreenUI", "When enabled, PCSX2 will list achievements from unofficial sets. Please note that these achievements are not tracked by RetroAchievements, so they unlock every time.");
TRANSLATE_NOOP("FullscreenUI", "Notifications");
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages on events such as achievement unlocks and leaderboard submissions.");
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages on events such as achievement unlocks and game completion.");
TRANSLATE_NOOP("FullscreenUI", "Displays popup messages when starting, submitting, or failing a leaderboard challenge.");
TRANSLATE_NOOP("FullscreenUI", "Plays sound effects for events such as achievement unlocks and leaderboard submissions.");
TRANSLATE_NOOP("FullscreenUI", "Determines where achievement/leaderboard notification popups are positioned on the screen.");
TRANSLATE_NOOP("FullscreenUI", "Determines the display duration for achievement unlock popups.");
TRANSLATE_NOOP("FullscreenUI", "Determines the display duration for leaderboard popups.");
TRANSLATE_NOOP("FullscreenUI", "Determines the display duration for leaderboard notification popups.");
TRANSLATE_NOOP("FullscreenUI", "Overlay Settings");
TRANSLATE_NOOP("FullscreenUI", "Shows icons in the screen when a challenge/primed achievement is active.");
TRANSLATE_NOOP("FullscreenUI", "Shows icons in the screen when leaderboard tracking is active.");
@@ -6205,14 +6212,15 @@ TRANSLATE_NOOP("FullscreenUI", "Determines how the results of floating-point ope
TRANSLATE_NOOP("FullscreenUI", "Determines how the results of floating-point division is rounded. Some games need specific settings.");
TRANSLATE_NOOP("FullscreenUI", "Determines how out-of-range floating point numbers are handled. Some games need specific settings.");
TRANSLATE_NOOP("FullscreenUI", "Performs just-in-time binary translation of 64-bit MIPS-IV machine code to native code.");
TRANSLATE_NOOP("FullscreenUI", "Enables simulation of the EE's cache. Slow.");
TRANSLATE_NOOP("FullscreenUI", "Enables emulation of the EE's hardware cache. Interpreter only, provided for diagnostics.");
TRANSLATE_NOOP("FullscreenUI", "Huge speedup for some games, with almost no compatibility side effects.");
TRANSLATE_NOOP("FullscreenUI", "Moderate speedup for some games, with no known side effects.");
TRANSLATE_NOOP("FullscreenUI", "Uses backpatching to avoid register flushing on every memory access.");
TRANSLATE_NOOP("FullscreenUI", "Pauses the virtual machine when a TLB miss occurs, instead of ignoring it and continuing.");
TRANSLATE_NOOP("FullscreenUI", "Exposes additional memory to the virtual machine, expanding the EE and IOP memory to 128MB and 8MB respectively.");
TRANSLATE_NOOP("FullscreenUI", "Vector Units");
TRANSLATE_NOOP("FullscreenUI", "New Vector Unit recompiler with much improved compatibility. Recommended.");
TRANSLATE_NOOP("FullscreenUI", "Performs just-in-time binary translation of Vector Unit 0 (VU0) microprograms to native code.");
TRANSLATE_NOOP("FullscreenUI", "Performs just-in-time binary translation of Vector Unit 1 (VU1) microprograms to native code.");
TRANSLATE_NOOP("FullscreenUI", "Good speedup and high compatibility, may cause graphical errors.");
TRANSLATE_NOOP("FullscreenUI", "Runs VU1 instantly. Provides a modest speed improvement in most games. Safe for most games, but a few games may exhibit graphical errors.");
TRANSLATE_NOOP("FullscreenUI", "I/O Processor");
@@ -6587,6 +6595,7 @@ TRANSLATE_NOOP("FullscreenUI", "Minute");
TRANSLATE_NOOP("FullscreenUI", "Second");
TRANSLATE_NOOP("FullscreenUI", "Maximum Frame Latency");
TRANSLATE_NOOP("FullscreenUI", "Optimal Frame Pacing");
TRANSLATE_NOOP("FullscreenUI", "Advanced Frame Display");
TRANSLATE_NOOP("FullscreenUI", "Vertical Sync (VSync)");
TRANSLATE_NOOP("FullscreenUI", "Sync to Host Refresh Rate");
TRANSLATE_NOOP("FullscreenUI", "Use Host VSync Timing");
+4
View File
@@ -928,6 +928,8 @@ __ri void ImGuiManager::DrawSettingsOverlay(float scale, float margin, float spa
APPEND("MTVU ");
if (EmuConfig.GS.VsyncEnable)
APPEND("VSYNC ");
if (EmuConfig.GS.AdvancedFrameDisplay)
APPEND("AFD ");
APPEND("EER={} EEC={} VUR={} VUC={} VQS={} ", static_cast<unsigned>(EmuConfig.Cpu.FPUFPCR.GetRoundMode()),
EmuConfig.Cpu.Recompiler.GetEEClampMode(), static_cast<unsigned>(EmuConfig.Cpu.VU0FPCR.GetRoundMode()),
@@ -1021,6 +1023,8 @@ __ri void ImGuiManager::DrawSettingsOverlay(float scale, float margin, float spa
APPEND("ETR ");
if (GSConfig.UserHacks_DrawBuffering)
APPEND("DRWB ");
if (GSConfig.UserHacks_RewriteLargeSTCoords)
APPEND("RWST ");
if (GSConfig.HWSpinGPUForReadbacks)
APPEND("RBSG ");
if (GSConfig.HWSpinCPUForReadbacks)
+4 -3
View File
@@ -151,18 +151,19 @@ void psxDma6(u32 madr, u32 bcr, u32 chcr)
void psxDma8(u32 madr, u32 bcr, u32 chcr)
{
const int size = (bcr >> 16) * (bcr & 0xFFFF) * 8;
const int size = (bcr >> 16) * (bcr & 0xFFFF);
switch (chcr & 0x01000201)
{
case 0x01000201: //cpu to dev9 transfer
PSXDMA_LOG("*** DMA 8 - DEV9 mem2dev9 *** %lx addr = %lx size = %lx", chcr, madr, bcr);
DEV9writeDMA8Mem((u32*)iopPhysMem(madr), size);
DEV9writeDMA8Mem((u32*)iopPhysMem(madr), size * 4);
break;
case 0x01000200: //dev9 to cpu transfer
PSXDMA_LOG("*** DMA 8 - DEV9 dev9mem *** %lx addr = %lx size = %lx", chcr, madr, bcr);
DEV9readDMA8Mem((u32*)iopPhysMem(madr), size);
DEV9readDMA8Mem((u32*)iopPhysMem(madr), size * 4);
psxCpu->Clear(madr, size);
break;
default:
+7
View File
@@ -1048,6 +1048,13 @@ void MTGS::SetRunIdle(bool enabled)
s_run_idle_flag.store(enabled, std::memory_order_release);
}
void MTGS::ResetStats()
{
RunOnGSThread([]() {
GSResetStats();
});
}
// Used in MTVU mode... MTVU will later complete a real packet
void Gif_AddGSPacketMTVU(GS_Packet& gsPack, GIF_PATH path)
{
+1
View File
@@ -78,6 +78,7 @@ namespace MTGS
bool SaveMemorySnapshot(u32 window_width, u32 window_height, bool apply_aspect, bool crop_borders,
u32* width, u32* height, std::vector<u32>* pixels);
void SetRunIdle(bool enabled);
void ResetStats();
// Size of the ringbuffer as a power of 2 -- size is a multiple of simd128s.
// (actual size is 1<<m_RingBufferSizeFactor simd vectors [128-bit values])
+13
View File
@@ -723,6 +723,7 @@ Pcsx2Config::GSOptions::GSOptions()
DisableFramebufferFetch = false;
DisableVertexShaderExpand = false;
SkipDuplicateFrames = true;
AdvancedFrameDisplay = false;
OsdMessagesPos = OsdOverlayPos::TopLeft;
OsdPerformancePos = OsdOverlayPos::TopRight;
OsdShowSpeed = false;
@@ -875,6 +876,10 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
OpEqu(SaveFrameStart) &&
OpEqu(SaveFrameCount) &&
OpEqu(SaveFrameBy) &&
OpEqu(DumpReplayLoopCount) &&
OpEqu(DumpReplayFrameStart) &&
OpEqu(DumpReplayFrameEnd) &&
OpEqu(SavedMetricsCaptureSeconds) &&
OpEqu(ExclusiveFullscreenControl) &&
OpEqu(ScreenshotSize) &&
@@ -961,6 +966,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
SettingsWrapBitBool(DisableFramebufferFetch);
SettingsWrapBitBool(DisableVertexShaderExpand);
SettingsWrapBitBool(SkipDuplicateFrames);
SettingsWrapBitBool(AdvancedFrameDisplay);
SettingsWrapBitBool(OsdShowSpeed);
SettingsWrapBitBool(OsdShowFPS);
SettingsWrapBitBool(OsdShowVPS);
@@ -1005,6 +1011,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
SettingsWrapIntEnumEx(UserHacks_Limit24BitDepth, "UserHacks_Limit24BitDepth");
SettingsWrapBitBoolEx(UserHacks_EstimateTextureRegion, "UserHacks_EstimateTextureRegion");
SettingsWrapBitBoolEx(UserHacks_DrawBuffering, "UserHacks_DrawBuffering");
SettingsWrapBitBoolEx(UserHacks_RewriteLargeSTCoords, "UserHacks_RewriteLargeSTCoords");
SettingsWrapBitBoolEx(FXAA, "fxaa");
SettingsWrapBitBool(ShadeBoost);
SettingsWrapBitBoolEx(DumpGSData, "DumpGSData");
@@ -1018,6 +1025,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
SettingsWrapBitBoolEx(SaveDrawStats, "SaveDrawStats");
SettingsWrapBitBoolEx(SaveFrameStats, "SaveFrameStats");
SettingsWrapBitBoolEx(SaveHWConfig, "SaveHWConfig");
SettingsWrapBitBoolEx(DumpReplayUseFrameRange, "DumpReplayUseFrameRange");
SettingsWrapBitBool(DumpReplaceableTextures);
SettingsWrapBitBool(DumpReplaceableMipmaps);
SettingsWrapBitBool(DumpTexturesWithFMVActive);
@@ -1092,6 +1100,10 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
SettingsWrapBitfieldEx(SaveFrameStart, "SaveFrameStart");
SettingsWrapBitfieldEx(SaveFrameCount, "SaveFrameCount");
SettingsWrapBitfieldEx(SaveFrameBy, "SaveFrameBy");
SettingsWrapBitfieldEx(DumpReplayLoopCount, "DumpReplayLoopCount");
SettingsWrapBitfieldEx(DumpReplayFrameStart, "DumpReplayFrameStart");
SettingsWrapBitfieldEx(DumpReplayFrameEnd, "DumpReplayFrameEnd");
SettingsWrapBitfieldEx(SavedMetricsCaptureSeconds, "SavedMetricsCaptureSeconds");
SettingsWrapEntryEx(CaptureContainer, "CaptureContainer");
SettingsWrapEntryEx(VideoCaptureCodec, "VideoCaptureCodec");
@@ -1145,6 +1157,7 @@ void Pcsx2Config::GSOptions::MaskUserHacks()
UserHacks_Limit24BitDepth = GSLimit24BitDepth::Disabled;
UserHacks_EstimateTextureRegion = false;
UserHacks_DrawBuffering = false;
UserHacks_RewriteLargeSTCoords = false;
UserHacks_TCOffsetX = 0;
UserHacks_TCOffsetY = 0;
UserHacks_CPUSpriteRenderBW = 0;
+111 -5
View File
@@ -3,6 +3,7 @@
#include <chrono>
#include <vector>
#include <cmath>
#include "common/Timer.h"
#include "common/Threading.h"
@@ -75,6 +76,10 @@ static double s_average_gpu_ps_invocations = 0.0;
static u64 s_accumulated_gpu_vs_invocations = 0;
static u64 s_accumulated_gpu_ps_invocations = 0;
static PerformanceMetrics::SavedMetrics s_saved_metrics;
static PerformanceMetrics::SavedMetrics s_saved_metrics_std;
static float s_saved_metrics_remaining_seconds = 0.0f;
void PerformanceMetrics::Clear()
{
Reset();
@@ -85,6 +90,8 @@ void PerformanceMetrics::Clear()
s_average_frame_time = 0.0f;
s_maximum_frame_time = 0.0f;
s_internal_fps_method = PerformanceMetrics::InternalFPSMethod::None;
s_average_gpu_vs_invocations = 0.0;
s_average_gpu_ps_invocations = 0.0;
s_cpu_thread_usage = 0.0f;
s_cpu_thread_time = 0.0f;
@@ -102,6 +109,10 @@ void PerformanceMetrics::Clear()
s_frame_time_history.fill(0.0f);
s_frame_time_history_pos = 0;
s_saved_metrics = {};
s_saved_metrics_std = {};
s_saved_metrics_remaining_seconds = 0.0f;
}
void PerformanceMetrics::Reset()
@@ -113,6 +124,8 @@ void PerformanceMetrics::Reset()
s_minimum_frame_time_accumulator = 0.0f;
s_average_frame_time_accumulator = 0.0f;
s_maximum_frame_time_accumulator = 0.0f;
s_accumulated_gpu_vs_invocations = 0;
s_accumulated_gpu_ps_invocations = 0;
s_accumulated_gpu_time = 0.0f;
s_presents_since_last_update = 0;
@@ -130,6 +143,17 @@ void PerformanceMetrics::Reset()
stat.last_cpu_time = stat.handle.GetCPUTime();
}
static double GetCPUTimeToPCTFactor(u64 ticks_delta)
{
return 100.0 * static_cast<double>(GetTickFrequency()) /
(static_cast<double>(ticks_delta) * static_cast<double>(Threading::GetThreadTicksPerSecond()));
}
static double GetCPUTimeToMSFactor(u64 frames)
{
return 1000.0 / static_cast<double>(Threading::GetThreadTicksPerSecond()) / static_cast<double>(frames);
}
void PerformanceMetrics::Update(bool gs_register_write, bool fb_blit, bool is_skipping_present)
{
if (!is_skipping_present)
@@ -191,11 +215,8 @@ void PerformanceMetrics::Update(bool gs_register_write, bool fb_blit, bool is_sk
const u64 ticks_delta = ticks - s_last_ticks;
s_last_ticks = ticks;
const double pct_divider =
100.0 * (1.0 / ((static_cast<double>(ticks_delta) * static_cast<double>(Threading::GetThreadTicksPerSecond())) /
static_cast<double>(GetTickFrequency())));
const double time_divider = 1000.0 * (1.0 / static_cast<double>(Threading::GetThreadTicksPerSecond())) *
(1.0 / static_cast<double>(s_frames_since_last_update));
const double pct_divider = GetCPUTimeToPCTFactor(ticks_delta);
const double time_divider = GetCPUTimeToMSFactor(s_frames_since_last_update);
const u64 cpu_time = s_cpu_thread_handle.GetCPUTime();
const u64 gs_time = MTGS::GetThreadHandle().GetCPUTime();
@@ -229,6 +250,32 @@ void PerformanceMetrics::Update(bool gs_register_write, bool fb_blit, bool is_sk
thread.time = static_cast<double>(delta) * time_divider;
}
if (s_saved_metrics_remaining_seconds > 0.0f)
{
auto UpdateSavedMetrics = [&](PerformanceMetrics::SavedMetrics& metrics, bool square) {
auto Transform = [square](float f) { return square ? f * f : f; };
metrics.num_samples += 1.0f;
metrics.frames += static_cast<float>(s_frames_since_last_update);
metrics.time += time;
metrics.fps += Transform(s_fps);
metrics.internal_fps += Transform(s_internal_fps);
metrics.cpu_thread_usage += Transform(s_cpu_thread_usage);
metrics.cpu_thread_time += Transform(s_cpu_thread_time);
metrics.gs_thread_usage += Transform(s_gs_thread_usage);
metrics.gs_thread_time += Transform(s_gs_thread_time);
metrics.gpu_time += Transform(s_average_gpu_time);;
metrics.gpu_usage += Transform(s_gpu_usage);
};
UpdateSavedMetrics(s_saved_metrics, false);
UpdateSavedMetrics(s_saved_metrics_std, true);
s_saved_metrics_remaining_seconds -= std::min(s_saved_metrics_remaining_seconds, time);
std::atomic_thread_fence(std::memory_order_release); // results might be read on another thread
}
s_frames_since_last_update = 0;
s_unskipped_frames_since_last_update = 0;
s_presents_since_last_update = 0;
@@ -391,3 +438,62 @@ u32 PerformanceMetrics::GetFrameTimeHistoryPos()
{
return s_frame_time_history_pos;
}
void PerformanceMetrics::StartSavingMetrics(u32 seconds)
{
s_saved_metrics_remaining_seconds = static_cast<float>(seconds);
s_saved_metrics = {};
s_saved_metrics_std = {};
}
bool PerformanceMetrics::IsSavingMetrics()
{
return s_saved_metrics_remaining_seconds > 0.0f;
}
void PerformanceMetrics::DumpSavedMetrics()
{
s_saved_metrics_remaining_seconds = 0.0f;
SavedMetrics metrics = std::exchange(s_saved_metrics, SavedMetrics{});
SavedMetrics metrics_std = std::exchange(s_saved_metrics_std, SavedMetrics{});
const float num_samples = metrics.num_samples;
if (num_samples > 0.0f)
{
const auto Square = [](float f) { return f * f; };
const auto Average = [num_samples](float f) { return f / num_samples; };
metrics.fps = Average(metrics.fps);
metrics.internal_fps = Average(metrics.internal_fps);
metrics.cpu_thread_usage = Average(metrics.cpu_thread_usage);
metrics.cpu_thread_time = Average(metrics.cpu_thread_time);
metrics.gs_thread_usage = Average(metrics.gs_thread_usage);
metrics.gs_thread_time = Average(metrics.gs_thread_time);
metrics.gpu_time = Average(metrics.gpu_time);
metrics.gpu_usage = Average(metrics.gpu_usage);
metrics_std.fps = std::sqrt((Average(metrics_std.fps) - Square(metrics.fps)));
metrics_std.internal_fps = std::sqrt((Average(metrics_std.internal_fps) - Square(metrics.internal_fps)));
metrics_std.cpu_thread_usage = std::sqrt((Average(metrics_std.cpu_thread_usage) - Square(metrics.cpu_thread_usage)));
metrics_std.cpu_thread_time = std::sqrt((Average(metrics_std.cpu_thread_time) - Square(metrics.cpu_thread_time)));
metrics_std.gs_thread_usage = std::sqrt((Average(metrics_std.gs_thread_usage) - Square(metrics.gs_thread_usage)));
metrics_std.gs_thread_time = std::sqrt((Average(metrics_std.gs_thread_time) - Square(metrics.gs_thread_time)));
metrics_std.gpu_time = std::sqrt((Average(metrics_std.gpu_time) - Square(metrics.gpu_time)));
metrics_std.gpu_usage = std::sqrt((Average(metrics_std.gpu_usage) - Square(metrics.gpu_usage)));
Console.WriteLnFmt("@HWSTAT@ Frames: {} ({} samples)", metrics.frames, metrics.num_samples);
Console.WriteLnFmt("@HWSTAT@ Time: {:.3f} sec", metrics.time);
Console.WriteLnFmt("@HWSTAT@ FPS: {:.3f} ± {:.3f} ({:.3f} ± {:.3f} internal)", metrics.fps, metrics_std.fps, metrics.internal_fps, metrics_std.internal_fps);
Console.WriteLnFmt("@HWSTAT@ Minimum Frame Time: {:.3f} ms ({:.3f} FPS)", GetMinimumFrameTime(), 1000.0f / GetMinimumFrameTime());
Console.WriteLnFmt("@HWSTAT@ Average Frame Time: {:.3f} ms ({:.3f} FPS)", GetAverageFrameTime(), 1000.0f / GetAverageFrameTime());
Console.WriteLnFmt("@HWSTAT@ Maximum Frame Time: {:.3f} ms ({:.3f} FPS)", GetMaximumFrameTime(), 1000.0f / GetMaximumFrameTime());
Console.WriteLnFmt("@HWSTAT@ Average CPU Thread Usage: {:.3f} ± {:.3f} %", metrics.cpu_thread_usage, metrics_std.cpu_thread_usage);
Console.WriteLnFmt("@HWSTAT@ Average GS Thread Usage: {:.3f} ± {:.3f} %", metrics.gs_thread_usage, metrics_std.gs_thread_usage);
Console.WriteLnFmt("@HWSTAT@ Average GPU Usage: {:.3f} ± {:.3f} %", metrics.gpu_usage, metrics_std.gpu_usage);
Console.WriteLnFmt("@HWSTAT@ Average CPU Thread Time: {:.3f} ± {:.3f} ms", metrics.cpu_thread_time, metrics_std.cpu_thread_time);
Console.WriteLnFmt("@HWSTAT@ Average GS Thread Time: {:.3f} ± {:.3f} ms", metrics.gs_thread_time, metrics_std.gs_thread_time);
Console.WriteLnFmt("@HWSTAT@ Average GPU Time: {:.3f} ± {:.3f} ms", metrics.gpu_time, metrics_std.gpu_time);
}
}

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