-
-
Notifications
You must be signed in to change notification settings - Fork 425
/
Copy pathProgram.cs
196 lines (162 loc) · 6.61 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
/////////////////////////////////////////////////////// PLEASE READ! ///////////////////////////////////////////////////
// This provides a basic example of using our Direct3D 11 bindings in their current form. These bindings are still //
// improving over time, and as a result the content of this example may change. //
// Notably: //
// TODO remove Unsafe.NullRef once we've updated the bindings to not require it //
// TODO investigate making the D3DPrimitiveTopology enum more user friendly //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
using System.Runtime.CompilerServices;
using ImGuiNET;
using Silk.NET.Core.Native;
using Silk.NET.Direct3D11;
using Silk.NET.DXGI;
using Silk.NET.Input;
using Silk.NET.Lab.Experiments.ImGuiDX11;
using Silk.NET.Maths;
using Silk.NET.Windowing;
float[] backgroundColour = [0.0f, 0.0f, 0.0f, 1.0f];
// Load the DXGI and Direct3D11 libraries for later use.
// Given this is not tied to the window, this doesn't need to be done in the OnLoad event.
DXGI dxgi = null!;
D3D11 d3d11 = null!;
// These variables are initialized within the Load event.
ComPtr<IDXGIFactory2> factory = default;
ComPtr<IDXGISwapChain1> swapchain = default;
ComPtr<ID3D11Device> device = default;
ComPtr<ID3D11DeviceContext> deviceContext = default;
ImGuiDX11Controller controller = null;
// Create a window.
WindowOptions options = WindowOptions.Default with
{
Size = new Vector2D<int>(800, 600),
Title = "Learn Direct3D11 with Silk.NET",
API = GraphicsAPI.None, // <-- This bit is important, as your window will be configured for OpenGL by default.
};
var window = Window.Create(options);
// Assign events.
window.Load += OnLoad;
window.Render += OnRender;
window.FramebufferResize += OnFramebufferResize;
// Run the window.
window.Run();
// Dispose of the ImGui context.
controller?.Dispose();
// Clean up any resources.
factory.Dispose();
swapchain.Dispose();
device.Dispose();
deviceContext.Dispose();
d3d11.Dispose();
dxgi.Dispose();
//dispose the window, and its internal resources
window.Dispose();
unsafe void OnLoad()
{
//Whether or not to force use of DXVK on platforms where native DirectX implementations are available
const bool forceDxvk = false;
dxgi = DXGI.GetApi(window, forceDxvk);
d3d11 = D3D11.GetApi(window, forceDxvk);
// Set-up input context.
var input = window.CreateInput();
foreach (var keyboard in input.Keyboards)
{
keyboard.KeyDown += OnKeyDown;
}
// Create our D3D11 logical device.
SilkMarshal.ThrowHResult
(
d3d11.CreateDevice
(
default(ComPtr<IDXGIAdapter>),
D3DDriverType.Hardware,
Software: default,
(uint) CreateDeviceFlag.Debug,
null,
0,
D3D11.SdkVersion,
ref device,
null,
ref deviceContext
)
);
//This is not supported under DXVK
//TODO: PR a stub into DXVK for this maybe?
if (OperatingSystem.IsWindows())
{
// Log debug messages for this device (given that we've enabled the debug flag). Don't do this in release code!
device.SetInfoQueueCallback(msg => Console.WriteLine(SilkMarshal.PtrToString((nint) msg.PDescription)));
}
// Create our swapchain.
var swapChainDesc = new SwapChainDesc1
{
BufferCount = 2, // double buffered
Format = Format.FormatB8G8R8A8Unorm,
BufferUsage = DXGI.UsageRenderTargetOutput,
SwapEffect = SwapEffect.FlipDiscard,
SampleDesc = new SampleDesc(1, 0)
};
// Create our DXGI factory to allow us to create a swapchain.
factory = dxgi.CreateDXGIFactory<IDXGIFactory2>();
// Create the swapchain.
SilkMarshal.ThrowHResult
(
factory.CreateSwapChainForHwnd
(
device,
window.Native!.DXHandle!.Value,
in swapChainDesc,
null,
ref Unsafe.NullRef<IDXGIOutput>(),
ref swapchain
)
);
// Init ImGui.
// This is where you can set a custom font for ImGui.
//ImGuiFontConfig fontConfig = new ImGuiFontConfig("C:\\Windows\\Fonts\\arial.ttf", 16, ptr => ptr.Fonts.GetGlyphRangesDefault());
controller = new ImGuiDX11Controller(device, deviceContext, window, input/*, fontConfig*/);
}
void OnFramebufferResize(Vector2D<int> newSize)
{
// If the window resizes, we need to be sure to update the swapchain's back buffers.
// Good starting point for this function:
// https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/d3d10-graphics-programming-guide-dxgi#handling-window-resizing
SilkMarshal.ThrowHResult
(
swapchain.ResizeBuffers(0, (uint) newSize.X, (uint) newSize.Y, Format.FormatB8G8R8A8Unorm, 0)
);
}
unsafe void OnRender(double deltaSeconds)
{
// Update the ImGui controller.
controller.Update((float)deltaSeconds);
// Obtain the framebuffer for the swapchain's backbuffer.
using ComPtr<ID3D11Texture2D> framebuffer = swapchain.GetBuffer<ID3D11Texture2D>(0);
// Create a view over the render target.
ComPtr<ID3D11RenderTargetView> renderTargetView = default;
SilkMarshal.ThrowHResult(device.CreateRenderTargetView(framebuffer, null, ref renderTargetView));
// Clear the render target to be all black ahead of rendering.
deviceContext.ClearRenderTargetView(renderTargetView, ref backgroundColour[0]);
// Update the rasterizer state with the current viewport.
Viewport viewport = new Viewport(0, 0, window.FramebufferSize.X, window.FramebufferSize.Y, 0, 1);
deviceContext.RSSetViewports(1, in viewport);
// Tell the output merger about our render target view.
deviceContext.OMSetRenderTargets(1, ref renderTargetView, ref Unsafe.NullRef<ID3D11DepthStencilView>());
// Show everything you want before calling ImGui.Render().
ImGui.ShowDemoWindow();
// Then render ImGui.
controller.Render();
// Present the drawn image.
swapchain.Present(1, 0);
// Clean up any resources created in this method.
renderTargetView.Dispose();
}
void OnKeyDown(IKeyboard keyboard, Key key, int scancode)
{
// Check to close the window on escape.
if (key == Key.Escape)
{
window.Close();
}
}