Skip to content

Instantly share code, notes, and snippets.

@mlarouche
Created April 14, 2020 20:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mlarouche/a495c8ba13437c339cc6abee2696c4aa to your computer and use it in GitHub Desktop.
Save mlarouche/a495c8ba13437c339cc6abee2696c4aa to your computer and use it in GitHub Desktop.
Direct3D sample usage in one of my projects
const DxContext = struct {
device: ?*dx.ID3D11Device = null,
deviceContext: ?*dx.ID3D11DeviceContext = null,
swapChain: ?*dx.IDXGISwapChain = null,
mainRenderTargetView: ?*dx.ID3D11RenderTargetView = null,
};
var dxContext: DxContext = undefined;
fn comFindReturnType(comptime vTableType: type, comptime name: []const u8) type {
for (@typeInfo(vTableType).Struct.fields) |field| {
if (std.mem.eql(u8, field.name, name)) {
const funcType = @typeInfo(@typeInfo(field.field_type).Optional.child);
return funcType.Fn.return_type.?;
}
}
return void;
}
fn comFindVtableType(comptime parentType: type) type {
switch (@typeInfo(parentType)) {
.Struct => |structInfo| {
for (structInfo.fields) |field| {
if (std.mem.eql(u8, field.name, "lpVtbl")) {
return @typeInfo(field.field_type).Pointer.child;
}
}
},
.Pointer => |pointerInfo| {
for (@typeInfo(pointerInfo.child).Struct.fields) |field| {
if (std.mem.eql(u8, field.name, "lpVtbl")) {
return @typeInfo(field.field_type).Pointer.child;
}
}
},
else => {},
}
return void;
}
fn comCall(self: var, comptime name: []const u8, args: var) comFindReturnType(comFindVtableType(@TypeOf(self)), name) {
if (@field(self.lpVtbl[0], name)) |func| {
return @call(.{}, func, .{self} ++ args);
}
return undefined;
}
fn createDeviceD3D(hWnd: win32.HWND) bool {
var sd = std.mem.zeroes(dx.DXGI_SWAP_CHAIN_DESC);
sd.BufferCount = 2;
sd.BufferDesc.Width = 0;
sd.BufferDesc.Height = 0;
sd.BufferDesc.Format = ._R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.Flags = dx.DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
sd.BufferUsage = dx.DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = @ptrCast(dx.HWND, hWnd);
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = win32.TRUE;
sd.SwapEffect = ._DISCARD;
var createDeviceFlags: win32.UINT = 0;
var featureLevel: dx.D3D_FEATURE_LEVEL = undefined;
const featureLevelArray = &[_]dx.D3D_FEATURE_LEVEL{
._11_0,
._10_0,
};
if (dx.D3D11CreateDeviceAndSwapChain(null, ._HARDWARE, null, createDeviceFlags, featureLevelArray, 2, dx.D3D11_SDK_VERSION, &sd, &dxContext.swapChain, &dxContext.device, &featureLevel, &dxContext.deviceContext) != dx.S_OK)
return false;
createRenderTarget();
return true;
}
fn createRenderTarget() void {
var pBackBuffer: ?*dx.ID3D11Texture2D = null;
if (dxContext.swapChain) |swapChain| {
_ = comCall(swapChain, "GetBuffer", .{ 0, &dx.IID_ID3D11Texture2D, @ptrCast([*c]?*c_void, &pBackBuffer) });
}
if (dxContext.device) |device| {
_ = comCall(device, "CreateRenderTargetView", .{ @ptrCast([*c]dx.struct_ID3D11Resource, pBackBuffer), null, @ptrCast([*c][*c]dx.struct_ID3D11RenderTargetView, &dxContext.mainRenderTargetView) });
}
if (pBackBuffer) |backBuffer| {
_ = comCall(backBuffer, "Release", .{});
}
}
fn cleanupDeviceD3D() void {
cleanupRenderTarget();
if (dxContext.swapChain) |swapChain| {
_ = comCall(swapChain, "Release", .{});
}
if (dxContext.deviceContext) |deviceContext| {
_ = comCall(deviceContext, "Release", .{});
}
if (dxContext.device) |device| {
_ = comCall(device, "Release", .{});
}
}
fn cleanupRenderTarget() void {
if (dxContext.mainRenderTargetView) |mainRenderTargetView| {
_ = comCall(mainRenderTargetView, "Release", .{});
dxContext.mainRenderTargetView = null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment