Skip to content

Commit 54e3680

Browse files
committed
perf: 特定情况下检查重复帧不执行边界检查
1 parent 7e685c0 commit 54e3680

File tree

7 files changed

+56
-5
lines changed

7 files changed

+56
-5
lines changed

src/Magpie.Core/DuplicateFrameChecker.cpp

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "Logger.h"
55
#include "ScalingWindow.h"
66
#include "shaders/DuplicateFrameCS.h"
7+
#include "shaders/DuplicateFrameCS_NoBoundsChecking.h"
78

89
namespace Magpie {
910

@@ -18,12 +19,16 @@ DuplicateFrameChecker::DuplicateFrameChecker() noexcept :
1819
// 1. D3D11 支持 IDXGIDevice::SetGPUThreadPriority,可以提高 GPU 优先级,
1920
// 而 D3D12 没有等价接口。
2021
// 2. 对于小任务 D3D11 启动渲染的耗时比 D3D12 短,差距可以达到 50us 以上。
22+
//
23+
// 对于不支持脏矩形且捕获帧右下两边没有多余像素的捕获方式,可以禁用边界检查获得
24+
// 性能提升。
2125
bool DuplicateFrameChecker::Initialize(
2226
ID3D11Device5* d3d11Device,
2327
ID3D11DeviceContext4* d3d11DC,
2428
const ColorInfo& colorInfo,
2529
Size frameSize,
26-
uint32_t frameCount
30+
uint32_t frameCount,
31+
bool disableBoundsChecking
2732
) noexcept {
2833
assert(ScalingWindow::Get().Options().duplicateFrameDetectionMode !=
2934
DuplicateFrameDetectionMode::Never);
@@ -32,11 +37,18 @@ bool DuplicateFrameChecker::Initialize(
3237
_deviceContext = d3d11DC;
3338
_isScRGB = colorInfo.kind != winrt::AdvancedColorKind::StandardDynamicRange;
3439
_frameSize = frameSize;
40+
#ifdef _DEBUG
41+
_isBoundsCheckingDisabled = disableBoundsChecking;
42+
#endif
3543

3644
_frameSrvs.resize(frameCount);
3745

3846
HRESULT hr = d3d11Device->CreateComputeShader(
39-
DuplicateFrameCS, sizeof(DuplicateFrameCS), nullptr, _dupFrameCS.put());
47+
disableBoundsChecking ? DuplicateFrameCS_NoBoundsChecking : DuplicateFrameCS,
48+
disableBoundsChecking ? sizeof(DuplicateFrameCS_NoBoundsChecking) : sizeof(DuplicateFrameCS),
49+
nullptr,
50+
_dupFrameCS.put()
51+
);
4052
if (FAILED(hr)) {
4153
Logger::Get().ComError("CreateComputeShader 失败", hr);
4254
return false;
@@ -134,6 +146,13 @@ HRESULT DuplicateFrameChecker::CheckFrame(
134146
D3D11_TEXTURE2D_DESC desc;
135147
frameResource->GetDesc(&desc);
136148
assert(desc.Width == _frameSize.width && desc.Height == _frameSize.height);
149+
150+
if (_isBoundsCheckingDisabled) {
151+
// 确保捕获帧右下两边没有多余像素
152+
for (const Rect& rect : dirtyRects) {
153+
assert(rect.right == desc.Width && rect.bottom == desc.Height);
154+
}
155+
}
137156
}
138157
#endif
139158

src/Magpie.Core/DuplicateFrameChecker.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ class DuplicateFrameChecker {
1616
ID3D11DeviceContext4* d3d11DC,
1717
const ColorInfo& colorInfo,
1818
Size frameSize,
19-
uint32_t frameCount
19+
uint32_t frameCount,
20+
bool disableBoundsChecking
2021
) noexcept;
2122

2223
HRESULT CheckFrame(ID3D11Texture2D* frameResource, uint32_t frameIdx, SmallVectorImpl<Rect>& dirtyRects) noexcept;
@@ -49,6 +50,9 @@ class DuplicateFrameChecker {
4950
uint16_t _framesLeft;
5051

5152
bool _isScRGB = false;
53+
#ifdef _DEBUG
54+
bool _isBoundsCheckingDisabled = false;
55+
#endif
5256
bool _isCheckingForDuplicateFrame = true;
5357
};
5458

src/Magpie.Core/GraphicsCaptureFrameSource.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,9 @@ bool GraphicsCaptureFrameSource::Initialize(
261261

262262
if (options.duplicateFrameDetectionMode != DuplicateFrameDetectionMode::Never) {
263263
_duplicateFrameChecker = std::make_unique<DuplicateFrameChecker>();
264+
// 不使用脏区域时可以跳过边界检查,因为捕获帧右下两边没有多余像素
264265
if (!_duplicateFrameChecker->Initialize(_d3d11Device.get(), _d3d11DC.get(),
265-
colorInfo, Size{ _frameBox.right, _frameBox.bottom }, frameCount)) {
266+
colorInfo, Size{ _frameBox.right, _frameBox.bottom }, frameCount, !_isDirtyRegionSupported)) {
266267
Logger::Get().Error("DuplicateFrameChecker::Initialize 失败");
267268
return false;
268269
}
@@ -1153,7 +1154,7 @@ HRESULT GraphicsCaptureFrameSource::_StartCapture() noexcept {
11531154
assert(!_captureFramePool && !_captureSession);
11541155

11551156
try {
1156-
// 创建帧缓冲池。帧的尺寸为包含源窗口的最小尺寸
1157+
// 创建帧缓冲池。帧的尺寸为包含捕获区域的最小尺寸,既能降低显存压力,又使得检查重复帧时无需边界检查
11571158
_captureFramePool = winrt::Direct3D11CaptureFramePool::CreateFreeThreaded(
11581159
_wrappedDevice,
11591160
_isScRGB ? winrt::DirectXPixelFormat::R16G16B16A16Float : winrt::DirectXPixelFormat::B8G8R8A8UIntNormalized,

src/Magpie.Core/Magpie.Core.vcxproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@
156156
<FxCompile Include="shaders\DuplicateFrameCS.hlsl">
157157
<ShaderType>Compute</ShaderType>
158158
</FxCompile>
159+
<FxCompile Include="shaders\DuplicateFrameCS_NoBoundsChecking.hlsl">
160+
<ShaderType>Compute</ShaderType>
161+
</FxCompile>
159162
<FxCompile Include="shaders\ImGuiImplPS.hlsl">
160163
<ShaderType>Pixel</ShaderType>
161164
</FxCompile>

src/Magpie.Core/Magpie.Core.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@
309309
<FxCompile Include="CatmullRomCS_sRGB.hlsl">
310310
<Filter>Shaders</Filter>
311311
</FxCompile>
312+
<FxCompile Include="shaders\DuplicateFrameCS_NoBoundsChecking.hlsl">
313+
<Filter>Shaders</Filter>
314+
</FxCompile>
312315
</ItemGroup>
313316
<ItemGroup>
314317
<None Include="packages.config" />

src/Magpie.Core/shaders/DuplicateFrameCS.hlsl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,30 @@ void main(uint3 tid : SV_GroupThreadID, uint3 gid : SV_GroupID) {
2020
}
2121

2222
const uint2 gxy = dirtyRect.xy + (gid.xy << 4) + (tid.xy << 1);
23+
24+
#ifndef MP_NO_BOUNDS_CHECKING
2325
if (gxy.x >= dirtyRect.z || gxy.y >= dirtyRect.w) {
2426
return;
2527
}
28+
#endif
2629

2730
const float2 pos = (gxy + 1) * texPt;
31+
32+
#ifdef MP_NO_BOUNDS_CHECKING
33+
if (any(tex1.GatherRed(sam, pos) != tex2.GatherRed(sam, pos))) {
34+
result[resultOffset] = target;
35+
return;
36+
}
37+
38+
if (any(tex1.GatherGreen(sam, pos) != tex2.GatherGreen(sam, pos))) {
39+
result[resultOffset] = target;
40+
return;
41+
}
2842

43+
if (any(tex1.GatherBlue(sam, pos) != tex2.GatherBlue(sam, pos))) {
44+
result[resultOffset] = target;
45+
}
46+
#else
2947
// w z
3048
// x y
3149
float4 mask = 1.0f;
@@ -57,4 +75,5 @@ void main(uint3 tid : SV_GroupThreadID, uint3 gid : SV_GroupID) {
5775
result[resultOffset] = target;
5876
return;
5977
}
78+
#endif
6079
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#define MP_NO_BOUNDS_CHECKING
2+
#include "DuplicateFrameCS.hlsl"

0 commit comments

Comments
 (0)