Skip to content

fix(HDR): reduce false display detections#2186

Merged
alandtse merged 17 commits into
community-shaders:devfrom
SkrubbySkrubInAShrub:HDR-detection
Apr 24, 2026
Merged

fix(HDR): reduce false display detections#2186
alandtse merged 17 commits into
community-shaders:devfrom
SkrubbySkrubInAShrub:HDR-detection

Conversation

@SkrubbySkrubInAShrub
Copy link
Copy Markdown
Collaborator

@SkrubbySkrubInAShrub SkrubbySkrubInAShrub commented Apr 22, 2026

Attempt at reducing false positives and negatives. Also added more information for the user to understand what is going on.
Still needs to be tested, but works on my machine.
based on methods given to me by shortfuse(RenoDX) and Pumbo.

Summary by CodeRabbit

  • Bug Fixes

    • More reliable HDR detection by identifying the actual presenting display and using robust fallbacks in wrapped/interposed setups, improving consistent HDR state reporting.
  • New Features

    • UI/status text and tooltips now distinguish HDR "active" versus "capable".
    • App now surfaces monitor "capable" and "active" separately; automatic detection and status reporting show whether Windows HDR is currently enabled (active) rather than just capability.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Refactors HDR detection to be swap-chain–centric: uses IDXGISwapChain::GetContainingOutput and DisplayConfig advanced color info (preferring Windows 11 Compat variant) to set separate "capable" vs "enabled" flags. Adds HDRDisplay::isHDRCapableMonitor; DetectHDR() now returns whether Windows HDR is active/enabled.

Changes

Cohort / File(s) Summary
HDR detection & header
src/Features/HDRDisplay.cpp, src/Features/HDRDisplay.h
Rewrote detection from HWND/monitor-rect to swap-chain-centric flow: call IDXGISwapChain::GetContainingOutput() -> map output to DisplayConfig device (viewGdiDeviceName) -> call DisplayConfigGetDeviceInfo (prefer Compat_DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2, fallback to DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO) to obtain highDynamicRangeSupported (capability) and activeColorMode (enabled). Secondary fallback: enumerate adapter outputs and use IDXGIOutput6::GetDesc1().ColorSpace to infer HDR when GetContainingOutput fails. Added static bool isHDRCapableMonitor; changed DetectHDR() and isHDRMonitor semantics to reflect active/enabled state only; updated comments/UI/tooltips accordingly.

Sequence Diagram(s)

sequenceDiagram
    participant App as "App (HDRDisplay)"
    participant SwapChain as "IDXGISwapChain"
    participant DXGIOutput as "IDXGIOutput / IDXGIOutput6"
    participant DisplayConfig as "DisplayConfigGetDeviceInfo"

    App->>SwapChain: GetContainingOutput()
    SwapChain-->>App: IDXGIOutput (or fail)
    alt GetContainingOutput succeeded
        App->>DXGIOutput: GetDesc() -> viewGdiDeviceName
        App->>DisplayConfig: DisplayConfigGetDeviceInfo(viewGdiDeviceName) [Compat_ADV_COLOR_INFO_2 -> ADV_COLOR_INFO]
        DisplayConfig-->>App: {highDynamicRangeSupported, activeColorMode}
        App->>App: set isHDRCapableMonitor (supported) / isHDRMonitor (active)
    else GetContainingOutput failed
        App->>DXGIOutput: enumerate outputs via adapter / OutputWindow -> IDXGIOutput6::GetDesc1()
        DXGIOutput-->>App: ColorSpace
        App->>App: infer active state from ColorSpace -> set capability & active accordingly
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • davo0411
  • alandtse
  • doodlum

Poem

🐰 I hopped from swap-chain to GDI name bright,
I sniffed the advanced color flags in Windows' light,
I set "capable" and "on" with a twitch of my nose,
Now HDR wakes gently where the framebuffer glows,
Hop—may your pixels bloom carrot-bright tonight 🥕✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: refactoring HDR detection to reduce false positive/negative detection results by distinguishing between HDR capability and active HDR status.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

No actionable suggestions for changed features.

Automated formatting by clang-format, prettier, and other hooks.
See https://pre-commit.ci for details.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/Features/HDRDisplay.cpp (1)

128-146: Optional: return true from the DXGI fallback when it successfully populates the out params.

The fallback block sets enabled/supported via IDXGIOutput6::GetDesc1 but then always return false;. Currently DetectHDR() at line 236 discards the return value, so behavior is correct today, but returning false after a successful query makes the function's contract ambiguous (did we fail to detect, or did we detect SDR?) and is a latent footgun for future callers that might gate on the return value.

♻️ Proposed refactor
 		winrt::com_ptr<IDXGIOutput> output;
 		if (SUCCEEDED(swapChain->GetContainingOutput(output.put()))) {
 			winrt::com_ptr<IDXGIOutput6> output6;
 			if (SUCCEEDED(output->QueryInterface(IID_PPV_ARGS(output6.put())))) {
 				DXGI_OUTPUT_DESC1 desc1{};
 				if (SUCCEEDED(output6->GetDesc1(&desc1))) {
 					enabled = desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
 					supported = enabled;
 					logger::debug("[HDR] DXGI fallback detection: colorSpace={}", static_cast<int>(desc1.ColorSpace));
+					return true;
 				}
 			}
 		}
 		return false;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/HDRDisplay.cpp` around lines 128 - 146, The DXGI fallback
currently populates enabled/supported via IDXGIOutput6::GetDesc1 but
unconditionally returns false; change the fallback in the
GetDisplayConfigPathInfo failure branch so that after a successful
QueryInterface/GetDesc1 and setting enabled and supported it returns true (only
return false if the fallback fails to obtain the output or GetDesc1 fails).
Update the return logic around
swapChain/GetContainingOutput/QueryInterface/GetDesc1 so
GetDisplayConfigPathInfo, DetectHDR, and any future callers can trust the
boolean return; keep the existing behavior of logging via logger::debug and only
return false on actual failure to populate the out params.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 128-146: The DXGI fallback currently populates enabled/supported
via IDXGIOutput6::GetDesc1 but unconditionally returns false; change the
fallback in the GetDisplayConfigPathInfo failure branch so that after a
successful QueryInterface/GetDesc1 and setting enabled and supported it returns
true (only return false if the fallback fails to obtain the output or GetDesc1
fails). Update the return logic around
swapChain/GetContainingOutput/QueryInterface/GetDesc1 so
GetDisplayConfigPathInfo, DetectHDR, and any future callers can trust the
boolean return; keep the existing behavior of logging via logger::debug and only
return false on actual failure to populate the out params.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1ec2a3b1-4d33-4881-8c74-2d5b74f897dc

📥 Commits

Reviewing files that changed from the base of the PR and between 9543ada and d63a4cb.

📒 Files selected for processing (2)
  • src/Features/HDRDisplay.cpp
  • src/Features/HDRDisplay.h

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Features/HDRDisplay.cpp (1)

232-243: Guard DetectHDR() against a null globals::d3d::swapChain.

IsHDRSupportedAndEnabled and GetSwapChainOutputDeviceName dereference swapChain without a null check (line 67). LoadSettings already defers auto-detection until SetupResources specifically because the swap chain isn't valid early (lines 523-524), but DetectHDR() is also invoked from RestoreDefaultSettings() (line 541) and is public static, so a future caller can easily trip this. Cheap defensive guard:

🛡️ Proposed fix
 bool HDRDisplay::DetectHDR()
 {
 	bool hdrSupported = false;
 	bool hdrEnabled = false;

-	IsHDRSupportedAndEnabled(globals::d3d::swapChain, hdrSupported, hdrEnabled);
+	if (globals::d3d::swapChain) {
+		IsHDRSupportedAndEnabled(globals::d3d::swapChain, hdrSupported, hdrEnabled);
+	} else {
+		logger::warn("[HDR] DetectHDR called before swap chain available");
+	}

 	isHDRMonitor = hdrEnabled;
 	isHDRCapableMonitor = hdrSupported;

As per coding guidelines: "Include proper resource management and graceful degradation for DirectX 11 resources and user input validation to prevent crashes from malformed configurations".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/HDRDisplay.cpp` around lines 232 - 243, DetectHDR currently
calls IsHDRSupportedAndEnabled using globals::d3d::swapChain without validating
the swapChain pointer; add a null check at the start of HDRDisplay::DetectHDR()
to return false (and set isHDRMonitor/isHDRCapableMonitor to false) if
globals::d3d::swapChain is null so callers like RestoreDefaultSettings or any
external caller cannot dereference a null swapChain; update only DetectHDR
(referencing globals::d3d::swapChain, IsHDRSupportedAndEnabled, isHDRMonitor,
isHDRCapableMonitor) to perform this defensive guard and preserve existing
logging behavior when swapChain is present.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 80-147: GetDisplayConfigPathInfo currently logs a warning when
GetSwapChainOutputDeviceName fails, which causes a scary warning even when
IsHDRSupportedAndEnabled later recovers via IDXGIOutput6 fallback; also the
fallback redundantly calls GetContainingOutput again so the comment is
misleading. Remove the unconditional logger::warn from GetDisplayConfigPathInfo
(do not emit logs inside that helper), let it simply return false on failure,
and move/log a single warn or debug in IsHDRSupportedAndEnabled after both the
display-config path attempt and the IDXGIOutput6 fallback have failed;
alternatively, if you want to preserve distinct messages, make
GetDisplayConfigPathInfo return an error enum or set an out-flag (e.g., bool
swapchainOutputMissing) so IsHDRSupportedAndEnabled can log a downgraded debug
message when the fallback succeeds and only warn when both methods fail. Ensure
references to GetDisplayConfigPathInfo, IsHDRSupportedAndEnabled,
GetContainingOutput, and IDXGIOutput6::GetDesc1 are updated accordingly.

---

Nitpick comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 232-243: DetectHDR currently calls IsHDRSupportedAndEnabled using
globals::d3d::swapChain without validating the swapChain pointer; add a null
check at the start of HDRDisplay::DetectHDR() to return false (and set
isHDRMonitor/isHDRCapableMonitor to false) if globals::d3d::swapChain is null so
callers like RestoreDefaultSettings or any external caller cannot dereference a
null swapChain; update only DetectHDR (referencing globals::d3d::swapChain,
IsHDRSupportedAndEnabled, isHDRMonitor, isHDRCapableMonitor) to perform this
defensive guard and preserve existing logging behavior when swapChain is
present.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a504a4e8-6177-4831-afee-c6e75cc1b7c2

📥 Commits

Reviewing files that changed from the base of the PR and between 0764e77 and eaf7f02.

📒 Files selected for processing (1)
  • src/Features/HDRDisplay.cpp

Comment thread src/Features/HDRDisplay.cpp
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Features/HDRDisplay.cpp (1)

21-52: ⚠️ Potential issue | 🟠 Major

Fix the fallback enum value for DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2.

The polyfill defines this as 13, but the Windows DisplayConfig enum reserves 12 and 13 for monitor specialization operations before this request. The correct value is 15. With older SDKs lacking this enum, the hardcoded value 13 causes DisplayConfigGetDeviceInfo to query the wrong request type (SET_MONITOR_SPECIALIZATION instead of GET_ADVANCED_COLOR_INFO_2), breaking HDR capability detection.

Also update the struct bitfield wideColorEnforced and reserved to match the SDK definition: wideColorEnforced should be split into wideColorSupported (1 bit) and wideColorUserEnabled (1 bit), with reserved reduced to 24 bits.

Proposed fix
 `#ifndef` DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2
-#	define DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2 ((DISPLAYCONFIG_DEVICE_INFO_TYPE)13)
+#	define DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2 ((DISPLAYCONFIG_DEVICE_INFO_TYPE)15)
@@
-			UINT32 wideColorEnforced: 1;
-			UINT32 reserved: 25;
+			UINT32 wideColorSupported: 1;
+			UINT32 wideColorUserEnabled: 1;
+			UINT32 reserved: 24;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/HDRDisplay.cpp` around lines 21 - 52, The fallback enum macro
DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2 is incorrect (currently 13)
— change its value to 15 so DisplayConfigGetDeviceInfo uses
GET_ADVANCED_COLOR_INFO_2; in the DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 struct
adjust the bitfield to match the SDK: replace wideColorEnforced with two 1-bit
fields wideColorSupported and wideColorUserEnabled, and shrink reserved to 24
bits (keeping the other bit names unchanged), ensuring the union still exposes
the UINT32 value member.
♻️ Duplicate comments (1)
src/Features/HDRDisplay.cpp (1)

125-144: ⚠️ Potential issue | 🟡 Minor

The DXGI fallback still cannot recover GetContainingOutput wrapper failures.

When GetDisplayConfigPathInfo() fails because GetSwapChainOutputDeviceName() cannot call GetContainingOutput(), this fallback repeats the same GetContainingOutput() call at Line 131. So the Streamline/frame-gen case described in the comment still returns false instead of falling back.

Possible direction
-		if (!GetDisplayConfigPathInfo(swapChain, pathInfo)) {
-			// GetContainingOutput can fail under Streamline/frame-gen wrappers. Fall back to
-			// IDXGIOutput6::GetDesc1 which reads the output's current color space directly.
+		if (!GetDisplayConfigPathInfo(swapChain, pathInfo)) {
+			// DisplayConfig matching can fail even when the presenting output is available.
+			// Fall back to IDXGIOutput6::GetDesc1 for those cases.

If wrapper recovery is still required, this path needs a fallback that does not depend on IDXGISwapChain::GetContainingOutput() again.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/HDRDisplay.cpp` around lines 125 - 144, The fallback currently
re-calls IDXGISwapChain::GetContainingOutput (same failing call) inside the
GetDisplayConfigPathInfo failure path; change the fallback to not depend on
GetContainingOutput: call swapChain->GetDesc1() (use the IDXGISwapChain1/
GetDesc1 path) to obtain the OutputWindow, use MonitorFromWindow/MonitorFromRect
to get the HMONITOR, then enumerate DXGI adapters/outputs
(IDXGIFactory::EnumAdapters1 / IDXGIAdapter::EnumOutputs) and call
IDXGIOutput::GetDesc1 on each to find the matching output for that HMONITOR;
once you find the matching IDXGIOutput/IDXGIOutput6, call GetDesc1 and derive
enabled/supported as before (checking desc1.ColorSpace), logging the same
debug/warn messages and returning true/false accordingly (refer to
GetDisplayConfigPathInfo, GetContainingOutput, swapChain->GetDesc1,
MonitorFromWindow, EnumAdapters1, EnumOutputs, IDXGIOutput::GetDesc1,
IDXGIOutput6).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 21-52: The fallback enum macro
DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2 is incorrect (currently 13)
— change its value to 15 so DisplayConfigGetDeviceInfo uses
GET_ADVANCED_COLOR_INFO_2; in the DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 struct
adjust the bitfield to match the SDK: replace wideColorEnforced with two 1-bit
fields wideColorSupported and wideColorUserEnabled, and shrink reserved to 24
bits (keeping the other bit names unchanged), ensuring the union still exposes
the UINT32 value member.

---

Duplicate comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 125-144: The fallback currently re-calls
IDXGISwapChain::GetContainingOutput (same failing call) inside the
GetDisplayConfigPathInfo failure path; change the fallback to not depend on
GetContainingOutput: call swapChain->GetDesc1() (use the IDXGISwapChain1/
GetDesc1 path) to obtain the OutputWindow, use MonitorFromWindow/MonitorFromRect
to get the HMONITOR, then enumerate DXGI adapters/outputs
(IDXGIFactory::EnumAdapters1 / IDXGIAdapter::EnumOutputs) and call
IDXGIOutput::GetDesc1 on each to find the matching output for that HMONITOR;
once you find the matching IDXGIOutput/IDXGIOutput6, call GetDesc1 and derive
enabled/supported as before (checking desc1.ColorSpace), logging the same
debug/warn messages and returning true/false accordingly (refer to
GetDisplayConfigPathInfo, GetContainingOutput, swapChain->GetDesc1,
MonitorFromWindow, EnumAdapters1, EnumOutputs, IDXGIOutput::GetDesc1,
IDXGIOutput6).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 546a5afd-f194-42e7-8005-c642afedbcba

📥 Commits

Reviewing files that changed from the base of the PR and between eaf7f02 and a7b637d.

📒 Files selected for processing (1)
  • src/Features/HDRDisplay.cpp

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/Features/HDRDisplay.cpp (2)

1-1: Nit: conventional commit scope casing.

PR title fix(HDR): reduce false display detections uses an uppercase scope; the repo's conventional-commit guideline examples (feat(vr), fix(water)) use lowercase. Consider fix(hdr): reduce false display detections to stay consistent. As per coding guidelines: "Format: type(scope): description … Examples: - feat(vr): add cross-eye sampling".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/HDRDisplay.cpp` at line 1, Update the PR title to use a
lowercase conventional-commit scope: change the current title `fix(HDR): reduce
false display detections` to `fix(hdr): reduce false display detections`; this
aligns with the repo guideline examples and the existing symbol/name casing such
as HDRDisplay/HDRDisplay.h referenced in the diff.

147-178: Optional: simplify DXGI factory acquisition via the swap chain.

The globals::d3d::deviceIDXGIDeviceIDXGIAdapterIDXGIFactory1 chain is longer than needed and is not guarded against a null globals::d3d::device. Since you already have the swap chain, you can get its adapter/factory directly, which is also more correct on multi-GPU systems because it resolves the adapter actually presenting this swap chain rather than the one backing globals::d3d::device:

♻️ Proposed refactor
-			winrt::com_ptr<IDXGIDevice> dxgiDevice;
-			winrt::com_ptr<IDXGIAdapter> adapter;
-			winrt::com_ptr<IDXGIFactory1> factory;
-			if (SUCCEEDED(globals::d3d::device->QueryInterface(IID_PPV_ARGS(dxgiDevice.put()))) &&
-				SUCCEEDED(dxgiDevice->GetAdapter(adapter.put())) &&
-				SUCCEEDED(adapter->GetParent(IID_PPV_ARGS(factory.put())))) {
+			winrt::com_ptr<IDXGIAdapter> scAdapter;
+			winrt::com_ptr<IDXGIFactory1> factory;
+			if (SUCCEEDED(swapChain->GetParent(IID_PPV_ARGS(scAdapter.put()))) &&
+				SUCCEEDED(scAdapter->GetParent(IID_PPV_ARGS(factory.put())))) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/HDRDisplay.cpp` around lines 147 - 178, Replace the long
globals::d3d::device → QueryInterface(IID_PPV_ARGS(dxgiDevice)) → GetAdapter →
GetParent chain with the swap chain's output lookup: call the existing swap
chain's GetContainingOutput to obtain the IDXGIOutput for the presenting
surface, then QueryInterface that output to IDXGIOutput6 and call GetDesc1 to
inspect ColorSpace (instead of enumerating factory adapters/outputs). Also add a
null-check for globals::d3d::device before any use, and remove the unused
IDXGIDevice/IDXGIAdapter/IDXGIFactory1 acquisition (the code paths using
QueryInterface, GetAdapter, and GetParent should be replaced). Ensure you still
handle DXGI_ERROR_NOT_FOUND and FAILED/ SUCCEEDED checks around
GetContainingOutput, QueryInterface(out6), and GetDesc1, and keep the existing
logic that sets enabled/supported and logs desc1.ColorSpace.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 138-144: The fallback that picks the primary monitor when
OutputWindow is null (hMonitor = MonitorFromRect(..., MONITOR_DEFAULTTOPRIMARY))
can misidentify the active display; update the logic around OutputWindow /
hMonitor (the MonitorFromWindow/MonitorFromRect path) to avoid silently guessing
the primary monitor: either (preferred) bail out and return false when no
reliable monitor can be determined, or at minimum log the picked monitor’s
identity by querying the chosen IDXGIOutput6's description (outDesc.DeviceName)
so misdetection is diagnosable; ensure the change is applied where hMonitor is
derived and before any ColorSpace/IDXGIOutput6 lookups.

---

Nitpick comments:
In `@src/Features/HDRDisplay.cpp`:
- Line 1: Update the PR title to use a lowercase conventional-commit scope:
change the current title `fix(HDR): reduce false display detections` to
`fix(hdr): reduce false display detections`; this aligns with the repo guideline
examples and the existing symbol/name casing such as HDRDisplay/HDRDisplay.h
referenced in the diff.
- Around line 147-178: Replace the long globals::d3d::device →
QueryInterface(IID_PPV_ARGS(dxgiDevice)) → GetAdapter → GetParent chain with the
swap chain's output lookup: call the existing swap chain's GetContainingOutput
to obtain the IDXGIOutput for the presenting surface, then QueryInterface that
output to IDXGIOutput6 and call GetDesc1 to inspect ColorSpace (instead of
enumerating factory adapters/outputs). Also add a null-check for
globals::d3d::device before any use, and remove the unused
IDXGIDevice/IDXGIAdapter/IDXGIFactory1 acquisition (the code paths using
QueryInterface, GetAdapter, and GetParent should be replaced). Ensure you still
handle DXGI_ERROR_NOT_FOUND and FAILED/ SUCCEEDED checks around
GetContainingOutput, QueryInterface(out6), and GetDesc1, and keep the existing
logic that sets enabled/supported and logs desc1.ColorSpace.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ea9dda17-663d-4a62-a246-bdef4b22adc7

📥 Commits

Reviewing files that changed from the base of the PR and between a7b637d and 2918fed.

📒 Files selected for processing (1)
  • src/Features/HDRDisplay.cpp

Comment thread src/Features/HDRDisplay.cpp Outdated
@SkrubbySkrubInAShrub
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Features/HDRDisplay.cpp (1)

20-53: ⚠️ Potential issue | 🔴 Critical

Use namespace-scoped compatibility names to avoid redefining Win11 SDK symbols.

The #ifndef DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2 guard cannot detect enum values—only preprocessor macros. In newer Windows SDKs, this identifier is an enum value in DISPLAYCONFIG_DEVICE_INFO_TYPE, so the preprocessor cannot see it. The guard evaluates to TRUE even with modern headers, causing the code to redeclare DISPLAYCONFIG_ADVANCED_COLOR_MODE and DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2, which already exist in the SDK, resulting in typedef redefinition errors.

Replace the conflicting typedefs with namespace-scoped compatibility names to prevent collisions across SDK versions.

🛠️ Proposed compatibility-safe approach
-#ifndef DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2
-#	define DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2 ((DISPLAYCONFIG_DEVICE_INFO_TYPE)15)
-
-typedef enum
+namespace Win11AdvancedColorCompat
 {
-	DISPLAYCONFIG_ADVANCED_COLOR_MODE_SDR = 0,
-	DISPLAYCONFIG_ADVANCED_COLOR_MODE_WCG = 1,
-	DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR = 2
-} DISPLAYCONFIG_ADVANCED_COLOR_MODE;
+	constexpr auto kGetAdvancedColorInfo2 = static_cast<DISPLAYCONFIG_DEVICE_INFO_TYPE>(15);
 
-typedef struct DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2
-{
-	DISPLAYCONFIG_DEVICE_INFO_HEADER header;
-	union
+	enum DISPLAYCONFIG_ADVANCED_COLOR_MODE_COMPAT
 	{
-		struct
+		DISPLAYCONFIG_ADVANCED_COLOR_MODE_SDR_COMPAT = 0,
+		DISPLAYCONFIG_ADVANCED_COLOR_MODE_WCG_COMPAT = 1,
+		DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR_COMPAT = 2
+	};
+
+	struct DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2_COMPAT
+	{
+		DISPLAYCONFIG_DEVICE_INFO_HEADER header;
+		union
 		{
+			struct
+			{
-			UINT32 advancedColorSupported: 1;
-			UINT32 advancedColorActive: 1;
-			UINT32 reserved1: 1;
-			UINT32 advancedColorLimitedByPolicy: 1;
-			UINT32 highDynamicRangeSupported: 1;
-			UINT32 highDynamicRangeUserEnabled: 1;
-			UINT32 wideColorSupported: 1;
-			UINT32 wideColorUserEnabled: 1;
-			UINT32 reserved: 24;
+				UINT32 advancedColorSupported: 1;
+				UINT32 advancedColorActive: 1;
+				UINT32 reserved1: 1;
+				UINT32 advancedColorLimitedByPolicy: 1;
+				UINT32 highDynamicRangeSupported: 1;
+				UINT32 highDynamicRangeUserEnabled: 1;
+				UINT32 wideColorSupported: 1;
+				UINT32 wideColorUserEnabled: 1;
+				UINT32 reserved: 24;
+			};
+			UINT32 value;
 		};
-		UINT32 value;
+		DISPLAYCONFIG_COLOR_ENCODING colorEncoding;
+		UINT32 bitsPerColorChannel;
+		DISPLAYCONFIG_ADVANCED_COLOR_MODE_COMPAT activeColorMode;
 	};
-	DISPLAYCONFIG_COLOR_ENCODING colorEncoding;
-	UINT32 bitsPerColorChannel;
-	DISPLAYCONFIG_ADVANCED_COLOR_MODE activeColorMode;
-} DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2;
-#endif
+}
-		DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 colorInfo2{};
-		colorInfo2.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2;
+		Win11AdvancedColorCompat::DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2_COMPAT colorInfo2{};
+		colorInfo2.header.type = Win11AdvancedColorCompat::kGetAdvancedColorInfo2;
 		colorInfo2.header.size = sizeof(colorInfo2);
 		colorInfo2.header.adapterId = pathInfo.targetInfo.adapterId;
 		colorInfo2.header.id = pathInfo.targetInfo.id;
 		if (DisplayConfigGetDeviceInfo(&colorInfo2.header) == ERROR_SUCCESS) {
 			supported = colorInfo2.highDynamicRangeSupported != 0;
-			enabled = colorInfo2.activeColorMode == DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR;
+			enabled = colorInfo2.activeColorMode == Win11AdvancedColorCompat::DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR_COMPAT;

Also applies to: lines 184-191

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/HDRDisplay.cpp` around lines 20 - 53, The preprocessor guard
using DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2 fails on newer SDKs
because that identifier is an enum member (not a macro), causing your typedefs
DISPLAYCONFIG_ADVANCED_COLOR_MODE and DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 to
be unconditionally redeclared; to fix, stop redefining the SDK symbols and
instead add compatibility-scoped names (e.g.,
Compat_DISPLAYCONFIG_ADVANCED_COLOR_MODE and
Compat_DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2) in your project namespace and
only define them when the SDK types are not available, then update any local
usage to those compatibility names (or add conditional using/type-alias that
maps Compat_* to the SDK types when they already exist); apply the same change
for the similar block at the later lines referenced (lines 184-191) so you never
directly typedef/enum the SDK identifiers DISPLAYCONFIG_ADVANCED_COLOR_MODE or
DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 20-53: The preprocessor guard using
DISPLAYCONFIG_DEVICE_INFO_GET_ADVANCED_COLOR_INFO_2 fails on newer SDKs because
that identifier is an enum member (not a macro), causing your typedefs
DISPLAYCONFIG_ADVANCED_COLOR_MODE and DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 to
be unconditionally redeclared; to fix, stop redefining the SDK symbols and
instead add compatibility-scoped names (e.g.,
Compat_DISPLAYCONFIG_ADVANCED_COLOR_MODE and
Compat_DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2) in your project namespace and
only define them when the SDK types are not available, then update any local
usage to those compatibility names (or add conditional using/type-alias that
maps Compat_* to the SDK types when they already exist); apply the same change
for the similar block at the later lines referenced (lines 184-191) so you never
directly typedef/enum the SDK identifiers DISPLAYCONFIG_ADVANCED_COLOR_MODE or
DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d37c4a02-5f92-4b73-9ad1-0625799ec11a

📥 Commits

Reviewing files that changed from the base of the PR and between a7b637d and 8ddf61a.

📒 Files selected for processing (1)
  • src/Features/HDRDisplay.cpp

@SkrubbySkrubInAShrub
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 24-35: When building against the newer SDK branch (the `#if` path)
the enum value constants like Compat_DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR are
missing; add compat aliases in that branch by defining constexpr values (or enum
constants) that map Compat_DISPLAYCONFIG_ADVANCED_COLOR_MODE_SDR/WCG/HDR to the
corresponding DISPLAYCONFIG_ADVANCED_COLOR_MODE_* values from
DISPLAYCONFIG_ADVANCED_COLOR_MODE so code using
Compat_DISPLAYCONFIG_ADVANCED_COLOR_MODE_HDR (and the other enum constants)
compiles; update the `#if` block where Compat_DISPLAYCONFIG_ADVANCED_COLOR_MODE
and Compat_DISPLAYCONFIG_GET_ADVANCED_COLOR_INFO_2 are aliased to also declare
the three Compat_DISPLAYCONFIG_ADVANCED_COLOR_MODE_* constant aliases.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2181cb8f-d0e0-417c-8ad3-5ef19c780960

📥 Commits

Reviewing files that changed from the base of the PR and between 8ddf61a and 83e49dc.

📒 Files selected for processing (1)
  • src/Features/HDRDisplay.cpp

Comment thread src/Features/HDRDisplay.cpp Outdated
@SkrubbySkrubInAShrub
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/Features/HDRDisplay.cpp (1)

156-189: Enumerating the full factory is unnecessary — the device's adapter is already known.

You already have adapter (the DXGI adapter backing globals::d3d::device). The swap chain is tied to that adapter, so you only need to enumerate its outputs rather than re-enumerating every adapter in the system via factory->EnumAdapters1. This simplifies the fallback and avoids touching unrelated GPUs on multi-adapter systems (e.g. iGPU + dGPU laptops).

♻️ Proposed simplification
-			winrt::com_ptr<IDXGIDevice> dxgiDevice;
-			winrt::com_ptr<IDXGIAdapter> adapter;
-			winrt::com_ptr<IDXGIFactory1> factory;
-			if (globals::d3d::device &&
-				SUCCEEDED(globals::d3d::device->QueryInterface(IID_PPV_ARGS(dxgiDevice.put()))) &&
-				SUCCEEDED(dxgiDevice->GetAdapter(adapter.put())) &&
-				SUCCEEDED(adapter->GetParent(IID_PPV_ARGS(factory.put())))) {
-				for (UINT ai = 0;; ++ai) {
-					winrt::com_ptr<IDXGIAdapter1> adap;
-					if (factory->EnumAdapters1(ai, adap.put()) == DXGI_ERROR_NOT_FOUND)
-						break;
-					for (UINT oi = 0;; ++oi) {
-						winrt::com_ptr<IDXGIOutput> out;
-						if (adap->EnumOutputs(oi, out.put()) == DXGI_ERROR_NOT_FOUND)
-							break;
-						DXGI_OUTPUT_DESC outDesc{};
-						if (FAILED(out->GetDesc(&outDesc)))
-							continue;
-						if (outDesc.Monitor != hMonitor)
-							continue;
-						winrt::com_ptr<IDXGIOutput6> out6;
-						if (SUCCEEDED(out->QueryInterface(IID_PPV_ARGS(out6.put())))) {
-							DXGI_OUTPUT_DESC1 desc1{};
-							if (SUCCEEDED(out6->GetDesc1(&desc1))) {
-								enabled = desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
-								supported = enabled;
-								logger::debug("[HDR] DXGI fallback detection: colorSpace={}", static_cast<int>(desc1.ColorSpace));
-								return true;
-							}
-						}
-					}
-				}
-			}
+			winrt::com_ptr<IDXGIDevice> dxgiDevice;
+			winrt::com_ptr<IDXGIAdapter> adapter;
+			if (globals::d3d::device &&
+				SUCCEEDED(globals::d3d::device->QueryInterface(IID_PPV_ARGS(dxgiDevice.put()))) &&
+				SUCCEEDED(dxgiDevice->GetAdapter(adapter.put()))) {
+				for (UINT oi = 0;; ++oi) {
+					winrt::com_ptr<IDXGIOutput> out;
+					if (adapter->EnumOutputs(oi, out.put()) == DXGI_ERROR_NOT_FOUND)
+						break;
+					DXGI_OUTPUT_DESC outDesc{};
+					if (FAILED(out->GetDesc(&outDesc)) || outDesc.Monitor != hMonitor)
+						continue;
+					winrt::com_ptr<IDXGIOutput6> out6;
+					if (SUCCEEDED(out->QueryInterface(IID_PPV_ARGS(out6.put())))) {
+						DXGI_OUTPUT_DESC1 desc1{};
+						if (SUCCEEDED(out6->GetDesc1(&desc1))) {
+							enabled = desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
+							supported = enabled;
+							logger::debug("[HDR] DXGI fallback detection: colorSpace={}", static_cast<int>(desc1.ColorSpace));
+							return true;
+						}
+					}
+				}
+			}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/HDRDisplay.cpp` around lines 156 - 189, The code needlessly
re-enumerates all adapters via factory->EnumAdapters1; since you already
obtained the device's adapter (adapter) from globals::d3d::device, restrict
output enumeration to that adapter only. Replace the outer factory/EnumAdapters1
loop and local adap with a single loop calling adapter->EnumOutputs(oi,
out.put()) (keep the existing inner output handling and QueryInterface to
IDXGIOutput6/getDesc1), remove factory and adap usage, and ensure
enabled/supported and the debug log remain unchanged; this prevents touching
unrelated GPUs on multi-adapter systems.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 156-189: The code needlessly re-enumerates all adapters via
factory->EnumAdapters1; since you already obtained the device's adapter
(adapter) from globals::d3d::device, restrict output enumeration to that adapter
only. Replace the outer factory/EnumAdapters1 loop and local adap with a single
loop calling adapter->EnumOutputs(oi, out.put()) (keep the existing inner output
handling and QueryInterface to IDXGIOutput6/getDesc1), remove factory and adap
usage, and ensure enabled/supported and the debug log remain unchanged; this
prevents touching unrelated GPUs on multi-adapter systems.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b2257c23-028d-404b-aa32-d0f29ca28a95

📥 Commits

Reviewing files that changed from the base of the PR and between 83e49dc and 869486d.

📒 Files selected for processing (1)
  • src/Features/HDRDisplay.cpp

@SkrubbySkrubInAShrub
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Features/HDRDisplay.cpp (1)

1-1: Consider normalizing the PR title scope casing.

Current title is close, but the guideline examples use lowercase scopes. Suggested title: fix(hdr): reduce false display detections. If this maps to a tracked bug, also add Fixes #... or Related to #... in the PR description.

As per coding guidelines, “Conventional Commit Titles … Format: type(scope): description … Style: lowercase description, no ending period” and “Issue References … Suggest adding appropriate GitHub keywords.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/HDRDisplay.cpp` at line 1, The PR title scope should use
lowercase per Conventional Commit rules; rename the PR title from something like
"fix(HDRDisplay): ..." to "fix(hdr): reduce false display detections" and update
the PR description to include an issue reference using GitHub keywords (e.g.,
"Fixes #<issue>" or "Related to #<issue>"); also ensure any commit messages
touching HDRDisplay.cpp / HDRDisplay.h follow the same lowercase scope
convention.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 137-143: The EnumOutputs loop in HDRDisplay.cpp currently only
checks for DXGI_ERROR_NOT_FOUND and then unconditionally calls out->GetDesc(),
which can dereference a null com_ptr on other failures; change the
adapter->EnumOutputs handling to capture the HRESULT (e.g., hr =
adapter->EnumOutputs(oi, out.put())), then: if hr == DXGI_ERROR_NOT_FOUND break
the loop; if FAILED(hr) continue (or log and continue) so you never call
out->GetDesc() when EnumOutputs failed; then call out->GetDesc(&outDesc) only
when EnumOutputs succeeded and out is valid.

---

Nitpick comments:
In `@src/Features/HDRDisplay.cpp`:
- Line 1: The PR title scope should use lowercase per Conventional Commit rules;
rename the PR title from something like "fix(HDRDisplay): ..." to "fix(hdr):
reduce false display detections" and update the PR description to include an
issue reference using GitHub keywords (e.g., "Fixes #<issue>" or "Related to
#<issue>"); also ensure any commit messages touching HDRDisplay.cpp /
HDRDisplay.h follow the same lowercase scope convention.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 289a4060-741c-4930-ae12-b99eaeb5e584

📥 Commits

Reviewing files that changed from the base of the PR and between 869486d and 692c3de.

📒 Files selected for processing (1)
  • src/Features/HDRDisplay.cpp

Comment thread src/Features/HDRDisplay.cpp
@SkrubbySkrubInAShrub
Copy link
Copy Markdown
Collaborator Author

@coderabbitai resume

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

✅ Actions performed

Reviews resumed.

@SkrubbySkrubInAShrub
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/Features/HDRDisplay.cpp (1)

137-143: ⚠️ Potential issue | 🟠 Major

Break on EnumOutputs failures to prevent unbounded loop during HDR detection.

When EnumOutputs returns a persistent failure like DXGI_ERROR_NOT_CURRENTLY_AVAILABLE (in Session 0 processes), the current code continues indefinitely, incrementing oi through the full UINT range. This can cause hangs during plugin initialization. Break on non-DXGI_ERROR_NOT_FOUND failures and log the error for debugging.

Proposed fix
 				for (UINT oi = 0;; ++oi) {
 					winrt::com_ptr<IDXGIOutput> out;
 					HRESULT hr = adapter->EnumOutputs(oi, out.put());
 					if (hr == DXGI_ERROR_NOT_FOUND)
 						break;
-					if (FAILED(hr))
-						continue;
+					if (FAILED(hr)) {
+						logger::warn("[HDR] DXGI fallback EnumOutputs failed at index {}: 0x{:08X}", oi, static_cast<std::uint32_t>(hr));
+						break;
+					}
 					DXGI_OUTPUT_DESC outDesc{};

PR metadata note: consider normalizing the title to fix(hdr): reduce false display detections and adding Fixes #... / Addresses #... if tracking a known issue.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/Features/HDRDisplay.cpp` around lines 137 - 143, In HDRDisplay.cpp inside
the loop using adapter->EnumOutputs(oi, out.put()) (the for loop that declares
UINT oi and winrt::com_ptr<IDXGIOutput> out), change behavior so that when
EnumOutputs returns a failure other than DXGI_ERROR_NOT_FOUND (e.g.,
DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) you break out of the loop instead of
continuing; also log the HRESULT error for debugging before breaking (use the
existing logging facility in this module). This prevents iterating oi to the
UINT wraparound on persistent EnumOutputs failures and keeps normal behavior of
breaking on DXGI_ERROR_NOT_FOUND.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 186-192: The legacy DisplayConfigGetDeviceInfo path currently sets
enabled = colorInfo.advancedColorEnabled != 0 unconditionally; change it to gate
HDR enablement on the swap-chain output color space like the DXGI fallback: keep
supported = colorInfo.advancedColorSupported != 0 but set enabled =
(colorInfo.advancedColorEnabled != 0) && (swapChainOutputColorSpace ==
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) (use the same variable/name used
elsewhere for the current output color space), and update the debug log to
reflect the gated result; reference DisplayConfigGetDeviceInfo,
colorInfo.advancedColorEnabled, enabled, supported, and
DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020.

---

Duplicate comments:
In `@src/Features/HDRDisplay.cpp`:
- Around line 137-143: In HDRDisplay.cpp inside the loop using
adapter->EnumOutputs(oi, out.put()) (the for loop that declares UINT oi and
winrt::com_ptr<IDXGIOutput> out), change behavior so that when EnumOutputs
returns a failure other than DXGI_ERROR_NOT_FOUND (e.g.,
DXGI_ERROR_NOT_CURRENTLY_AVAILABLE) you break out of the loop instead of
continuing; also log the HRESULT error for debugging before breaking (use the
existing logging facility in this module). This prevents iterating oi to the
UINT wraparound on persistent EnumOutputs failures and keeps normal behavior of
breaking on DXGI_ERROR_NOT_FOUND.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 374d96ac-5e61-4dab-a16e-805656d00642

📥 Commits

Reviewing files that changed from the base of the PR and between 692c3de and 25a8fd8.

📒 Files selected for processing (1)
  • src/Features/HDRDisplay.cpp

Comment thread src/Features/HDRDisplay.cpp
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 22, 2026

✅ A pre-release build is available for this PR:
Download

SkrubbySkrubInAShrub and others added 2 commits April 23, 2026 21:54
@SkrubbySkrubInAShrub
Copy link
Copy Markdown
Collaborator Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Automated formatting by clang-format, prettier, and other hooks.
See https://pre-commit.ci for details.
@alandtse alandtse merged commit 6d2ae4b into community-shaders:dev Apr 24, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants