mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-09-11 15:22:58 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37a8be7b42 | ||
|
|
4cdda8d99b | ||
|
|
a5fc5aefc9 | ||
|
|
e6a88bccff | ||
|
|
0caaa2cb49 | ||
|
|
4a4cbb875e | ||
|
|
6a0d3011ab | ||
|
|
d3cc62f37e | ||
|
|
32c19d94fa | ||
|
|
1810140d1d | ||
|
|
7676b1f73e | ||
|
|
bbc57ec622 | ||
|
|
98697735f1 | ||
|
|
4102a0bd2c | ||
|
|
cb3c60557e | ||
|
|
c62d29e6a1 | ||
|
|
ac24959c4a | ||
|
|
236f67a82f | ||
|
|
4e9c5dcc88 | ||
|
|
450a39a37c | ||
|
|
ca0145e6aa | ||
|
|
20c51dd80e | ||
|
|
aaf03c18b6 | ||
|
|
77bec5e0f5 | ||
|
|
f0cd834ed2 | ||
|
|
77cfac7dbe | ||
|
|
ca5942151a | ||
|
|
0be8947a33 | ||
|
|
33127ad0df | ||
|
|
c475c752bf | ||
|
|
bd9b6daaad | ||
|
|
9120e6fb6a | ||
|
|
65dc286e9b | ||
|
|
4545e24f7d | ||
|
|
deb6edc076 | ||
|
|
969c3b54b8 | ||
|
|
d9dcb0abd7 | ||
|
|
d53b89a848 | ||
|
|
3d9fea596d | ||
|
|
e1a2faf5c2 |
+1
-1
@@ -2,7 +2,7 @@
|
||||
* text=auto
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.sln text eol=crlf
|
||||
*.slnx text eol=crlf
|
||||
*.props text eol=crlf
|
||||
*.vcxproj text eol=crlf
|
||||
*.vcxproj.filters text eol=crlf
|
||||
|
||||
@@ -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
@@ -6,8 +6,8 @@
|
||||
- any-glob-to-any-file:
|
||||
- '.github/*'
|
||||
- '.github/**/*'
|
||||
- '*.sln'
|
||||
- '**/*.sln'
|
||||
- '*.slnx'
|
||||
- '**/*.slnx'
|
||||
- '*.vcxproj*'
|
||||
- '**/*.vcxproj*'
|
||||
- 'cmake/*'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
@@ -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/"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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*
|
||||
|
||||
Vendored
+244
-3
@@ -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:
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -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
|
||||
)
|
||||
|
||||
|
||||
Vendored
+5
-2
@@ -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.
|
||||
|
||||
Vendored
+119
-63
@@ -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
@@ -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);
|
||||
|
||||
Vendored
+346
-96
File diff suppressed because it is too large
Load Diff
Vendored
+163
-61
@@ -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();
|
||||
}
|
||||
|
||||
Vendored
+153
-117
@@ -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
@@ -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;
|
||||
|
||||
Vendored
+415
-175
File diff suppressed because it is too large
Load Diff
Vendored
+138
-91
@@ -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
File diff suppressed because it is too large
Load Diff
+485
@@ -0,0 +1,485 @@
|
||||
<Solution>
|
||||
<Configurations>
|
||||
<BuildType Name="Debug" />
|
||||
<BuildType Name="Debug AVX2" />
|
||||
<BuildType Name="Debug Clang" />
|
||||
<BuildType Name="Debug Clang AVX2" />
|
||||
<BuildType Name="Devel" />
|
||||
<BuildType Name="Devel AVX2" />
|
||||
<BuildType Name="Devel Clang" />
|
||||
<BuildType Name="Devel Clang AVX2" />
|
||||
<BuildType Name="Release" />
|
||||
<BuildType Name="Release AVX2" />
|
||||
<BuildType Name="Release Clang" />
|
||||
<BuildType Name="Release Clang AVX2" />
|
||||
<Platform Name="ARM64" />
|
||||
<Platform Name="x64" />
|
||||
</Configurations>
|
||||
<Folder Name="/3rdparty/">
|
||||
<Project Path="3rdparty/ccc/ccc.vcxproj" Id="2589f8ce-ea77-4b73-911e-64074569795b">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/cpuinfo/cpuinfo.vcxproj" Id="7e183337-a7e9-460c-9d3d-568bc9f9bcc1">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/cubeb/cubeb.vcxproj" Id="bf74c473-dc04-44b3-92e8-4145f4e77342">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/d3d12memalloc/d3d12memalloc.vcxproj" Id="d45cec7a-3171-40dd-975d-e1544cf16139">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/demangler/demangler.vcxproj" Id="d31a6dd1-99ca-41d8-a230-1fae913c8989">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/discord-rpc/discord-rpc.vcxproj" Id="e960dfdf-1bd3-4c29-b251-d1a0919c9b09">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/fmt/fmt.vcxproj" Id="449ad25e-424a-4714-babc-68706cdcc33b">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/freesurround/freesurround.vcxproj" Id="1dd0b31f-37f0-4a36-a521-74133aca4737">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/glad/glad.vcxproj" Id="c0293b32-5acf-40f0-aa6c-e6da6f3bf33a">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/imgui/imgui.vcxproj" Id="88fb34ec-845e-4f21-a552-f1573b9ed167">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/libchdr/libchdr.vcxproj" Id="a0d2b3ad-1f72-4ee3-8b5c-f2c358da35f0">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/libzip/libzip.vcxproj" Id="20b2e9fe-f020-42a0-b324-956f5b06ea68">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/lzma/lzma.vcxproj" Id="a4323327-3f2b-4271-83d9-7f9a3c66b6b2">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/rainterface/rainterface.vcxproj" Id="95dd0a0c-d14d-4cff-a593-820ef26efcc8">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/rcheevos/rcheevos.vcxproj" Id="6d5b5ad9-1525-459b-939f-a5e1082af6b3">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/simpleini/simpleini.vcxproj" Id="1ec8b3c0-8fb3-46de-a2e0-a9121203f266">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/soundtouch/SoundTouch.vcxproj" Id="e9b51944-7e6d-4bcd-83f2-7bbd5a46182d">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/vixl/vixl.vcxproj" Id="8906836e-f06e-46e8-b11a-74e5e8c7b8fb">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="*|x64" Project="false" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="3rdparty/zydis/zydis.vcxproj" Id="67d0160c-0fe4-44b9-ac2e-82bbcf4104df">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="*|ARM64" Project="false" />
|
||||
</Project>
|
||||
</Folder>
|
||||
<Project Path="common/common.vcxproj" Id="4639972e-424e-4e13-8b07-ca403c481346">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="pcsx2-gsrunner/pcsx2-gsrunner.vcxproj" Id="bb98bf81-a132-444a-bb81-96d510f433a8">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Project="false" />
|
||||
</Project>
|
||||
<Project Path="pcsx2-qt/pcsx2-qt.vcxproj" Id="2a016f21-87ae-4154-8271-1f57e91408e9">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="pcsx2/pcsx2.vcxproj" Id="6c7986c4-3e4d-4dcc-b3c6-6bb12b238995">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="updater/updater.vcxproj" Id="90bbdc04-cc44-4006-b893-06a4fea8ed47">
|
||||
<BuildType Solution="Debug AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug Clang AVX2|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Debug|ARM64" Project="Debug Clang" />
|
||||
<BuildType Solution="Devel AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel Clang AVX2|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Devel|ARM64" Project="Devel Clang" />
|
||||
<BuildType Solution="Release AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release Clang AVX2|ARM64" Project="Release Clang" />
|
||||
<BuildType Solution="Release|ARM64" Project="Release Clang" />
|
||||
<Build Solution="Debug AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
<Build Solution="Devel AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Devel|ARM64" Project="false" />
|
||||
<Build Solution="Release AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release Clang AVX2|ARM64" Project="false" />
|
||||
<Build Solution="Release|ARM64" Project="false" />
|
||||
</Project>
|
||||
</Solution>
|
||||
@@ -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"
|
||||
@@ -35387,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: "ふれーすヴぇるぐ [たいけんばん]"
|
||||
@@ -54809,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"
|
||||
@@ -60602,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"
|
||||
@@ -62340,7 +62342,6 @@ SLPS-25800:
|
||||
gsHWFixes:
|
||||
halfPixelOffset: 4 # Aligns DoF effects.
|
||||
nativeScaling: 2 # Fixes post effects.
|
||||
getSkipCount: "GSC_UltramanFightingEvolution"
|
||||
SLPS-25801:
|
||||
name: "今日からマ王! 眞マ国の休日"
|
||||
name-sort: "きょうからまおう しんまこくのきゅうじつ"
|
||||
@@ -63501,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!]"
|
||||
@@ -64503,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"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -62,7 +62,6 @@ namespace GSRunner
|
||||
static bool InitializeConfig();
|
||||
static void SettingsOverride();
|
||||
static bool ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& params);
|
||||
static void DumpStats();
|
||||
|
||||
static bool CreatePlatformWindow();
|
||||
static void DestroyPlatformWindow();
|
||||
@@ -80,43 +79,11 @@ static std::string s_output_prefix;
|
||||
static s32 s_loop_count = 1;
|
||||
static std::optional<bool> s_use_window;
|
||||
static bool s_no_console = false;
|
||||
static bool s_perf_enable = false;
|
||||
|
||||
// Owned by the GS thread.
|
||||
static u32 s_dump_frame_number = 0;
|
||||
static u32 s_loop_number = s_loop_count;
|
||||
static double s_last_internal_draws = 0;
|
||||
static double s_last_draws = 0;
|
||||
static double s_last_render_passes = 0;
|
||||
static double s_last_barriers = 0;
|
||||
static double s_last_copies = 0;
|
||||
static double s_last_uploads = 0;
|
||||
static double s_last_readbacks = 0;
|
||||
static double s_last_depth_copies_rov = 0;
|
||||
static double s_last_draws_rov = 0;
|
||||
static double s_last_barriers_rov = 0;
|
||||
static u64 s_total_internal_draws = 0;
|
||||
static u64 s_total_draws = 0;
|
||||
static u64 s_total_render_passes = 0;
|
||||
static u64 s_total_barriers = 0;
|
||||
static u64 s_total_copies = 0;
|
||||
static u64 s_total_uploads = 0;
|
||||
static u64 s_total_readbacks = 0;
|
||||
static u64 s_total_copies_rov = 0;
|
||||
static u64 s_total_draws_rov = 0;
|
||||
static u64 s_total_barriers_rov = 0;
|
||||
static u32 s_total_frames = 0;
|
||||
static u32 s_total_drawn_frames = 0;
|
||||
|
||||
static bool s_perf_enable = false;
|
||||
static float s_perf_updates = 0.0f;
|
||||
static float s_perf_sum_fps = 0.0f;
|
||||
static float s_perf_sum_internal_fps = 0.0f;
|
||||
static float s_perf_sum_cpu_thread_usage = 0.0f;
|
||||
static float s_perf_sum_cpu_thread_time = 0.0f;
|
||||
static float s_perf_sum_gs_thread_usage = 0.0f;
|
||||
static float s_perf_sum_gs_thread_time = 0.0f;
|
||||
static float s_perf_sum_gpu_time = 0.0f;
|
||||
static float s_perf_sum_gpu_usage = 0.0f;
|
||||
|
||||
bool GSRunner::InitializeConfig()
|
||||
{
|
||||
@@ -278,39 +245,6 @@ void Host::BeginPresentFrame()
|
||||
std::string dump_path(fmt::format("{}_frame{:05}.png", s_output_prefix, s_dump_frame_number));
|
||||
GSQueueSnapshot(dump_path);
|
||||
}
|
||||
|
||||
if (GSIsHardwareRenderer())
|
||||
{
|
||||
const u32 last_draws = s_total_internal_draws;
|
||||
const u32 last_uploads = s_total_uploads;
|
||||
|
||||
static constexpr auto update_stat = [](GSPerfMon::counter_t counter, u64& dst, double& last) {
|
||||
// perfmon resets every 30 frames to zero
|
||||
const double val = g_perfmon.GetCounter(counter);
|
||||
dst += static_cast<u64>((val < last) ? val : (val - last));
|
||||
last = val;
|
||||
};
|
||||
|
||||
update_stat(GSPerfMon::Draw, s_total_internal_draws, s_last_internal_draws);
|
||||
update_stat(GSPerfMon::DrawCalls, s_total_draws, s_last_draws);
|
||||
update_stat(GSPerfMon::RenderPasses, s_total_render_passes, s_last_render_passes);
|
||||
update_stat(GSPerfMon::Barriers, s_total_barriers, s_last_barriers);
|
||||
update_stat(GSPerfMon::TextureCopies, s_total_copies, s_last_copies);
|
||||
update_stat(GSPerfMon::TextureUploads, s_total_uploads, s_last_uploads);
|
||||
update_stat(GSPerfMon::Readbacks, s_total_readbacks, s_last_readbacks);
|
||||
update_stat(GSPerfMon::TextureCopiesROV, s_total_copies_rov, s_last_depth_copies_rov);
|
||||
update_stat(GSPerfMon::DrawCallsROV, s_total_draws_rov, s_last_draws_rov);
|
||||
update_stat(GSPerfMon::BarriersROV, s_total_barriers_rov, s_last_barriers_rov);
|
||||
|
||||
const bool idle_frame = s_total_frames && (last_draws == s_total_internal_draws && last_uploads == s_total_uploads);
|
||||
|
||||
if (!idle_frame)
|
||||
s_total_drawn_frames++;
|
||||
|
||||
s_total_frames++;
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
void Host::RequestResizeHostDisplay(s32 width, s32 height)
|
||||
@@ -344,18 +278,6 @@ void Host::OnGameChanged(const std::string& title, const std::string& elf_overri
|
||||
|
||||
void Host::OnPerformanceMetricsUpdated()
|
||||
{
|
||||
if (s_perf_enable)
|
||||
{
|
||||
s_perf_updates += 1.0f;
|
||||
s_perf_sum_fps += PerformanceMetrics::GetFPS();
|
||||
s_perf_sum_internal_fps += PerformanceMetrics::GetInternalFPS();
|
||||
s_perf_sum_cpu_thread_usage += PerformanceMetrics::GetCPUThreadUsage();
|
||||
s_perf_sum_cpu_thread_time += PerformanceMetrics::GetCPUThreadAverageTime();
|
||||
s_perf_sum_gs_thread_usage += PerformanceMetrics::GetGSThreadUsage();
|
||||
s_perf_sum_gs_thread_time += PerformanceMetrics::GetGSThreadAverageTime();
|
||||
s_perf_sum_gpu_time += PerformanceMetrics::GetGPUAverageTime();
|
||||
s_perf_sum_gpu_usage += PerformanceMetrics::GetGPUUsage();
|
||||
}
|
||||
}
|
||||
|
||||
void Host::OnSaveStateLoading(const std::string_view filename)
|
||||
@@ -655,6 +577,7 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
{
|
||||
s_loop_count = StringUtil::FromChars<s32>(argv[++i]).value_or(0);
|
||||
Console.WriteLn("Looping dump playback %d times.", s_loop_count);
|
||||
s_settings_interface.SetIntValue("EmuCore/GS", "DumpReplayLoopCount", s_loop_count);
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG_PARAM("-renderer"))
|
||||
@@ -907,34 +830,6 @@ void GSRunner::SettingsOverride()
|
||||
}
|
||||
}
|
||||
|
||||
void GSRunner::DumpStats()
|
||||
{
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
Console.WriteLn(fmt::format("======= HW STATISTICS FOR {} ({}) FRAMES ========", s_total_frames, s_total_drawn_frames));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Draw Calls: {} (avg {})", s_total_draws, static_cast<u64>(std::ceil(s_total_draws / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Render Passes: {} (avg {})", s_total_render_passes, static_cast<u64>(std::ceil(s_total_render_passes / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Barriers: {} (avg {})", s_total_barriers, static_cast<u64>(std::ceil(s_total_barriers / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Copies: {} (avg {})", s_total_copies, static_cast<u64>(std::ceil(s_total_copies / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Uploads: {} (avg {})", s_total_uploads, static_cast<u64>(std::ceil(s_total_uploads / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Readbacks: {} (avg {})", s_total_readbacks, static_cast<u64>(std::ceil(s_total_readbacks / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Copies (ROV): {} (avg {})", s_total_copies_rov, static_cast<u64>(std::ceil(s_total_copies_rov / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Draws Calls (ROV): {} (avg {})", s_total_draws_rov, static_cast<u64>(std::ceil(s_total_draws_rov / static_cast<double>(s_total_drawn_frames)))));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Barriers (ROV): {} (avg {})", s_total_barriers_rov, static_cast<u64>(std::ceil(s_total_barriers_rov / static_cast<double>(s_total_drawn_frames)))));
|
||||
if (s_perf_enable)
|
||||
{
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Minimum Frame Time: {:.3f} ms ({:.3f} FPS)", PerformanceMetrics::GetMinimumFrameTime(), 1000.0f / PerformanceMetrics::GetMinimumFrameTime()));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Average Frame Time: {:.3f} ms ({:.3f} FPS)", PerformanceMetrics::GetAverageFrameTime(), 1000.0f / PerformanceMetrics::GetAverageFrameTime()));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Maximum Frame Time: {:.3f} ms ({:.3f} FPS)", PerformanceMetrics::GetMaximumFrameTime(), 1000.0f / PerformanceMetrics::GetMaximumFrameTime()));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ CPU Thread Usage: {:.3f} %", s_perf_sum_cpu_thread_usage / s_perf_updates));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ GS Thread Usage: {:.3f} %", s_perf_sum_gs_thread_usage / s_perf_updates));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ GPU Usage: {:.3f} %", s_perf_sum_gpu_usage / s_perf_updates));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Average CPU Thread Time: {:.3f} ms", s_perf_sum_cpu_thread_time / s_perf_updates));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Average GS Thread Time: {:.3f} ms", s_perf_sum_gs_thread_time / s_perf_updates));
|
||||
Console.WriteLn(fmt::format("@HWSTAT@ Average GPU Time: {:.3f} ms", s_perf_sum_gpu_time / s_perf_updates));
|
||||
}
|
||||
Console.WriteLn("============================================");
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// We can't handle unicode in filenames if we don't use wmain on Win32.
|
||||
#define main real_main
|
||||
@@ -948,12 +843,11 @@ static void CPUThreadMain(VMBootParameters* params, std::atomic<int>* ret)
|
||||
{
|
||||
// apply new settings (e.g. pick up renderer change)
|
||||
VMManager::ApplySettings();
|
||||
GSDumpReplayer::SetIsDumpRunner(true);
|
||||
GSDumpReplayer::SetIsDumpRunner(true, s_perf_enable);
|
||||
|
||||
if (VMManager::Initialize(*params) == VMBootResult::StartupSuccess)
|
||||
{
|
||||
// run until end
|
||||
GSDumpReplayer::SetLoopCount(s_loop_count);
|
||||
VMManager::SetState(VMState::Running);
|
||||
if (s_perf_enable)
|
||||
{
|
||||
@@ -963,7 +857,6 @@ static void CPUThreadMain(VMBootParameters* params, std::atomic<int>* ret)
|
||||
while (VMManager::GetState() == VMState::Running)
|
||||
VMManager::Execute();
|
||||
VMManager::Shutdown(false);
|
||||
GSRunner::DumpStats();
|
||||
ret->store(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<widget class="QGroupBox" name="groupBoxDrawDumping">
|
||||
<property name="title">
|
||||
<string>Draw Dumping</string>
|
||||
</property>
|
||||
@@ -240,6 +240,118 @@
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxDumpReplay">
|
||||
<property name="title">
|
||||
<string>Dump Replay Options</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayoutDumpReplay">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayoutDumpReplay">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="replayUseFrameRange">
|
||||
<property name="text">
|
||||
<string>Use Frame Range</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelDumpReplay1">
|
||||
<property name="text">
|
||||
<string>Replay Frame Start:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>replayFrameStart</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="replayFrameStart">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelDumpReplay2">
|
||||
<property name="text">
|
||||
<string>Replay Frame End:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>replayFrameEnd</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="replayFrameEnd">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelDumpReplay3">
|
||||
<property name="text">
|
||||
<string>Replay Loop Count:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>replayLoopCount</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="replayLoopCount">
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBoxPerfMetrics">
|
||||
<property name="title">
|
||||
<string>Performance Metrics Options</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayoutPerfMetrics">
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelPerfMetrics1">
|
||||
<property name="text">
|
||||
<string>Saved Metrics Capture Time:</string>
|
||||
</property>
|
||||
<property name="buddy">
|
||||
<cstring>savedMetricsCaptureSeconds</cstring>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="savedMetricsCaptureSeconds">
|
||||
<property name="suffix">
|
||||
<string> seconds</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>99999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -159,6 +159,16 @@ DebugSettingsWidget::DebugSettingsWidget(SettingsWindow* settings_dialog, QWidge
|
||||
tr("Destination directory for dumps generated by the hardware renderer."));
|
||||
dialog()->registerWidgetHelp(m_gs.swDumpDirectory, tr("Software Dump Directory"), tr("Default"),
|
||||
tr("Destination directory for dumps generated by the software renderer."));
|
||||
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.replayUseFrameRange, "EmuCore/GS", "DumpReplayUseFrameRange", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.replayFrameStart, "EmuCore/GS", "DumpReplayFrameStart", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.replayFrameEnd, "EmuCore/GS", "DumpReplayFrameEnd", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.replayLoopCount, "EmuCore/GS", "DumpReplayLoopCount", 0);
|
||||
|
||||
connect(m_gs.replayUseFrameRange, &QCheckBox::checkStateChanged, this, &DebugSettingsWidget::onDumpReplayUseFrameRangeChanged);
|
||||
onDumpReplayUseFrameRangeChanged();
|
||||
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.savedMetricsCaptureSeconds, "EmuCore/GS", "SavedMetricsCaptureSeconds", 10);
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -268,6 +278,13 @@ void DebugSettingsWidget::onDrawDumpingChanged()
|
||||
m_gs.swDumpOpen->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void DebugSettingsWidget::onDumpReplayUseFrameRangeChanged()
|
||||
{
|
||||
const bool enabled = dialog()->getEffectiveBoolValue("EmuCore/GS", "DumpReplayUseFrameRange", false);
|
||||
m_gs.replayFrameStart->setEnabled(enabled);
|
||||
m_gs.replayFrameEnd->setEnabled(enabled);
|
||||
}
|
||||
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
void DebugSettingsWidget::onLoggingEnableChanged()
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
|
||||
private Q_SLOTS:
|
||||
void onDrawDumpingChanged();
|
||||
void onDumpReplayUseFrameRangeChanged();
|
||||
#ifdef PCSX2_DEVBUILD
|
||||
void onLoggingEnableChanged();
|
||||
#endif
|
||||
|
||||
@@ -33,6 +33,7 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* settings_dialog
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.syncToHostRefreshRate, "EmuCore/GS", "SyncToHostRefreshRate", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.useVSyncForTiming, "EmuCore/GS", "UseVSyncForTiming", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.skipPresentingDuplicateFrames, "EmuCore/GS", "SkipDuplicateFrames", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.advancedFrameDisplay, "EmuCore/GS", "AdvancedFrameDisplay", false);
|
||||
connect(m_ui.optimalFramePacing, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::onOptimalFramePacingChanged);
|
||||
connect(m_ui.vsync, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::updateUseVSyncForTimingEnabled);
|
||||
connect(m_ui.syncToHostRefreshRate, &QCheckBox::checkStateChanged, this, &EmulationSettingsWidget::updateUseVSyncForTimingEnabled);
|
||||
@@ -155,6 +156,11 @@ EmulationSettingsWidget::EmulationSettingsWidget(SettingsWindow* settings_dialog
|
||||
"rendered, it just means the GPU has more time to complete it (this is NOT frame skipping). Can smooth out frame time "
|
||||
"fluctuations when the CPU/GPU are near maximum utilization, but makes frame pacing more inconsistent and can increase "
|
||||
"input lag. Helps when using frame generation on 25/30fps games."));
|
||||
dialog()->registerWidgetHelp(m_ui.advancedFrameDisplay, tr("Advanced Frame Display"), tr("Unchecked"),
|
||||
tr("Displays the newest frame immediately at the beginning of the "
|
||||
"frame raster time, instead of at the end. Can reduce perceived "
|
||||
"input lag, but may cause problems with some games, such as "
|
||||
"Soulcalibur II and Baldur's Gate Dark Alliance II."));
|
||||
dialog()->registerWidgetHelp(m_ui.manuallySetRealTimeClock, tr("Manually Set Real-Time Clock"), tr("Unchecked"),
|
||||
tr("Manually set a real-time clock to use for the virtual PlayStation 2 instead of using your OS' system clock."));
|
||||
dialog()->registerWidgetHelp(m_ui.rtcDateTime, tr("Real-Time Clock"), tr("Current date and time"),
|
||||
|
||||
@@ -263,6 +263,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="advancedFrameDisplay">
|
||||
<property name="text">
|
||||
<string>Advanced Frame Display</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -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
|
||||
|
||||
+2039
-1924
File diff suppressed because it is too large
Load Diff
+7
-4
@@ -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
@@ -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);
|
||||
|
||||
@@ -1263,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")
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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`)
|
||||
|
||||
@@ -204,7 +204,12 @@
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
"drawBuffering": {
|
||||
"drawBuffering": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
},
|
||||
"rewriteLargeSTCoords": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 1
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "GS/GSPerfMon.h"
|
||||
#include "GS/GSUtil.h"
|
||||
#include "GS/MultiISA.h"
|
||||
#include "GS/GSPerfMon.h"
|
||||
#include "Host.h"
|
||||
#include "Input/InputManager.h"
|
||||
#include "MTGS.h"
|
||||
@@ -491,6 +492,23 @@ void GSStopGSDump()
|
||||
g_gs_renderer->StopGSDump();
|
||||
}
|
||||
|
||||
void GSStartSavingMetrics(u32 seconds)
|
||||
{
|
||||
if (g_gs_renderer)
|
||||
g_gs_renderer->StartSavingMetrics(seconds);
|
||||
}
|
||||
|
||||
void GSDumpSavedMetrics()
|
||||
{
|
||||
if (g_gs_renderer)
|
||||
g_gs_renderer->DumpSavedMetrics();
|
||||
}
|
||||
|
||||
bool GSIsSavingMetrics()
|
||||
{
|
||||
return g_gs_renderer && g_gs_renderer->IsSavingMetrics();
|
||||
}
|
||||
|
||||
bool GSBeginCapture(std::string filename)
|
||||
{
|
||||
if (g_gs_renderer)
|
||||
@@ -565,6 +583,11 @@ void GSSetVSyncMode(GSVSyncMode mode, bool allow_present_throttle)
|
||||
g_gs_device->SetVSyncMode(mode, allow_present_throttle);
|
||||
}
|
||||
|
||||
void GSResetStats()
|
||||
{
|
||||
g_perfmon.Reset();
|
||||
}
|
||||
|
||||
bool GSWantsExclusiveFullscreen()
|
||||
{
|
||||
if (!g_gs_device || !g_gs_device->SupportsExclusiveFullscreen())
|
||||
@@ -1226,6 +1249,24 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphic
|
||||
GSStopGSDump();
|
||||
});
|
||||
}},
|
||||
{"GSStartSavingMetricsVariableFrames", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Start Saving Performance Metrics (Press & Hold)"),
|
||||
[](s32 pressed) {
|
||||
MTGS::RunOnGSThread([pressed]() {
|
||||
if (pressed > 0)
|
||||
GSStartSavingMetrics(UINT32_MAX);
|
||||
else
|
||||
GSDumpSavedMetrics();
|
||||
});
|
||||
}},
|
||||
{"GSStartSavingMetricsFixedFrames", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Start Saving Performance Metrics (Capture Timer)"),
|
||||
[](s32 pressed) {
|
||||
MTGS::RunOnGSThread([pressed]() {
|
||||
if (pressed > 0 && !GSIsSavingMetrics())
|
||||
GSStartSavingMetrics(GSConfig.SavedMetricsCaptureSeconds);
|
||||
});
|
||||
}},
|
||||
{"ToggleSoftwareRendering", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||
TRANSLATE_NOOP("Hotkeys", "Toggle Software Rendering"),
|
||||
[](s32 pressed) {
|
||||
|
||||
@@ -76,6 +76,9 @@ std::string GSGetBaseSnapshotFilename();
|
||||
std::string GSGetBaseVideoFilename();
|
||||
void GSQueueSnapshot(const std::string& path, u32 gsdump_frames = 0);
|
||||
void GSStopGSDump();
|
||||
void GSStartSavingMetrics(float time);
|
||||
void GSDumpSavedMetrics();
|
||||
bool GSIsSavingMetrics();
|
||||
bool GSBeginCapture(std::string filename);
|
||||
void GSEndCapture();
|
||||
void GSPresentCurrentFrame();
|
||||
@@ -86,6 +89,7 @@ bool GSHasDisplayWindow();
|
||||
void GSResizeDisplayWindow(u32 width, u32 height, float scale);
|
||||
void GSUpdateDisplayWindow();
|
||||
void GSSetVSyncMode(GSVSyncMode mode, bool allow_present_throttle);
|
||||
void GSResetStats();
|
||||
|
||||
GSRendererType GSGetCurrentRenderer();
|
||||
bool GSIsHardwareRenderer();
|
||||
|
||||
+159
-2
@@ -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()
|
||||
|
||||
+8
-3
@@ -318,9 +318,11 @@ public:
|
||||
static u64 s_last_transfer_draw_n;
|
||||
static u64 s_transfer_n;
|
||||
|
||||
GSPerfMon m_perfmon_frame; // Track stat across a frame.
|
||||
GSPerfMon m_perfmon_draw; // Track stat across a draw.
|
||||
|
||||
GSPerfMon m_perfmon_frame; // Track stats across a frame.
|
||||
GSPerfMon m_perfmon_draw; // Track stats across a draw.
|
||||
|
||||
void IncDraw();
|
||||
|
||||
static constexpr u32 STATE_VERSION = 9;
|
||||
|
||||
#define PRIM_REG_MASK 0x7FF
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -150,7 +150,7 @@ bool GSRenderer::Merge(int field)
|
||||
}
|
||||
}
|
||||
|
||||
s_n++;
|
||||
IncDraw();
|
||||
|
||||
GSVector4 src_gs_read[2] = {};
|
||||
GSVector4 dst[3] = {};
|
||||
@@ -524,6 +524,9 @@ bool GSRenderer::BeginPresentFrame(bool frame_skip)
|
||||
{
|
||||
Host::BeginPresentFrame();
|
||||
|
||||
if (GSDumpReplayer::IsReplayingDump())
|
||||
GSDumpReplayer::UpdateGSStats();
|
||||
|
||||
const GSDevice::PresentResult res = g_gs_device->BeginPresent(frame_skip);
|
||||
if (res == GSDevice::PresentResult::FrameSkipped)
|
||||
{
|
||||
@@ -805,6 +808,10 @@ void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
|
||||
}
|
||||
}
|
||||
|
||||
// metrics
|
||||
if (m_saving_metrics && !PerformanceMetrics::IsSavingMetrics())
|
||||
DumpSavedMetrics();
|
||||
|
||||
// capture
|
||||
if (GSCapture::IsCapturingVideo())
|
||||
{
|
||||
@@ -953,6 +960,29 @@ void GSRenderer::StopGSDump()
|
||||
m_dump_frames = 0;
|
||||
}
|
||||
|
||||
void GSRenderer::StartSavingMetrics(u32 seconds)
|
||||
{
|
||||
m_saving_metrics = true;
|
||||
PerformanceMetrics::StartSavingMetrics(seconds);
|
||||
Host::AddKeyedOSDMessage("GSMetrics",
|
||||
fmt::format(TRANSLATE_FS("GS", "Started saving performance metrics{}"),
|
||||
(0 < seconds && seconds < UINT32_MAX) ? fmt::format(" ({} seconds)", seconds) : ""),
|
||||
Host::OSD_INFO_DURATION);
|
||||
}
|
||||
|
||||
void GSRenderer::DumpSavedMetrics()
|
||||
{
|
||||
m_saving_metrics = false;
|
||||
PerformanceMetrics::DumpSavedMetrics();
|
||||
Host::AddKeyedOSDMessage("GSMetrics", fmt::format(TRANSLATE_FS("GS", "Logging saved performance metrics")),
|
||||
Host::OSD_INFO_DURATION);
|
||||
}
|
||||
|
||||
bool GSRenderer::IsSavingMetrics()
|
||||
{
|
||||
return m_saving_metrics;
|
||||
}
|
||||
|
||||
void GSRenderer::PresentCurrentFrame()
|
||||
{
|
||||
if (BeginPresentFrame(false))
|
||||
|
||||
@@ -19,6 +19,7 @@ private:
|
||||
std::string m_snapshot;
|
||||
u32 m_dump_frames = 0;
|
||||
u32 m_skipped_duplicate_frames = 0;
|
||||
bool m_saving_metrics = false;
|
||||
|
||||
// Tracking draw counters for idle frame detection.
|
||||
u64 m_last_draw_n = 0;
|
||||
@@ -56,6 +57,9 @@ public:
|
||||
|
||||
void QueueSnapshot(const std::string& path, const u32 gsdump_frames);
|
||||
void StopGSDump();
|
||||
void StartSavingMetrics(u32 seconds);
|
||||
void DumpSavedMetrics();
|
||||
bool IsSavingMetrics();
|
||||
void PresentCurrentFrame();
|
||||
bool BeginCapture(std::string filename, const GSVector2i& size = GSVector2i(0, 0));
|
||||
void EndCapture();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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])
|
||||
@@ -2381,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();
|
||||
@@ -2415,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];
|
||||
|
||||
|
||||
@@ -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()));
|
||||
|
||||
@@ -191,7 +191,6 @@ public:
|
||||
void UploadIndices(D3D12StreamBuffer& buffer, const void* index, size_t count);
|
||||
|
||||
private:
|
||||
// For pipeline statistics
|
||||
enum class QueryState
|
||||
{
|
||||
None,
|
||||
@@ -209,7 +208,7 @@ private:
|
||||
std::vector<std::pair<D3D12DescriptorHeapManager&, u32>> pending_descriptors;
|
||||
u64 ready_fence_value = 0;
|
||||
bool init_command_list_used = false;
|
||||
bool has_timestamp_query = false;
|
||||
QueryState timestamp_query_state = QueryState::None;
|
||||
QueryState pipeline_statistics_query = QueryState::None;
|
||||
};
|
||||
|
||||
@@ -524,6 +523,9 @@ public:
|
||||
void EndPresent() override;
|
||||
|
||||
bool SetGPUTimingEnabled(bool enabled) override;
|
||||
void StartGPUTiming();
|
||||
void EndGPUTiming();
|
||||
void ReadGPUTiming();
|
||||
float GetAndResetAccumulatedGPUTime() override;
|
||||
|
||||
bool SetGPUPipelineStatisticsEnabled(bool enabled) override;
|
||||
|
||||
@@ -607,20 +607,6 @@ bool GSHwHack::GSC_TalesOfLegendia(GSRendererHW& r, int& skip)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_UltramanFightingEvolution(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
{
|
||||
if (!s_nativeres && RTME && RFBP == 0x2a00 && RFPSM == PSMZ24 && RTBP0 == 0x1c00 && RTPSM == PSMZ24)
|
||||
{
|
||||
// Don't enable hack on native res if crc is below aggressive.
|
||||
skip = 5; // blur
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GSHwHack::GSC_TalesofSymphonia(GSRendererHW& r, int& skip)
|
||||
{
|
||||
if (skip == 0)
|
||||
@@ -1468,9 +1454,6 @@ const GSHwHack::Entry<GSRendererHW::GSC_Ptr> GSHwHack::s_get_skip_count_function
|
||||
|
||||
// Depth Issue
|
||||
CRC_F(GSC_BurnoutGames),
|
||||
|
||||
// Upscaling hacks
|
||||
CRC_F(GSC_UltramanFightingEvolution),
|
||||
};
|
||||
|
||||
const GSHwHack::Entry<GSRendererHW::OI_Ptr> GSHwHack::s_before_draw_functions[] = {
|
||||
|
||||
@@ -18,7 +18,6 @@ public:
|
||||
static bool GSC_BlackAndBurnoutSky(GSRendererHW& r, int& skip);
|
||||
static bool GSC_MidnightClub3(GSRendererHW& r, int& skip);
|
||||
static bool GSC_TalesOfLegendia(GSRendererHW& r, int& skip);
|
||||
static bool GSC_UltramanFightingEvolution(GSRendererHW& r, int& skip);
|
||||
static bool GSC_TalesofSymphonia(GSRendererHW& r, int& skip);
|
||||
static bool GSC_UrbanReign(GSRendererHW& r, int& skip);
|
||||
static bool GSC_BlueTongueGames(GSRendererHW& r, int& skip);
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -1735,8 +1735,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
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.
|
||||
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 && (bw * 64) != t->m_valid.z && r.w > req_psm.pgs.y)
|
||||
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.
|
||||
@@ -7963,8 +7963,9 @@ 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())));
|
||||
@@ -8028,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)
|
||||
@@ -8057,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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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];
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -1,6 +1,8 @@
|
||||
// SPDX-FileCopyrightText: 2002-2026 PCSX2 Dev Team
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "PerformanceMetrics.h"
|
||||
#include "GS/GSPerfMon.h"
|
||||
#include "GS.h"
|
||||
#include "GS/GSLzma.h"
|
||||
#include "GSDumpReplayer.h"
|
||||
@@ -27,6 +29,7 @@
|
||||
#include "common/Timer.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <cinttypes>
|
||||
|
||||
static void GSDumpReplayerCpuReserve();
|
||||
static void GSDumpReplayerCpuShutdown();
|
||||
@@ -46,6 +49,19 @@ static bool s_needs_state_loaded = false;
|
||||
static u64 s_frame_ticks = 0;
|
||||
static u64 s_next_frame_time = 0;
|
||||
static bool s_is_dump_runner = false;
|
||||
static bool s_dump_perf_metrics = true;
|
||||
|
||||
static bool s_use_frame_range = false;
|
||||
static bool s_init_frame_range = false;
|
||||
static u32 s_frame_start = 0;
|
||||
static u32 s_frame_end = 0;
|
||||
static u32 s_frame_start_packet = 0;
|
||||
static u32 s_frame_end_packet = 0;
|
||||
|
||||
static GSPerfMon s_total_gs_stats;
|
||||
static GSPerfMon s_last_g_perfmon;
|
||||
static u64 s_total_frames = 0;
|
||||
static u64 s_total_drawn_frames = 0;
|
||||
|
||||
R5900cpu GSDumpReplayerCpu = {
|
||||
GSDumpReplayerCpuReserve,
|
||||
@@ -70,9 +86,10 @@ bool GSDumpReplayer::IsRunner()
|
||||
return s_is_dump_runner;
|
||||
}
|
||||
|
||||
void GSDumpReplayer::SetIsDumpRunner(bool is_runner)
|
||||
void GSDumpReplayer::SetIsDumpRunner(bool is_runner, bool dump_perf)
|
||||
{
|
||||
s_is_dump_runner = is_runner;
|
||||
s_dump_perf_metrics = dump_perf;
|
||||
}
|
||||
|
||||
void GSDumpReplayer::SetLoopCount(s32 loop_count)
|
||||
@@ -85,6 +102,13 @@ int GSDumpReplayer::GetLoopCount()
|
||||
return s_dump_loop_count;
|
||||
}
|
||||
|
||||
void GSDumpReplayer::SetFrameRange(bool use, u32 start, u32 end)
|
||||
{
|
||||
s_use_frame_range = use;
|
||||
s_frame_start = start;
|
||||
s_frame_end = end;
|
||||
}
|
||||
|
||||
bool GSDumpReplayer::Initialize(const char* filename, Error* error)
|
||||
{
|
||||
Common::Timer timer;
|
||||
@@ -145,6 +169,8 @@ void GSDumpReplayer::Shutdown()
|
||||
{
|
||||
Console.WriteLn("(GSDumpReplayer) Shutting down.");
|
||||
|
||||
DumpStats();
|
||||
|
||||
Cpu = nullptr;
|
||||
psxCpu = nullptr;
|
||||
CpuVU0 = nullptr;
|
||||
@@ -196,6 +222,13 @@ void GSDumpReplayerCpuReset()
|
||||
s_needs_state_loaded = true;
|
||||
s_current_packet = 0;
|
||||
s_dump_frame_number = 0;
|
||||
s_total_gs_stats.Reset();
|
||||
s_last_g_perfmon.Reset();
|
||||
s_init_frame_range = false;
|
||||
s_frame_start_packet = 0;
|
||||
s_frame_end_packet = 0;
|
||||
s_total_frames = 0;
|
||||
s_total_drawn_frames = 0;
|
||||
}
|
||||
|
||||
static void GSDumpReplayerLoadInitialState()
|
||||
@@ -256,17 +289,10 @@ static void GSDumpReplayerFrameLimit()
|
||||
s_next_frame_time = std::max(now, s_next_frame_time + s_frame_ticks);
|
||||
}
|
||||
|
||||
void GSDumpReplayerCpuStep()
|
||||
void AdvanceNextLoop()
|
||||
{
|
||||
if (s_needs_state_loaded)
|
||||
{
|
||||
GSDumpReplayerLoadInitialState();
|
||||
s_needs_state_loaded = false;
|
||||
}
|
||||
|
||||
const GSDumpFile::GSData& packet = s_dump_file->GetPackets()[s_current_packet];
|
||||
s_current_packet = (s_current_packet + 1) % static_cast<u32>(s_dump_file->GetPackets().size());
|
||||
if (s_current_packet == 0)
|
||||
const bool end_of_dump = (s_current_packet == static_cast<u32>(s_dump_file->GetPackets().size()));
|
||||
if (end_of_dump || (s_init_frame_range && s_current_packet > s_frame_end_packet))
|
||||
{
|
||||
s_dump_frame_number = 0;
|
||||
if (s_dump_loop_count > 0)
|
||||
@@ -277,6 +303,55 @@ void GSDumpReplayerCpuStep()
|
||||
s_dump_running = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateFrameRangePacketsOnVSync()
|
||||
{
|
||||
if (s_use_frame_range && !s_init_frame_range)
|
||||
{
|
||||
if (s_dump_frame_number == s_frame_start)
|
||||
{
|
||||
// +1 since the current packet is the previous frame VSync packet.
|
||||
s_frame_start_packet = s_current_packet + 1;
|
||||
}
|
||||
else if (s_dump_frame_number >= s_frame_end && s_frame_end > s_frame_start)
|
||||
{
|
||||
// Current packet is the VSync packet of the last frame we want to loop over.
|
||||
s_frame_end_packet = s_current_packet;
|
||||
s_init_frame_range = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckFrameRange()
|
||||
{
|
||||
if (s_init_frame_range)
|
||||
{
|
||||
if (s_current_packet > s_frame_end_packet || s_current_packet < s_frame_start_packet)
|
||||
{
|
||||
s_dump_frame_number = s_frame_start;
|
||||
s_current_packet = s_frame_start_packet;
|
||||
}
|
||||
}
|
||||
else if (s_current_packet == static_cast<u32>(s_dump_file->GetPackets().size()))
|
||||
{
|
||||
// This will run if the frame range goes past the end of the dump.
|
||||
s_frame_end_packet = s_current_packet;
|
||||
s_init_frame_range = true;
|
||||
}
|
||||
}
|
||||
|
||||
void GSDumpReplayerCpuStep()
|
||||
{
|
||||
if (s_needs_state_loaded)
|
||||
{
|
||||
GSDumpReplayerLoadInitialState();
|
||||
s_needs_state_loaded = false;
|
||||
PerformanceMetrics::StartSavingMetrics(UINT32_MAX);
|
||||
}
|
||||
|
||||
// Get the next packet.
|
||||
const GSDumpFile::GSData& packet = s_dump_file->GetPackets()[s_current_packet];
|
||||
|
||||
switch (packet.id)
|
||||
{
|
||||
@@ -323,6 +398,7 @@ void GSDumpReplayerCpuStep()
|
||||
if (VMManager::Internal::IsExecutionInterrupted())
|
||||
GSDumpReplayerExitExecution();
|
||||
Host::PumpMessagesOnCPUThread();
|
||||
UpdateFrameRangePacketsOnVSync();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -343,6 +419,18 @@ void GSDumpReplayerCpuStep()
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Increment the packet counter.
|
||||
s_current_packet++;
|
||||
|
||||
// Increment the loop counter.
|
||||
AdvanceNextLoop();
|
||||
|
||||
// Adjust packet index based on the frame range we're replaying.
|
||||
CheckFrameRange();
|
||||
|
||||
// Loop packet index.
|
||||
s_current_packet %= static_cast<u32>(s_dump_file->GetPackets().size());
|
||||
}
|
||||
|
||||
void GSDumpReplayerCpuExecute()
|
||||
@@ -404,3 +492,68 @@ void GSDumpReplayer::RenderUI()
|
||||
|
||||
#undef DRAW_LINE
|
||||
}
|
||||
|
||||
static void UpdateSingleGSStat(GSPerfMon::counter_t counter)
|
||||
{
|
||||
const double curr = g_perfmon.GetCounter(counter);
|
||||
const double last = s_last_g_perfmon.GetCounter(counter);
|
||||
// GSPerfMon resets every 30 frames to zero.
|
||||
s_total_gs_stats.Put(counter, curr < last ? curr : (curr - last));
|
||||
};
|
||||
|
||||
void GSDumpReplayer::UpdateGSStats()
|
||||
{
|
||||
// Called on GS thread.
|
||||
if (GSIsHardwareRenderer())
|
||||
{
|
||||
const double last_draws = s_total_gs_stats.GetCounter(GSPerfMon::Draw);
|
||||
const double last_uploads = s_total_gs_stats.GetCounter(GSPerfMon::TextureUploads);
|
||||
|
||||
UpdateSingleGSStat(GSPerfMon::Draw);
|
||||
UpdateSingleGSStat(GSPerfMon::DrawCalls);
|
||||
UpdateSingleGSStat(GSPerfMon::RenderPasses);
|
||||
UpdateSingleGSStat(GSPerfMon::Barriers);
|
||||
UpdateSingleGSStat(GSPerfMon::TextureCopies);
|
||||
UpdateSingleGSStat(GSPerfMon::TextureUploads);
|
||||
UpdateSingleGSStat(GSPerfMon::Readbacks);
|
||||
UpdateSingleGSStat(GSPerfMon::TextureCopiesROV);
|
||||
UpdateSingleGSStat(GSPerfMon::DrawCallsROV);
|
||||
UpdateSingleGSStat(GSPerfMon::BarriersROV);
|
||||
|
||||
s_last_g_perfmon = g_perfmon;
|
||||
|
||||
const bool idle_frame = s_total_frames > 0 &&
|
||||
s_total_gs_stats.GetCounter(GSPerfMon::Draw) == last_draws &&
|
||||
s_total_gs_stats.GetCounter(GSPerfMon::TextureUploads) == last_uploads;
|
||||
|
||||
if (!idle_frame)
|
||||
s_total_drawn_frames++;
|
||||
|
||||
s_total_frames++;
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_release);
|
||||
}
|
||||
}
|
||||
|
||||
static void DumpStatAndAvg(const char* format, double stat)
|
||||
{
|
||||
Console.WriteLn(format, static_cast<u64>(stat), static_cast<u64>(std::ceil(stat / static_cast<double>(s_total_drawn_frames))));
|
||||
}
|
||||
|
||||
void GSDumpReplayer::DumpStats()
|
||||
{
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
Console.WriteLnFmt("======= HW STATISTICS FOR {} ({}) FRAMES ========", s_total_frames, s_total_drawn_frames);
|
||||
DumpStatAndAvg("@HWSTAT@ Draw Calls: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::DrawCalls));
|
||||
DumpStatAndAvg("@HWSTAT@ Render Passes: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::RenderPasses));
|
||||
DumpStatAndAvg("@HWSTAT@ Barriers: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::Barriers));
|
||||
DumpStatAndAvg("@HWSTAT@ Copies: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::TextureCopies));
|
||||
DumpStatAndAvg("@HWSTAT@ Uploads: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::TextureUploads));
|
||||
DumpStatAndAvg("@HWSTAT@ Readbacks: %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::Readbacks));
|
||||
DumpStatAndAvg("@HWSTAT@ Copies (ROV): %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::TextureCopiesROV));
|
||||
DumpStatAndAvg("@HWSTAT@ Draws Calls (ROV): %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::DrawCallsROV));
|
||||
DumpStatAndAvg("@HWSTAT@ Barriers (ROV): %" PRIu64 " (avg %" PRIu64 ")", s_total_gs_stats.GetCounter(GSPerfMon::BarriersROV));
|
||||
if (s_dump_perf_metrics)
|
||||
PerformanceMetrics::DumpSavedMetrics();
|
||||
Console.WriteLnFmt("============================================");
|
||||
}
|
||||
@@ -16,7 +16,8 @@ namespace GSDumpReplayer
|
||||
void SetLoopCount(s32 loop_count = 0);
|
||||
int GetLoopCount();
|
||||
bool IsRunner();
|
||||
void SetIsDumpRunner(bool is_runner);
|
||||
void SetIsDumpRunner(bool is_runner, bool dump_perf = true);
|
||||
void SetFrameRange(bool use, u32 start, u32 end);
|
||||
|
||||
bool Initialize(const char* filename, Error* error = nullptr);
|
||||
bool ChangeDump(const char* filename);
|
||||
@@ -28,4 +29,8 @@ namespace GSDumpReplayer
|
||||
u32 GetFrameNumber();
|
||||
|
||||
void RenderUI();
|
||||
|
||||
void UpdateGSStats();
|
||||
|
||||
void DumpStats();
|
||||
} // namespace GSDumpReplayer
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -61,6 +61,7 @@ namespace GameDatabaseSchema
|
||||
NativePaletteDraw,
|
||||
EstimateTextureRegion,
|
||||
DrawBuffering,
|
||||
RewriteLargeSTCoords,
|
||||
PCRTCOffsets,
|
||||
PCRTCOverscan,
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -5960,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.");
|
||||
@@ -6014,6 +6025,8 @@ 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.");
|
||||
@@ -6582,6 +6595,7 @@ TRANSLATE_NOOP("FullscreenUI", "Minute");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Second");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Maximum Frame Latency");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Optimal Frame Pacing");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Advanced Frame Display");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Vertical Sync (VSync)");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Sync to Host Refresh Rate");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Use Host VSync Timing");
|
||||
|
||||
@@ -928,6 +928,8 @@ __ri void ImGuiManager::DrawSettingsOverlay(float scale, float margin, float spa
|
||||
APPEND("MTVU ");
|
||||
if (EmuConfig.GS.VsyncEnable)
|
||||
APPEND("VSYNC ");
|
||||
if (EmuConfig.GS.AdvancedFrameDisplay)
|
||||
APPEND("AFD ");
|
||||
|
||||
APPEND("EER={} EEC={} VUR={} VUC={} VQS={} ", static_cast<unsigned>(EmuConfig.Cpu.FPUFPCR.GetRoundMode()),
|
||||
EmuConfig.Cpu.Recompiler.GetEEClampMode(), static_cast<unsigned>(EmuConfig.Cpu.VU0FPCR.GetRoundMode()),
|
||||
@@ -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)
|
||||
|
||||
@@ -1048,6 +1048,13 @@ void MTGS::SetRunIdle(bool enabled)
|
||||
s_run_idle_flag.store(enabled, std::memory_order_release);
|
||||
}
|
||||
|
||||
void MTGS::ResetStats()
|
||||
{
|
||||
RunOnGSThread([]() {
|
||||
GSResetStats();
|
||||
});
|
||||
}
|
||||
|
||||
// Used in MTVU mode... MTVU will later complete a real packet
|
||||
void Gif_AddGSPacketMTVU(GS_Packet& gsPack, GIF_PATH path)
|
||||
{
|
||||
|
||||
@@ -78,6 +78,7 @@ namespace MTGS
|
||||
bool SaveMemorySnapshot(u32 window_width, u32 window_height, bool apply_aspect, bool crop_borders,
|
||||
u32* width, u32* height, std::vector<u32>* pixels);
|
||||
void SetRunIdle(bool enabled);
|
||||
void ResetStats();
|
||||
|
||||
// Size of the ringbuffer as a power of 2 -- size is a multiple of simd128s.
|
||||
// (actual size is 1<<m_RingBufferSizeFactor simd vectors [128-bit values])
|
||||
|
||||
@@ -723,6 +723,7 @@ Pcsx2Config::GSOptions::GSOptions()
|
||||
DisableFramebufferFetch = false;
|
||||
DisableVertexShaderExpand = false;
|
||||
SkipDuplicateFrames = true;
|
||||
AdvancedFrameDisplay = false;
|
||||
OsdMessagesPos = OsdOverlayPos::TopLeft;
|
||||
OsdPerformancePos = OsdOverlayPos::TopRight;
|
||||
OsdShowSpeed = false;
|
||||
@@ -875,6 +876,10 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
|
||||
OpEqu(SaveFrameStart) &&
|
||||
OpEqu(SaveFrameCount) &&
|
||||
OpEqu(SaveFrameBy) &&
|
||||
OpEqu(DumpReplayLoopCount) &&
|
||||
OpEqu(DumpReplayFrameStart) &&
|
||||
OpEqu(DumpReplayFrameEnd) &&
|
||||
OpEqu(SavedMetricsCaptureSeconds) &&
|
||||
|
||||
OpEqu(ExclusiveFullscreenControl) &&
|
||||
OpEqu(ScreenshotSize) &&
|
||||
@@ -961,6 +966,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||
SettingsWrapBitBool(DisableFramebufferFetch);
|
||||
SettingsWrapBitBool(DisableVertexShaderExpand);
|
||||
SettingsWrapBitBool(SkipDuplicateFrames);
|
||||
SettingsWrapBitBool(AdvancedFrameDisplay);
|
||||
SettingsWrapBitBool(OsdShowSpeed);
|
||||
SettingsWrapBitBool(OsdShowFPS);
|
||||
SettingsWrapBitBool(OsdShowVPS);
|
||||
@@ -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;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <chrono>
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
|
||||
#include "common/Timer.h"
|
||||
#include "common/Threading.h"
|
||||
@@ -75,6 +76,10 @@ static double s_average_gpu_ps_invocations = 0.0;
|
||||
static u64 s_accumulated_gpu_vs_invocations = 0;
|
||||
static u64 s_accumulated_gpu_ps_invocations = 0;
|
||||
|
||||
static PerformanceMetrics::SavedMetrics s_saved_metrics;
|
||||
static PerformanceMetrics::SavedMetrics s_saved_metrics_std;
|
||||
static float s_saved_metrics_remaining_seconds = 0.0f;
|
||||
|
||||
void PerformanceMetrics::Clear()
|
||||
{
|
||||
Reset();
|
||||
@@ -85,6 +90,8 @@ void PerformanceMetrics::Clear()
|
||||
s_average_frame_time = 0.0f;
|
||||
s_maximum_frame_time = 0.0f;
|
||||
s_internal_fps_method = PerformanceMetrics::InternalFPSMethod::None;
|
||||
s_average_gpu_vs_invocations = 0.0;
|
||||
s_average_gpu_ps_invocations = 0.0;
|
||||
|
||||
s_cpu_thread_usage = 0.0f;
|
||||
s_cpu_thread_time = 0.0f;
|
||||
@@ -102,6 +109,10 @@ void PerformanceMetrics::Clear()
|
||||
|
||||
s_frame_time_history.fill(0.0f);
|
||||
s_frame_time_history_pos = 0;
|
||||
|
||||
s_saved_metrics = {};
|
||||
s_saved_metrics_std = {};
|
||||
s_saved_metrics_remaining_seconds = 0.0f;
|
||||
}
|
||||
|
||||
void PerformanceMetrics::Reset()
|
||||
@@ -113,6 +124,8 @@ void PerformanceMetrics::Reset()
|
||||
s_minimum_frame_time_accumulator = 0.0f;
|
||||
s_average_frame_time_accumulator = 0.0f;
|
||||
s_maximum_frame_time_accumulator = 0.0f;
|
||||
s_accumulated_gpu_vs_invocations = 0;
|
||||
s_accumulated_gpu_ps_invocations = 0;
|
||||
|
||||
s_accumulated_gpu_time = 0.0f;
|
||||
s_presents_since_last_update = 0;
|
||||
@@ -130,6 +143,17 @@ void PerformanceMetrics::Reset()
|
||||
stat.last_cpu_time = stat.handle.GetCPUTime();
|
||||
}
|
||||
|
||||
static double GetCPUTimeToPCTFactor(u64 ticks_delta)
|
||||
{
|
||||
return 100.0 * static_cast<double>(GetTickFrequency()) /
|
||||
(static_cast<double>(ticks_delta) * static_cast<double>(Threading::GetThreadTicksPerSecond()));
|
||||
}
|
||||
|
||||
static double GetCPUTimeToMSFactor(u64 frames)
|
||||
{
|
||||
return 1000.0 / static_cast<double>(Threading::GetThreadTicksPerSecond()) / static_cast<double>(frames);
|
||||
}
|
||||
|
||||
void PerformanceMetrics::Update(bool gs_register_write, bool fb_blit, bool is_skipping_present)
|
||||
{
|
||||
if (!is_skipping_present)
|
||||
@@ -191,11 +215,8 @@ void PerformanceMetrics::Update(bool gs_register_write, bool fb_blit, bool is_sk
|
||||
const u64 ticks_delta = ticks - s_last_ticks;
|
||||
s_last_ticks = ticks;
|
||||
|
||||
const double pct_divider =
|
||||
100.0 * (1.0 / ((static_cast<double>(ticks_delta) * static_cast<double>(Threading::GetThreadTicksPerSecond())) /
|
||||
static_cast<double>(GetTickFrequency())));
|
||||
const double time_divider = 1000.0 * (1.0 / static_cast<double>(Threading::GetThreadTicksPerSecond())) *
|
||||
(1.0 / static_cast<double>(s_frames_since_last_update));
|
||||
const double pct_divider = GetCPUTimeToPCTFactor(ticks_delta);
|
||||
const double time_divider = GetCPUTimeToMSFactor(s_frames_since_last_update);
|
||||
|
||||
const u64 cpu_time = s_cpu_thread_handle.GetCPUTime();
|
||||
const u64 gs_time = MTGS::GetThreadHandle().GetCPUTime();
|
||||
@@ -229,6 +250,32 @@ void PerformanceMetrics::Update(bool gs_register_write, bool fb_blit, bool is_sk
|
||||
thread.time = static_cast<double>(delta) * time_divider;
|
||||
}
|
||||
|
||||
if (s_saved_metrics_remaining_seconds > 0.0f)
|
||||
{
|
||||
auto UpdateSavedMetrics = [&](PerformanceMetrics::SavedMetrics& metrics, bool square) {
|
||||
auto Transform = [square](float f) { return square ? f * f : f; };
|
||||
|
||||
metrics.num_samples += 1.0f;
|
||||
metrics.frames += static_cast<float>(s_frames_since_last_update);
|
||||
metrics.time += time;
|
||||
metrics.fps += Transform(s_fps);
|
||||
metrics.internal_fps += Transform(s_internal_fps);
|
||||
metrics.cpu_thread_usage += Transform(s_cpu_thread_usage);
|
||||
metrics.cpu_thread_time += Transform(s_cpu_thread_time);
|
||||
metrics.gs_thread_usage += Transform(s_gs_thread_usage);
|
||||
metrics.gs_thread_time += Transform(s_gs_thread_time);
|
||||
metrics.gpu_time += Transform(s_average_gpu_time);;
|
||||
metrics.gpu_usage += Transform(s_gpu_usage);
|
||||
};
|
||||
|
||||
UpdateSavedMetrics(s_saved_metrics, false);
|
||||
UpdateSavedMetrics(s_saved_metrics_std, true);
|
||||
|
||||
s_saved_metrics_remaining_seconds -= std::min(s_saved_metrics_remaining_seconds, time);
|
||||
|
||||
std::atomic_thread_fence(std::memory_order_release); // results might be read on another thread
|
||||
}
|
||||
|
||||
s_frames_since_last_update = 0;
|
||||
s_unskipped_frames_since_last_update = 0;
|
||||
s_presents_since_last_update = 0;
|
||||
@@ -391,3 +438,62 @@ u32 PerformanceMetrics::GetFrameTimeHistoryPos()
|
||||
{
|
||||
return s_frame_time_history_pos;
|
||||
}
|
||||
|
||||
void PerformanceMetrics::StartSavingMetrics(u32 seconds)
|
||||
{
|
||||
s_saved_metrics_remaining_seconds = static_cast<float>(seconds);
|
||||
s_saved_metrics = {};
|
||||
s_saved_metrics_std = {};
|
||||
}
|
||||
|
||||
bool PerformanceMetrics::IsSavingMetrics()
|
||||
{
|
||||
return s_saved_metrics_remaining_seconds > 0.0f;
|
||||
}
|
||||
|
||||
void PerformanceMetrics::DumpSavedMetrics()
|
||||
{
|
||||
s_saved_metrics_remaining_seconds = 0.0f;
|
||||
|
||||
SavedMetrics metrics = std::exchange(s_saved_metrics, SavedMetrics{});
|
||||
SavedMetrics metrics_std = std::exchange(s_saved_metrics_std, SavedMetrics{});
|
||||
|
||||
const float num_samples = metrics.num_samples;
|
||||
|
||||
if (num_samples > 0.0f)
|
||||
{
|
||||
const auto Square = [](float f) { return f * f; };
|
||||
const auto Average = [num_samples](float f) { return f / num_samples; };
|
||||
|
||||
metrics.fps = Average(metrics.fps);
|
||||
metrics.internal_fps = Average(metrics.internal_fps);
|
||||
metrics.cpu_thread_usage = Average(metrics.cpu_thread_usage);
|
||||
metrics.cpu_thread_time = Average(metrics.cpu_thread_time);
|
||||
metrics.gs_thread_usage = Average(metrics.gs_thread_usage);
|
||||
metrics.gs_thread_time = Average(metrics.gs_thread_time);
|
||||
metrics.gpu_time = Average(metrics.gpu_time);
|
||||
metrics.gpu_usage = Average(metrics.gpu_usage);
|
||||
|
||||
metrics_std.fps = std::sqrt((Average(metrics_std.fps) - Square(metrics.fps)));
|
||||
metrics_std.internal_fps = std::sqrt((Average(metrics_std.internal_fps) - Square(metrics.internal_fps)));
|
||||
metrics_std.cpu_thread_usage = std::sqrt((Average(metrics_std.cpu_thread_usage) - Square(metrics.cpu_thread_usage)));
|
||||
metrics_std.cpu_thread_time = std::sqrt((Average(metrics_std.cpu_thread_time) - Square(metrics.cpu_thread_time)));
|
||||
metrics_std.gs_thread_usage = std::sqrt((Average(metrics_std.gs_thread_usage) - Square(metrics.gs_thread_usage)));
|
||||
metrics_std.gs_thread_time = std::sqrt((Average(metrics_std.gs_thread_time) - Square(metrics.gs_thread_time)));
|
||||
metrics_std.gpu_time = std::sqrt((Average(metrics_std.gpu_time) - Square(metrics.gpu_time)));
|
||||
metrics_std.gpu_usage = std::sqrt((Average(metrics_std.gpu_usage) - Square(metrics.gpu_usage)));
|
||||
|
||||
Console.WriteLnFmt("@HWSTAT@ Frames: {} ({} samples)", metrics.frames, metrics.num_samples);
|
||||
Console.WriteLnFmt("@HWSTAT@ Time: {:.3f} sec", metrics.time);
|
||||
Console.WriteLnFmt("@HWSTAT@ FPS: {:.3f} ± {:.3f} ({:.3f} ± {:.3f} internal)", metrics.fps, metrics_std.fps, metrics.internal_fps, metrics_std.internal_fps);
|
||||
Console.WriteLnFmt("@HWSTAT@ Minimum Frame Time: {:.3f} ms ({:.3f} FPS)", GetMinimumFrameTime(), 1000.0f / GetMinimumFrameTime());
|
||||
Console.WriteLnFmt("@HWSTAT@ Average Frame Time: {:.3f} ms ({:.3f} FPS)", GetAverageFrameTime(), 1000.0f / GetAverageFrameTime());
|
||||
Console.WriteLnFmt("@HWSTAT@ Maximum Frame Time: {:.3f} ms ({:.3f} FPS)", GetMaximumFrameTime(), 1000.0f / GetMaximumFrameTime());
|
||||
Console.WriteLnFmt("@HWSTAT@ Average CPU Thread Usage: {:.3f} ± {:.3f} %", metrics.cpu_thread_usage, metrics_std.cpu_thread_usage);
|
||||
Console.WriteLnFmt("@HWSTAT@ Average GS Thread Usage: {:.3f} ± {:.3f} %", metrics.gs_thread_usage, metrics_std.gs_thread_usage);
|
||||
Console.WriteLnFmt("@HWSTAT@ Average GPU Usage: {:.3f} ± {:.3f} %", metrics.gpu_usage, metrics_std.gpu_usage);
|
||||
Console.WriteLnFmt("@HWSTAT@ Average CPU Thread Time: {:.3f} ± {:.3f} ms", metrics.cpu_thread_time, metrics_std.cpu_thread_time);
|
||||
Console.WriteLnFmt("@HWSTAT@ Average GS Thread Time: {:.3f} ± {:.3f} ms", metrics.gs_thread_time, metrics_std.gs_thread_time);
|
||||
Console.WriteLnFmt("@HWSTAT@ Average GPU Time: {:.3f} ± {:.3f} ms", metrics.gpu_time, metrics_std.gpu_time);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,4 +62,23 @@ namespace PerformanceMetrics
|
||||
|
||||
const FrameTimeHistory& GetFrameTimeHistory();
|
||||
u32 GetFrameTimeHistoryPos();
|
||||
|
||||
struct SavedMetrics
|
||||
{
|
||||
float num_samples;
|
||||
float frames;
|
||||
float time;
|
||||
float fps;
|
||||
float internal_fps;
|
||||
float cpu_thread_usage;
|
||||
float cpu_thread_time;
|
||||
float gs_thread_usage;
|
||||
float gs_thread_time;
|
||||
float gpu_time;
|
||||
float gpu_usage;
|
||||
};
|
||||
|
||||
void StartSavingMetrics(u32 seconds);
|
||||
bool IsSavingMetrics();
|
||||
void DumpSavedMetrics();
|
||||
} // namespace PerformanceMetrics
|
||||
|
||||
+1
-1
@@ -679,7 +679,7 @@ void eeloadHook()
|
||||
{
|
||||
CDVDDiscType disc_type;
|
||||
std::string disc_elf;
|
||||
cdvdGetDiscInfo(nullptr, &disc_elf, nullptr, nullptr, &disc_type);
|
||||
cdvdGetDiscInfo(nullptr, &disc_elf, nullptr, nullptr, nullptr, &disc_type);
|
||||
if (disc_type == CDVDDiscType::PS2Disc)
|
||||
{
|
||||
// only allow fast boot for PS2 games
|
||||
|
||||
@@ -23,8 +23,6 @@ bool SaveStateBase::InputRecordingFreeze()
|
||||
|
||||
#include "common/FileSystem.h"
|
||||
#include "common/StringUtil.h"
|
||||
#include "Counters.h"
|
||||
#include "SaveState.h"
|
||||
#include "VMManager.h"
|
||||
#include "Host.h"
|
||||
#include "ImGui/ImGuiOverlays.h"
|
||||
@@ -32,7 +30,7 @@ bool SaveStateBase::InputRecordingFreeze()
|
||||
#include "GameDatabase.h"
|
||||
#include "fmt/format.h"
|
||||
#include "GS.h"
|
||||
#include "Host.h"
|
||||
#include "SIO/Pad/Pad.h"
|
||||
|
||||
InputRecording g_InputRecording;
|
||||
|
||||
@@ -139,6 +137,7 @@ void InputRecording::closeActiveFile()
|
||||
if (m_file.close())
|
||||
{
|
||||
m_is_active = false;
|
||||
Pad::ResetAllControllerInputs();
|
||||
InputRec::log(TRANSLATE_STR("InputRecording", "Input recording stopped"), Host::OSD_ERROR_DURATION);
|
||||
MTGS::PresentCurrentFrame();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "InputRecording.h"
|
||||
#include "InputRecordingControls.h"
|
||||
#include "Utilities/InputRecordingLogger.h"
|
||||
#include "SIO/Pad/Pad.h"
|
||||
|
||||
#include "Host.h"
|
||||
#include "MTGS.h"
|
||||
@@ -29,6 +30,7 @@ void InputRecordingControls::setRecordMode(bool waitForFrameToEnd)
|
||||
if (!waitForFrameToEnd || VMManager::GetState() == VMState::Paused)
|
||||
{
|
||||
m_state = Mode::Recording;
|
||||
Pad::ResetAllControllerInputs();
|
||||
InputRec::log(TRANSLATE("InputRecordingControls","Record Mode Enabled"), Host::OSD_INFO_DURATION);
|
||||
MTGS::PresentCurrentFrame();
|
||||
}
|
||||
@@ -36,6 +38,7 @@ void InputRecordingControls::setRecordMode(bool waitForFrameToEnd)
|
||||
{
|
||||
m_controlQueue.push([&]() {
|
||||
m_state = Mode::Recording;
|
||||
Pad::ResetAllControllerInputs();
|
||||
InputRec::log(TRANSLATE("InputRecordingControls","Record Mode Enabled"), Host::OSD_INFO_DURATION);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -232,6 +232,8 @@ void Pad::SetDefaultHotkeyConfig(SettingsInterface& si)
|
||||
si.SetStringValue("Hotkeys", "GSDumpMultiFrame", "Keyboard/Control & Keyboard/Shift & Keyboard/F8");
|
||||
si.SetStringValue("Hotkeys", "Screenshot", "Keyboard/F8");
|
||||
si.SetStringValue("Hotkeys", "GSDumpSingleFrame", "Keyboard/Shift & Keyboard/F8");
|
||||
si.SetStringValue("Hotkeys", "GSStartSavingMetricsVariableFrames", "Keyboard/F10");
|
||||
si.SetStringValue("Hotkeys", "GSStartSavingMetricsFixedFrames", "Keyboard/Control & Keyboard/F10");
|
||||
si.SetStringValue("Hotkeys", "ToggleSoftwareRendering", "Keyboard/F9");
|
||||
// si.SetStringValue("Hotkeys", "ToggleTextureDumping", "Keyboard"); TBD
|
||||
// si.SetStringValue("Hotkeys", "ToggleTextureReplacements", "Keyboard"); TBD
|
||||
@@ -554,6 +556,32 @@ void Pad::SetControllerState(u32 controller, u32 bind, float value)
|
||||
s_controllers[controller]->Set(bind, value);
|
||||
}
|
||||
|
||||
void Pad::ResetControllerInputs(u32 controller)
|
||||
{
|
||||
if (controller >= NUM_CONTROLLER_PORTS || !HasConnectedPad(controller))
|
||||
return;
|
||||
|
||||
for (InputBindingInfo binding : s_controllers[controller]->GetInfo().bindings)
|
||||
{
|
||||
switch (binding.bind_type)
|
||||
{
|
||||
case InputBindingInfo::Type::Button:
|
||||
case InputBindingInfo::Type::Axis:
|
||||
case InputBindingInfo::Type::HalfAxis:
|
||||
s_controllers[controller]->Set(binding.bind_index, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Pad::ResetAllControllerInputs()
|
||||
{
|
||||
for (u32 port = 0; port < NUM_CONTROLLER_PORTS; port++)
|
||||
ResetControllerInputs(port);
|
||||
}
|
||||
|
||||
bool Pad::Freeze(StateWrapper& sw)
|
||||
{
|
||||
if (sw.IsReading())
|
||||
|
||||
@@ -66,6 +66,10 @@ namespace Pad
|
||||
// Sets the specified bind on a controller to the specified pressure (normalized to 0..1).
|
||||
void SetControllerState(u32 controller, u32 bind, float value);
|
||||
|
||||
// Resets all input binds on a controller to their default state.
|
||||
void ResetControllerInputs(u32 controller);
|
||||
void ResetAllControllerInputs();
|
||||
|
||||
bool Freeze(StateWrapper& sw);
|
||||
|
||||
// Sets the state of the specified macro button.
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
/// Version number for GS and other shaders. Increment whenever any of the contents of the
|
||||
/// shaders change, to invalidate the cache.
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 109; // Last changed in PR 14795
|
||||
static constexpr u32 SHADER_CACHE_VERSION = 113; // Last changed in PR 14743
|
||||
|
||||
+28
-5
@@ -171,6 +171,7 @@ static std::string s_disc_version;
|
||||
static std::string s_title;
|
||||
static std::string s_title_en_search;
|
||||
static std::string s_title_en_replace;
|
||||
static std::string s_cur_region;
|
||||
static u32 s_disc_crc;
|
||||
static u32 s_current_crc;
|
||||
static u32 s_elf_entry_point = 0xFFFFFFFFu;
|
||||
@@ -665,7 +666,12 @@ void VMManager::LoadCoreSettings(SettingsInterface& si)
|
||||
|
||||
// Force MTVU off when playing back GS dumps, it doesn't get used.
|
||||
if (GSDumpReplayer::IsReplayingDump())
|
||||
{
|
||||
EmuConfig.Speedhacks.vuThread = false;
|
||||
GSDumpReplayer::SetFrameRange(EmuConfig.GS.DumpReplayUseFrameRange,
|
||||
EmuConfig.GS.DumpReplayFrameStart, EmuConfig.GS.DumpReplayFrameEnd);
|
||||
GSDumpReplayer::SetLoopCount(EmuConfig.GS.DumpReplayLoopCount);
|
||||
}
|
||||
}
|
||||
|
||||
void VMManager::LoadInputBindings(SettingsInterface& si, std::unique_lock<std::mutex>& lock)
|
||||
@@ -1051,11 +1057,12 @@ void VMManager::UpdateDiscDetails(bool booting)
|
||||
s_disc_crc = GSDumpReplayer::GetDumpCRC();
|
||||
s_disc_elf = {};
|
||||
s_disc_version = {};
|
||||
s_cur_region = "NTSC";
|
||||
serial_is_valid = !s_disc_serial.empty();
|
||||
}
|
||||
else if (CDVDsys_GetSourceType() != CDVD_SourceType::NoDisc)
|
||||
{
|
||||
cdvdGetDiscInfo(&s_disc_serial, &s_disc_elf, &s_disc_version, &s_disc_crc, nullptr);
|
||||
cdvdGetDiscInfo(&s_disc_serial, &s_disc_elf, &s_disc_version, &s_cur_region, &s_disc_crc, nullptr);
|
||||
serial_is_valid = !s_disc_serial.empty();
|
||||
}
|
||||
else if (!s_elf_override.empty())
|
||||
@@ -1063,12 +1070,14 @@ void VMManager::UpdateDiscDetails(bool booting)
|
||||
s_disc_serial = Path::GetFileTitle(s_elf_override);
|
||||
s_disc_version = {};
|
||||
s_disc_crc = 0; // set below
|
||||
s_cur_region = "NTSC";
|
||||
}
|
||||
else
|
||||
{
|
||||
s_disc_serial = BiosSerial;
|
||||
s_disc_version = {};
|
||||
s_disc_crc = 0;
|
||||
s_cur_region = (BiosZone == "Europe") ? "PAL" : "NTSC";
|
||||
title = fmt::format(TRANSLATE_FS("VMManager", "PS2 BIOS ({})"), BiosZone);
|
||||
}
|
||||
|
||||
@@ -1645,6 +1654,7 @@ VMBootResult VMManager::Initialize(const VMBootParameters& boot_params, Error* e
|
||||
}
|
||||
|
||||
PerformanceMetrics::Clear();
|
||||
MTGS::ResetStats();
|
||||
return VMBootResult::StartupSuccess;
|
||||
}
|
||||
|
||||
@@ -2268,14 +2278,14 @@ void VMManager::ResetFrameLimiter()
|
||||
s_limiter_frame_start = GetCPUTicks();
|
||||
}
|
||||
|
||||
void VMManager::Internal::Throttle()
|
||||
void VMManager::Internal::Throttle(bool vsync_start)
|
||||
{
|
||||
if (s_target_speed == 0.0f || s_use_vsync_for_timing)
|
||||
return;
|
||||
|
||||
const u64 uExpectedEnd =
|
||||
s_limiter_frame_start +
|
||||
s_limiter_ticks_per_frame; // Compute when we would expect this frame to end, assuming everything goes perfectly perfect.
|
||||
(vsync_start ? (s_limiter_ticks_per_frame * 0.9) : s_limiter_ticks_per_frame); // Compute when we would expect this frame to end, assuming everything goes perfectly perfect.
|
||||
const u64 iEnd = GetCPUTicks(); // The current tick we actually stopped on.
|
||||
const s64 sDeltaTime = iEnd - uExpectedEnd; // The diff between when we stopped and when we expected to.
|
||||
|
||||
@@ -2304,8 +2314,11 @@ void VMManager::Internal::Throttle()
|
||||
{
|
||||
}
|
||||
|
||||
// Finally, set our next frame start to when this one ends
|
||||
s_limiter_frame_start = uExpectedEnd;
|
||||
if (!vsync_start)
|
||||
{
|
||||
// Finally, set our next frame start to when this one ends
|
||||
s_limiter_frame_start = uExpectedEnd;
|
||||
}
|
||||
}
|
||||
|
||||
void VMManager::Internal::FrameRateChanged()
|
||||
@@ -2818,6 +2831,11 @@ bool VMManager::Internal::IsFastBootInProgress()
|
||||
return s_fast_boot_requested && !HasBootedELF();
|
||||
}
|
||||
|
||||
std::string VMManager::Internal::GetCurrentRegion()
|
||||
{
|
||||
return s_cur_region;
|
||||
}
|
||||
|
||||
void VMManager::Internal::DisableFastBoot()
|
||||
{
|
||||
if (!s_fast_boot_requested)
|
||||
@@ -3270,6 +3288,11 @@ void VMManager::WarnAboutUnsafeSettings()
|
||||
append(ICON_FA_CIRCLE_EXCLAMATION,
|
||||
TRANSLATE_SV("VMManager", "Draw Buffering is enabled, this may result in graphical errors."));
|
||||
}
|
||||
if (EmuConfig.GS.UserHacks_RewriteLargeSTCoords)
|
||||
{
|
||||
append(ICON_FA_CIRCLE_EXCLAMATION,
|
||||
TRANSLATE_SV("VMManager", "Rewrite large ST is enabled, this may reduce performance."));
|
||||
}
|
||||
if (EmuConfig.GS.DumpReplaceableTextures)
|
||||
{
|
||||
append(ICON_FA_CIRCLE_EXCLAMATION,
|
||||
|
||||
+4
-1
@@ -306,6 +306,9 @@ namespace VMManager
|
||||
/// Returns true if fast booting is active (requested but ELF not started).
|
||||
bool IsFastBootInProgress();
|
||||
|
||||
// Returns the current disc/BIOS region, if set.
|
||||
std::string GetCurrentRegion();
|
||||
|
||||
/// Disables fast boot if it was requested, and found to be incompatible.
|
||||
void DisableFastBoot();
|
||||
|
||||
@@ -319,7 +322,7 @@ namespace VMManager
|
||||
void FrameRateChanged();
|
||||
|
||||
/// Throttles execution, or limits the frame rate.
|
||||
void Throttle();
|
||||
void Throttle(bool vsync_start);
|
||||
|
||||
/// Resets/clears all execution/code caches.
|
||||
void ClearCPUExecutionCaches();
|
||||
|
||||
@@ -2688,7 +2688,7 @@ StartRecomp:
|
||||
if ((oldBlock->startpc + oldBlock->size * 4) <= HWADDR(startpc))
|
||||
break;
|
||||
|
||||
if (memcmp(&recRAMCopy[oldBlock->startpc / 4], PSM(oldBlock->startpc),
|
||||
if (memcmp(&recRAMCopy[oldBlock->startpc], PSM(oldBlock->startpc),
|
||||
oldBlock->size * 4))
|
||||
{
|
||||
recClear(startpc, (pc - startpc) / 4);
|
||||
@@ -2698,7 +2698,7 @@ StartRecomp:
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(&recRAMCopy[HWADDR(startpc) / 4], PSM(startpc), pc - startpc);
|
||||
memcpy(&recRAMCopy[HWADDR(startpc)], PSM(startpc), pc - startpc);
|
||||
}
|
||||
|
||||
s_pCurBlock->SetFnptr((uptr)recPtr);
|
||||
|
||||
+2
-1
@@ -237,7 +237,8 @@ public:
|
||||
// if we're using the flag hack, ignore the mac flags going in to the new block too if an exact match wasn't requested.
|
||||
if (mVUsFlagHack)
|
||||
{
|
||||
if ((ref.quick & ~0x0C04) != (quick64 & ~0x0C04)) continue;
|
||||
if ((ref.quick & ~0x3002) != (quick64 & ~0x3002))
|
||||
continue;
|
||||
}
|
||||
else if (ref.quick != quick64) continue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user