Skip to content

Instantly share code, notes, and snippets.

@smourier
Created July 29, 2024 05:39
Show Gist options
  • Save smourier/1a7cf9097c70f9ecfc706b9a3bbeece5 to your computer and use it in GitHub Desktop.
Save smourier/1a7cf9097c70f9ecfc706b9a3bbeece5 to your computer and use it in GitHub Desktop.
Create Window and Swapchain with CsWin32
using System;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Microsoft.Win32.SafeHandles;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.Graphics.Direct3D;
using Windows.Win32.Graphics.Direct3D11;
using Windows.Win32.Graphics.Dxgi;
using Windows.Win32.Graphics.Dxgi.Common;
using Windows.Win32.System.Com;
using Windows.Win32.UI.WindowsAndMessaging;
[assembly: SupportedOSPlatform("windows10.0.10240")]
namespace ConsoleApp5;
internal class Program
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate LRESULT WndProcDelegate(HWND hwnd, uint msg, WPARAM wp, LPARAM lp);
private static readonly WndProcDelegate _wndProc = WndProc;
static unsafe void Main()
{
ID3D11Device* device;
PInvoke.D3D11CreateDevice(
null,
D3D_DRIVER_TYPE.D3D_DRIVER_TYPE_HARDWARE,
HMODULE.Null,
D3D11_CREATE_DEVICE_FLAG.D3D11_CREATE_DEVICE_DEBUG,
null,
0,
7,
&device,
null,
null).ThrowOnFailure();
PInvoke.CreateDXGIFactory2(DXGI_CREATE_FACTORY_FLAGS.DXGI_CREATE_FACTORY_DEBUG, typeof(IDXGIFactory3).GUID, out var obj).ThrowOnFailure();
var fac = (IDXGIFactory3*)obj;
var clsName = "MyWindowClass";
var cls = new WNDCLASSW
{
lpfnWndProc = (delegate* unmanaged[Stdcall]<HWND, uint, WPARAM, LPARAM, LRESULT>)Marshal.GetFunctionPointerForDelegate(_wndProc)
};
fixed (char* n = clsName)
{
cls.lpszClassName = n;
}
PInvoke.RegisterClass(cls);
cls.hInstance = PInvoke.GetModuleHandle(new PCWSTR());
PInvoke.RegisterClass(cls);
var hwnd = PInvoke.CreateWindowEx(
0,
clsName,
"test",
WINDOW_STYLE.WS_OVERLAPPED,
0,
0,
100, 100,
HWND.Null,
null,
new SafeFileHandle(cls.hInstance.Value, false), // whatever handle
null);
IDXGISwapChain1* sw;
var desc = new DXGI_SWAP_CHAIN_DESC1()
{
BufferCount = 2,
Format = DXGI_FORMAT.DXGI_FORMAT_R8G8B8A8_UNORM,
BufferUsage = DXGI_USAGE.DXGI_USAGE_RENDER_TARGET_OUTPUT,
SwapEffect = DXGI_SWAP_EFFECT.DXGI_SWAP_EFFECT_FLIP_DISCARD,
Scaling = DXGI_SCALING.DXGI_SCALING_NONE,
Flags = DXGI_SWAP_CHAIN_FLAG.DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT,
SampleDesc = new DXGI_SAMPLE_DESC { Count = 1 },
};
fac->CreateSwapChainForHwnd((IUnknown*)device, hwnd, desc, null, null, &sw).ThrowOnFailure();
sw->QueryInterface(typeof(IDXGISwapChain3).GUID, out var ppvObject).ThrowOnFailure();
var sw3 = (IDXGISwapChain3*)ppvObject;
var h = sw3->GetFrameLatencyWaitableObject();
Console.WriteLine(h.Value);
sw->Release();
fac->Release();
device->Release();
}
static LRESULT WndProc(HWND hwnd, uint msg, WPARAM wp, LPARAM lp)
{
return PInvoke.DefWindowProc(hwnd, msg, wp, lp);
}
}
@smourier
Copy link
Author

With NativeMethods.txt:

IDXGISwapChain3
IDXGIFactory3
CreateDXGIFactory2
D3D11CreateDevice
CreateWindowExW
RegisterClassW
GetModuleHandleW
DefWindowProcW

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment