Skip to content

Commit fd45507

Browse files
committed
Merge commit 'db627230f9d565b3b6839a978582f872bcbacfd5'
2 parents e2fd45b + db62723 commit fd45507

File tree

5 files changed

+575
-0
lines changed

5 files changed

+575
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net10.0</TargetFramework>
6+
<Nullable>enable</Nullable>
7+
<IsAotCompatible>true</IsAotCompatible>
8+
<PublishAot>true</PublishAot>
9+
</PropertyGroup>
10+
11+
<ItemGroup>
12+
<PackageReference Include="Vortice.Direct2D1" Version="3.8.2" />
13+
<PackageReference Include="Vortice.Direct3D11" Version="3.8.2" />
14+
<PackageReference Include="Vortice.DirectComposition" Version="3.8.2" />
15+
<PackageReference Include="Vortice.DXGI" Version="3.8.2" />
16+
<PackageReference Include="Vortice.Win32" Version="2.3.0" />
17+
18+
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.257">
19+
<PrivateAssets>all</PrivateAssets>
20+
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
21+
</PackageReference>
22+
23+
<PackageReference Include="MicroCom.Runtime" Version="0.11.0" />
24+
25+
</ItemGroup>
26+
27+
<ItemGroup>
28+
<!-- By default, any projects supports Windows, Linux, MacOS platforms. -->
29+
<!-- To properly support analyzers, we need to re-set this value -->
30+
<!-- https://github.com/dotnet/sdk/blob/v8.0.403/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.SupportedPlatforms.props -->
31+
<SupportedPlatform Remove="@(SupportedPlatform)" />
32+
<SupportedPlatform Include="Windows" />
33+
</ItemGroup>
34+
35+
</Project>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<Solution>
2+
<Project Path="JecekelbereLaiwharhowhelli.csproj" />
3+
</Solution>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
EnumDisplayMonitors
2+
GetMonitorInfo
3+
MONITORINFOEXW
4+
EnumDisplaySettings
5+
GetDisplayConfigBufferSizes
6+
QueryDisplayConfig
7+
DisplayConfigGetDeviceInfo
8+
9+
RegisterClassEx
10+
GetModuleHandle
11+
LoadCursor
12+
IDC_ARROW
13+
CreateWindowEx
14+
CW_USEDEFAULT
15+
ShowWindow
16+
SHOW_WINDOW_CMD
17+
GetMessage
18+
TranslateMessage
19+
DispatchMessage
20+
DefWindowProc
21+
GetClientRect
22+
WM_PAINT
23+
GetWindowLong
24+
SetWindowLong
25+
NCCALCSIZE_PARAMS
26+
WaitForSingleObjectEx
27+
28+
ClientToScreen
29+
WM_POINTERUPDATE
30+
GetPointerDeviceRects
31+
GetPointerTouchInfo
32+
EnableMouseInPointer
33+
PeekMessage
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// See https://aka.ms/new-console-template for more information
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Diagnostics;
6+
using System.Drawing;
7+
using System.Linq;
8+
using System.Runtime.CompilerServices;
9+
using System.Runtime.InteropServices;
10+
using System.Runtime.Versioning;
11+
using System.Text;
12+
using System.Threading;
13+
14+
using Vortice.DCommon;
15+
using Vortice.Direct2D1;
16+
using Vortice.Direct3D;
17+
using Vortice.Direct3D11;
18+
using Vortice.DirectComposition;
19+
using Vortice.DXGI;
20+
using Vortice.Mathematics;
21+
using Vortice.Win32;
22+
23+
using Windows.Win32;
24+
using Windows.Win32.Foundation;
25+
using Windows.Win32.Graphics.Gdi;
26+
using Windows.Win32.UI.Input.Pointer;
27+
using Windows.Win32.UI.WindowsAndMessaging;
28+
29+
using static Windows.Win32.PInvoke;
30+
31+
using AlphaMode = Vortice.DXGI.AlphaMode;
32+
using Color = Vortice.Mathematics.Color;
33+
using D2D = Vortice.Direct2D1;
34+
35+
namespace JecekelbereLaiwharhowhelli;
36+
37+
class Program
38+
{
39+
[STAThread]
40+
static unsafe void Main(string[] args)
41+
{
42+
HWND window;
43+
44+
#region 创建窗口
45+
46+
WINDOW_EX_STYLE exStyle = WINDOW_EX_STYLE.WS_EX_APPWINDOW;
47+
48+
var style = WNDCLASS_STYLES.CS_OWNDC | WNDCLASS_STYLES.CS_HREDRAW | WNDCLASS_STYLES.CS_VREDRAW;
49+
50+
var defaultCursor = LoadCursor(
51+
new HINSTANCE(IntPtr.Zero), new PCWSTR(IDC_ARROW.Value));
52+
var wndProcDelegate = new WNDPROC(WndProc);
53+
54+
var className = $"lindexi-{Guid.NewGuid().ToString()}";
55+
var title = "The Title";
56+
fixed (char* pClassName = className)
57+
fixed (char* pTitle = title)
58+
{
59+
var wndClassEx = new WNDCLASSEXW
60+
{
61+
cbSize = (uint) Marshal.SizeOf<WNDCLASSEXW>(),
62+
style = style,
63+
lpfnWndProc = wndProcDelegate,
64+
hInstance = new HINSTANCE(GetModuleHandle(null).DangerousGetHandle()),
65+
hCursor = defaultCursor,
66+
hbrBackground = new HBRUSH(IntPtr.Zero),
67+
lpszClassName = new PCWSTR(pClassName)
68+
};
69+
ushort atom = RegisterClassEx(in wndClassEx);
70+
71+
WINDOW_STYLE dwStyle = WINDOW_STYLE.WS_OVERLAPPEDWINDOW | WINDOW_STYLE.WS_VISIBLE | WINDOW_STYLE.WS_CAPTION | WINDOW_STYLE.WS_SYSMENU | WINDOW_STYLE.WS_MINIMIZEBOX | WINDOW_STYLE.WS_CLIPCHILDREN | WINDOW_STYLE.WS_BORDER | WINDOW_STYLE.WS_DLGFRAME | WINDOW_STYLE.WS_THICKFRAME | WINDOW_STYLE.WS_TABSTOP | WINDOW_STYLE.WS_SIZEBOX;
72+
73+
HWND windowHwnd = CreateWindowEx(
74+
exStyle,
75+
new PCWSTR((char*) atom),
76+
new PCWSTR(pTitle),
77+
dwStyle,
78+
0, 0, 1900, 1000,
79+
HWND.Null, HMENU.Null, HINSTANCE.Null, null);
80+
window = windowHwnd;
81+
}
82+
83+
// 防止委托对象被回收,导致注册进去的方法指针失效
84+
GC.KeepAlive(wndProcDelegate); // 保稳来说,这句话应该放在方法末尾
85+
86+
#endregion
87+
88+
// 显示窗口
89+
ShowWindow(window, SHOW_WINDOW_CMD.SW_NORMAL);
90+
91+
RECT windowRect;
92+
GetClientRect(window, &windowRect);
93+
GetClientRect(window, &windowRect);
94+
var clientSize = new SizeI(windowRect.right - windowRect.left, windowRect.bottom - windowRect.top);
95+
96+
#region 初始化 DX 相关
97+
98+
DeviceCreationFlags creationFlags = DeviceCreationFlags.BgraSupport;
99+
var result = D3D11.D3D11CreateDevice
100+
(
101+
null,
102+
DriverType.Hardware,
103+
creationFlags,
104+
null,
105+
out ID3D11Device? d3D11Device
106+
);
107+
108+
result.CheckError();
109+
Debug.Assert(d3D11Device != null);
110+
111+
// 缓存的数量,包括前缓存。大部分应用来说,至少需要两个缓存,这个玩过游戏的伙伴都知道
112+
const int FrameCount = 2;
113+
Format colorFormat = Format.B8G8R8A8_UNorm;
114+
SwapChainDescription1 swapChainDescription = new()
115+
{
116+
Width = (uint) clientSize.Width,
117+
Height = (uint) clientSize.Height,
118+
Format = colorFormat,
119+
BufferCount = FrameCount,
120+
BufferUsage = Usage.RenderTargetOutput,
121+
SampleDescription = SampleDescription.Default,
122+
Scaling = Scaling.Stretch,
123+
SwapEffect = SwapEffect.FlipSequential,
124+
AlphaMode = AlphaMode.Ignore,
125+
Flags = SwapChainFlags.None,
126+
};
127+
128+
var fullscreenDescription = new SwapChainFullscreenDescription()
129+
{
130+
Windowed = true,
131+
};
132+
133+
using var dxgiFactory2 = DXGI.CreateDXGIFactory1<IDXGIFactory2>();
134+
using IDXGISwapChain1 swapChain =
135+
dxgiFactory2.CreateSwapChainForHwnd(d3D11Device, window, swapChainDescription, fullscreenDescription);
136+
137+
// 不要被按下 alt+enter 进入全屏
138+
dxgiFactory2.MakeWindowAssociation(window,
139+
WindowAssociationFlags.IgnoreAltEnter | WindowAssociationFlags.IgnorePrintScreen);
140+
#endregion
141+
142+
#region 对接 D2D 渲染
143+
144+
using var d3D11Texture2D = swapChain.GetBuffer<ID3D11Texture2D>(0);
145+
using var dxgiSurface = d3D11Texture2D.QueryInterface<IDXGISurface>();
146+
147+
var renderTargetProperties = new D2D.RenderTargetProperties()
148+
{
149+
PixelFormat = new PixelFormat(colorFormat, Vortice.DCommon.AlphaMode.Premultiplied),
150+
Type = D2D.RenderTargetType.Hardware,
151+
};
152+
153+
using D2D.ID2D1Factory1 d2DFactory = D2D.D2D1.D2D1CreateFactory<D2D.ID2D1Factory1>();
154+
D2D.ID2D1RenderTarget d2D1RenderTarget =
155+
d2DFactory.CreateDxgiSurfaceRenderTarget(dxgiSurface, renderTargetProperties);
156+
D2D.ID2D1RenderTarget renderTarget = d2D1RenderTarget;
157+
#endregion
158+
159+
var maxCount = 100;
160+
var stepTimeList = new List<TimeSpan>();
161+
var stopwatch = new Stopwatch();
162+
163+
while (true)
164+
{
165+
renderTarget.BeginDraw();
166+
167+
renderTarget.Clear(new Color4((uint) Random.Shared.Next()));
168+
169+
renderTarget.EndDraw();
170+
171+
stopwatch.Restart();
172+
swapChain.Present(1, 0);
173+
stopwatch.Stop();
174+
175+
if (stepTimeList.Count < maxCount)
176+
{
177+
stepTimeList.Add(stopwatch.Elapsed);
178+
}
179+
else
180+
{
181+
var stringBuilder = new StringBuilder();
182+
183+
for (var i = 0; i < stepTimeList.Count; i++)
184+
{
185+
var timeSpan = stepTimeList[i];
186+
stringBuilder.AppendLine($"[{i:D3}] {timeSpan.TotalMilliseconds:0.000} ms");
187+
}
188+
189+
var costText = stringBuilder.ToString();
190+
Console.WriteLine(costText);
191+
192+
/*
193+
[000] 0.173 ms
194+
[001] 0.171 ms
195+
[002] 0.591 ms
196+
[003] 7.008 ms
197+
[004] 16.074 ms
198+
[005] 17.490 ms
199+
[006] 10.339 ms
200+
[007] 18.348 ms
201+
[008] 12.287 ms
202+
[009] 15.211 ms
203+
[010] 16.125 ms
204+
[011] 16.110 ms
205+
[012] 16.100 ms
206+
[013] 2.887 ms
207+
[014] 2.171 ms
208+
[015] 2.223 ms
209+
[016] 2.365 ms
210+
[017] 15.942 ms
211+
[018] 15.915 ms
212+
[019] 15.896 ms
213+
[020] 15.930 ms
214+
[021] 15.950 ms
215+
[022] 15.903 ms
216+
[023] 15.602 ms
217+
[024] 16.525 ms
218+
[025] 15.597 ms
219+
[026] 15.878 ms
220+
[027] 15.908 ms
221+
[028] 15.912 ms
222+
[029] 16.046 ms
223+
[030] 15.938 ms
224+
*/
225+
226+
Console.ReadLine();
227+
}
228+
229+
// 以下只是为了防止窗口无响应而已
230+
var success = PeekMessage(out var msg, HWND.Null, 0, 0, PEEK_MESSAGE_REMOVE_TYPE.PM_REMOVE);
231+
if (success)
232+
{
233+
// 处理窗口消息
234+
TranslateMessage(&msg);
235+
DispatchMessage(&msg);
236+
}
237+
}
238+
239+
Console.ReadLine();
240+
241+
LRESULT WndProc(HWND hwnd, uint message, WPARAM wParam, LPARAM lParam)
242+
{
243+
return DefWindowProc(hwnd, message, wParam, lParam);
244+
}
245+
}
246+
}

0 commit comments

Comments
 (0)