From 3d7df86a016d16663974389fdcc1f21683b87a38 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Thu, 13 Aug 2026 20:01:44 +1000 Subject: [PATCH] [idd] postprocess: centralize frame format utilities --- idd/LGIdd/LGIdd.vcxproj | 1 + idd/LGIdd/LGIdd.vcxproj.filters | 3 + idd/LGIdd/capture/CFrameProcessorUtil.cpp | 33 ----- idd/LGIdd/capture/CFrameProcessorUtil.h | 3 - idd/LGIdd/capture/CHardwareFrameProcessor.cpp | 3 +- idd/LGIdd/capture/CSoftwareFrameProcessor.cpp | 3 +- idd/LGIdd/capture/CSwapChainProcessor.cpp | 2 +- idd/LGIdd/postprocess/CPostProcessor.cpp | 17 +-- idd/LGIdd/postprocess/D12FrameFormat.cpp | 113 ++++++++++++++++++ idd/LGIdd/postprocess/D12FrameFormat.h | 27 +++++ .../postprocess/effect/CHDR16to10Effect.cpp | 9 +- 11 files changed, 150 insertions(+), 64 deletions(-) create mode 100644 idd/LGIdd/postprocess/D12FrameFormat.cpp diff --git a/idd/LGIdd/LGIdd.vcxproj b/idd/LGIdd/LGIdd.vcxproj index bec6dd07..010591c2 100644 --- a/idd/LGIdd/LGIdd.vcxproj +++ b/idd/LGIdd/LGIdd.vcxproj @@ -55,6 +55,7 @@ + diff --git a/idd/LGIdd/LGIdd.vcxproj.filters b/idd/LGIdd/LGIdd.vcxproj.filters index 8a83bf5c..32759f45 100644 --- a/idd/LGIdd/LGIdd.vcxproj.filters +++ b/idd/LGIdd/LGIdd.vcxproj.filters @@ -306,6 +306,9 @@ Post-processing + + Post-processing + Post-processing\Effects diff --git a/idd/LGIdd/capture/CFrameProcessorUtil.cpp b/idd/LGIdd/capture/CFrameProcessorUtil.cpp index fa1b8726..78614817 100644 --- a/idd/LGIdd/capture/CFrameProcessorUtil.cpp +++ b/idd/LGIdd/capture/CFrameProcessorUtil.cpp @@ -41,39 +41,6 @@ bool CFrameProcessorUtil::FrameMetadataChanged( previous.maxFrameAverageLightLevel != current.maxFrameAverageLightLevel)); } -FrameType CFrameProcessorUtil::GetFrameType(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_B8G8R8A8_UNORM : return FRAME_TYPE_BGRA; - case DXGI_FORMAT_R8G8B8A8_UNORM : return FRAME_TYPE_RGBA; - case DXGI_FORMAT_R10G10B10A2_UNORM : return FRAME_TYPE_RGBA10; - case DXGI_FORMAT_R16G16B16A16_FLOAT: return FRAME_TYPE_RGBA16F; - default : return FRAME_TYPE_INVALID; - } -} - -bool CFrameProcessorUtil::ResourceDescMatches( - const D3D12_RESOURCE_DESC& left, const D3D12_RESOURCE_DESC& right, - bool compareAlignment) -{ - // GetDesc may report a resolved alignment when resource creation requested - // automatic alignment, so callers comparing creation descriptors can omit - // this allocation metadata. - return - left.Dimension == right.Dimension && - (!compareAlignment || left.Alignment == right.Alignment) && - left.Width == right.Width && - left.Height == right.Height && - left.DepthOrArraySize == right.DepthOrArraySize && - left.MipLevels == right.MipLevels && - left.Format == right.Format && - left.SampleDesc.Count == right.SampleDesc.Count && - left.SampleDesc.Quality == right.SampleDesc.Quality && - left.Layout == right.Layout && - left.Flags == right.Flags; -} - static bool IsFullDamage(const RECT * dirtyRects, unsigned nbDirtyRects, unsigned width, unsigned height) { diff --git a/idd/LGIdd/capture/CFrameProcessorUtil.h b/idd/LGIdd/capture/CFrameProcessorUtil.h index eb740ac4..78d1a541 100644 --- a/idd/LGIdd/capture/CFrameProcessorUtil.h +++ b/idd/LGIdd/capture/CFrameProcessorUtil.h @@ -29,9 +29,6 @@ class CFrameProcessorUtil public: static bool FrameMetadataChanged(const D12FrameFormat& previous, const D12FrameFormat& current); - static FrameType GetFrameType(DXGI_FORMAT format); - static bool ResourceDescMatches(const D3D12_RESOURCE_DESC& left, - const D3D12_RESOURCE_DESC& right, bool compareAlignment = true); static void ClipDirtyRects(RECT dirtyRects[], unsigned * nbDirtyRects, unsigned width, unsigned height); static bool BuildCopyDamage(const CPostProcessor& postProcessor, diff --git a/idd/LGIdd/capture/CHardwareFrameProcessor.cpp b/idd/LGIdd/capture/CHardwareFrameProcessor.cpp index da30244f..9ea16f49 100644 --- a/idd/LGIdd/capture/CHardwareFrameProcessor.cpp +++ b/idd/LGIdd/capture/CHardwareFrameProcessor.cpp @@ -290,8 +290,7 @@ bool CHardwareFrameProcessor::EnsureCandidateResource( desc.Flags = D3D12_RESOURCE_FLAG_NONE; if (candidate.resource && - CFrameProcessorUtil::ResourceDescMatches( - candidate.resource->GetDesc(), desc, false)) + D12::Same(candidate.resource->GetDesc(), desc, D12::DescCmp::CREATE)) return true; candidate.resource.Reset(); diff --git a/idd/LGIdd/capture/CSoftwareFrameProcessor.cpp b/idd/LGIdd/capture/CSoftwareFrameProcessor.cpp index 2871561d..a4922956 100644 --- a/idd/LGIdd/capture/CSoftwareFrameProcessor.cpp +++ b/idd/LGIdd/capture/CSoftwareFrameProcessor.cpp @@ -263,8 +263,7 @@ bool CSoftwareFrameProcessor::EnsureProductResource( desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; if (product.resource && - CFrameProcessorUtil::ResourceDescMatches( - product.resource->GetDesc(), desc, false)) + D12::Same(product.resource->GetDesc(), desc, D12::DescCmp::CREATE)) return true; product.resource.Reset(); diff --git a/idd/LGIdd/capture/CSwapChainProcessor.cpp b/idd/LGIdd/capture/CSwapChainProcessor.cpp index b268af40..76ebee78 100644 --- a/idd/LGIdd/capture/CSwapChainProcessor.cpp +++ b/idd/LGIdd/capture/CSwapChainProcessor.cpp @@ -572,7 +572,7 @@ bool CSwapChainProcessor::SwapChainNewFrame(ComPtr acquiredBuffer srcFormat.desc = srcDesc; srcFormat.width = (unsigned)srcDesc.Width; srcFormat.height = srcDesc.Height; - srcFormat.format = CFrameProcessorUtil::GetFrameType(srcDesc.Format); + srcFormat.format = D12::Type(srcDesc.Format); srcFormat.sdrWhiteLevel = sdrWhiteLevel; srcFormat.colorTransform = m_control.GetColorTransform(); diff --git a/idd/LGIdd/postprocess/CPostProcessor.cpp b/idd/LGIdd/postprocess/CPostProcessor.cpp index 3bb359bc..135b9258 100644 --- a/idd/LGIdd/postprocess/CPostProcessor.cpp +++ b/idd/LGIdd/postprocess/CPostProcessor.cpp @@ -27,7 +27,6 @@ #include "postprocess/effect/CHDR16to10Effect.h" #include "postprocess/effect/CRGB24Effect.h" -#include #include #include @@ -71,18 +70,6 @@ bool IsIdentityColorTransform(const D12ColorTransform& transform) return true; } -static void CopyHDRMetadata(D12FrameFormat& dst, const D12FrameFormat& src) -{ - dst.hdrMetadata = src.hdrMetadata; - dst.sdrWhiteLevel = src.sdrWhiteLevel; - std::memcpy(dst.displayPrimary, src.displayPrimary, sizeof(dst.displayPrimary)); - std::memcpy(dst.whitePoint, src.whitePoint, sizeof(dst.whitePoint)); - dst.maxDisplayLuminance = src.maxDisplayLuminance; - dst.minDisplayLuminance = src.minDisplayLuminance; - dst.maxContentLightLevel = src.maxContentLightLevel; - dst.maxFrameAverageLightLevel = src.maxFrameAverageLightLevel; -} - bool CPostProcessor::Init(std::shared_ptr dx12Device, bool enableEffects) { @@ -213,8 +200,8 @@ bool CPostProcessor::Configure(const D12FrameFormat& srcFormat, { // Static HDR metadata may change independently of the resource format. // Propagate it without recreating resources or post-processing state. - CopyHDRMetadata(m_srcFormat, srcFormat); - CopyHDRMetadata(m_dstFormat, srcFormat); + D12::CopyHdr(m_srcFormat, srcFormat); + D12::CopyHdr(m_dstFormat, srcFormat); return true; } diff --git a/idd/LGIdd/postprocess/D12FrameFormat.cpp b/idd/LGIdd/postprocess/D12FrameFormat.cpp new file mode 100644 index 00000000..7172e031 --- /dev/null +++ b/idd/LGIdd/postprocess/D12FrameFormat.cpp @@ -0,0 +1,113 @@ +/** + * Looking Glass + * Copyright © 2017-2026 The Looking Glass Authors + * https://looking-glass.io + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "postprocess/D12FrameFormat.h" + +#include + +FrameType D12::Type(DXGI_FORMAT format) +{ + switch (format) + { + case DXGI_FORMAT_B8G8R8A8_UNORM: + return FRAME_TYPE_BGRA; + case DXGI_FORMAT_R8G8B8A8_UNORM: + return FRAME_TYPE_RGBA; + case DXGI_FORMAT_R10G10B10A2_UNORM: + return FRAME_TYPE_RGBA10; + case DXGI_FORMAT_R16G16B16A16_FLOAT: + return FRAME_TYPE_RGBA16F; + default: + return FRAME_TYPE_INVALID; + } +} + +void D12::CopyHdr(D12FrameFormat& dst, const D12FrameFormat& src) +{ + dst.hdrMetadata = src.hdrMetadata; + dst.sdrWhiteLevel = src.sdrWhiteLevel; + memcpy(dst.displayPrimary, src.displayPrimary, sizeof(dst.displayPrimary)); + memcpy(dst.whitePoint, src.whitePoint, sizeof(dst.whitePoint)); + dst.maxDisplayLuminance = src.maxDisplayLuminance; + dst.minDisplayLuminance = src.minDisplayLuminance; + dst.maxContentLightLevel = src.maxContentLightLevel; + dst.maxFrameAverageLightLevel = src.maxFrameAverageLightLevel; +} + +bool D12::Same(const D3D12_RESOURCE_DESC& left, + const D3D12_RESOURCE_DESC& right, DescCmp cmp) +{ + const bool alignment = cmp != DescCmp::CREATE && + cmp != DescCmp::COPY && cmp != DescCmp::VIEW; + const bool layout = cmp != DescCmp::COPY; + const bool flags = cmp != DescCmp::COPY && + cmp != DescCmp::NO_FLAGS && cmp != DescCmp::VIEW; + return + left.Dimension == right.Dimension && + (!alignment || left.Alignment == right.Alignment) && + left.Width == right.Width && + left.Height == right.Height && + left.DepthOrArraySize == right.DepthOrArraySize && + left.MipLevels == right.MipLevels && + left.Format == right.Format && + left.SampleDesc.Count == right.SampleDesc.Count && + left.SampleDesc.Quality == right.SampleDesc.Quality && + (!layout || left.Layout == right.Layout) && + (!flags || left.Flags == right.Flags); +} + +bool D12::Same(const D12FrameFormat& left, const D12FrameFormat& right, + FormatCmp cmp) +{ + const DescCmp descCmp = cmp == FormatCmp::IMAGE ? DescCmp::CREATE : + (cmp == FormatCmp::NO_FLAGS ? DescCmp::NO_FLAGS : DescCmp::EXACT); + if (!Same(left.desc, right.desc, descCmp)) + return false; + + if (cmp == FormatCmp::IMAGE) + return + left.width == right.width && + left.height == right.height && + left.format == right.format && + left.hdr == right.hdr && + left.hdrPQ == right.hdrPQ; + + return + left.dataWidth == right.dataWidth && + left.dataHeight == right.dataHeight && + left.pitch == right.pitch && + left.width == right.width && + left.height == right.height && + left.format == right.format && + left.hdr == right.hdr && + left.hdrPQ == right.hdrPQ && + left.hdrMetadata == right.hdrMetadata && + left.sdrWhiteLevel == right.sdrWhiteLevel && + left.colorTransform == right.colorTransform && + memcmp(left.displayPrimary, right.displayPrimary, + sizeof(left.displayPrimary)) == 0 && + memcmp(left.whitePoint, right.whitePoint, + sizeof(left.whitePoint)) == 0 && + + left.maxDisplayLuminance == right.maxDisplayLuminance && + left.minDisplayLuminance == right.minDisplayLuminance && + left.maxContentLightLevel == right.maxContentLightLevel && + left.maxFrameAverageLightLevel == right.maxFrameAverageLightLevel; +} diff --git a/idd/LGIdd/postprocess/D12FrameFormat.h b/idd/LGIdd/postprocess/D12FrameFormat.h index 0f5b2bb9..942d1551 100644 --- a/idd/LGIdd/postprocess/D12FrameFormat.h +++ b/idd/LGIdd/postprocess/D12FrameFormat.h @@ -68,3 +68,30 @@ struct D12FrameFormat uint32_t maxContentLightLevel; uint32_t maxFrameAverageLightLevel; }; + +namespace D12 +{ + enum class DescCmp : uint8_t + { + EXACT, + CREATE, + COPY, + NO_FLAGS, + VIEW, + }; + + enum class FormatCmp : uint8_t + { + EXACT, + IMAGE, + NO_FLAGS, + }; + + FrameType Type(DXGI_FORMAT format); + void CopyHdr(D12FrameFormat& dst, const D12FrameFormat& src); + bool Same(const D3D12_RESOURCE_DESC& left, + const D3D12_RESOURCE_DESC& right, + DescCmp cmp = DescCmp::EXACT); + bool Same(const D12FrameFormat& left, const D12FrameFormat& right, + FormatCmp cmp = FormatCmp::EXACT); +} diff --git a/idd/LGIdd/postprocess/effect/CHDR16to10Effect.cpp b/idd/LGIdd/postprocess/effect/CHDR16to10Effect.cpp index 3a0f60cd..d425b34c 100644 --- a/idd/LGIdd/postprocess/effect/CHDR16to10Effect.cpp +++ b/idd/LGIdd/postprocess/effect/CHDR16to10Effect.cpp @@ -134,14 +134,7 @@ PostProcessStatus CHDR16to10Effect::SetFormat( // Gamut conversion changes the signal's container primaries to BT.2020, but // does not change the mastering display chromaticities described by ST 2086. - dst.hdrMetadata = src.hdrMetadata; - memcpy(dst.displayPrimary, src.displayPrimary, sizeof(dst.displayPrimary)); - memcpy(dst.whitePoint , src.whitePoint , sizeof(dst.whitePoint )); - dst.maxDisplayLuminance = src.maxDisplayLuminance; - dst.minDisplayLuminance = src.minDisplayLuminance; - dst.maxContentLightLevel = src.maxContentLightLevel; - dst.maxFrameAverageLightLevel = src.maxFrameAverageLightLevel; - dst.sdrWhiteLevel = src.sdrWhiteLevel; + D12::CopyHdr(dst, src); return PostProcessStatus::SUCCESS; }