Skip to content

Instantly share code, notes, and snippets.

@cshenton
Last active May 14, 2024 16:09
Show Gist options
  • Save cshenton/9ab478252e2da5ac83e575439fa29a0f to your computer and use it in GitHub Desktop.
Save cshenton/9ab478252e2da5ac83e575439fa29a0f to your computer and use it in GitHub Desktop.
D3D11 Triangle in C99
#include <assert.h>
#define COBJMACROS
#include <windows.h>
#include <d3d11_1.h>
#include <d3dcompiler.h>
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define TITLE "D3D11 Triangle C"
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main()
{
HRESULT hr;
WNDCLASSA wnd_class = { 0, DefWindowProcA, 0, 0, 0, 0, 0, 0, 0, TITLE };
RegisterClassA(&wnd_class);
DWORD style = WS_POPUP | WS_MAXIMIZE | WS_VISIBLE;
HWND window = CreateWindowExA(0, TITLE, TITLE, style, 0, 0, 0, 0, NULL, NULL, NULL, NULL);
assert(window);
//////////////////////////////////////////////////////////////////////////////////////////////////////
D3D_FEATURE_LEVEL feature_levels[] = { D3D_FEATURE_LEVEL_11_1 };
ID3D11Device* base_device;
ID3D11DeviceContext* base_ctx;
hr = D3D11CreateDevice(
NULL, D3D_DRIVER_TYPE_HARDWARE,
NULL, D3D11_CREATE_DEVICE_BGRA_SUPPORT,
feature_levels, ARRAYSIZE(feature_levels),
D3D11_SDK_VERSION, &base_device,
NULL, &base_ctx);
assert(SUCCEEDED(hr));
//////////////////////////////////////////////////////////////////////////////////////////////////////
ID3D11Device1* device;
hr = ID3D11Device_QueryInterface(base_device, &IID_ID3D11Device1, (void**)(&device));
assert(SUCCEEDED(hr));
ID3D11DeviceContext1* ctx;
hr = ID3D11DeviceContext_QueryInterface(base_ctx, &IID_ID3D11DeviceContext1, (void**)&ctx);
assert(SUCCEEDED(hr));
//////////////////////////////////////////////////////////////////////////////////////////////////////
IDXGIDevice1* dxgi_dev;
hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice1, (void**)&dxgi_dev);
assert(SUCCEEDED(hr));
IDXGIAdapter1* adapter;
hr = IDXGIDevice_GetParent(dxgi_dev, &IID_IDXGIAdapter1, (void**)&adapter);
assert(SUCCEEDED(hr));
IDXGIFactory2* factory;
hr = IDXGIAdapter1_GetParent(adapter, &IID_IDXGIFactory2, (void**)&factory);
assert(SUCCEEDED(hr));
//////////////////////////////////////////////////////////////////////////////////////////////////////
DXGI_SWAP_CHAIN_DESC1 swapchain_desc = {
.Format = DXGI_FORMAT_B8G8R8A8_UNORM,
.SampleDesc = {.Count = 1},
.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
.BufferCount = 2,
.Scaling = DXGI_SCALING_STRETCH,
.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD,
.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED,
};
IDXGISwapChain1* swapchain;
hr = IDXGIFactory2_CreateSwapChainForHwnd(factory, (IUnknown*)device, window,
&swapchain_desc, NULL, NULL, &swapchain);
assert(SUCCEEDED(hr));
//////////////////////////////////////////////////////////////////////////////////////////////////////
ID3D11Texture2D* framebuffer;
hr = IDXGISwapChain1_GetBuffer(swapchain, 0, &IID_ID3D11Texture2D, (void**)&framebuffer);
assert(SUCCEEDED(hr));
D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {
.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D,
};
ID3D11RenderTargetView* rtv;
hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource*)framebuffer, &rtv_desc, &rtv);
assert(SUCCEEDED(hr));
//////////////////////////////////////////////////////////////////////////////////////////////////////
D3D11_TEXTURE2D_DESC depth_tex_desc;
ID3D11Texture2D_GetDesc(framebuffer, &depth_tex_desc);
depth_tex_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depth_tex_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
ID3D11Texture2D* depth_tex;
hr = ID3D11Device_CreateTexture2D(device, &depth_tex_desc, NULL, &depth_tex);
assert(SUCCEEDED(hr));
ID3D11DepthStencilView* dsv;
ID3D11Device_CreateDepthStencilView(device, (ID3D11Resource*)depth_tex, NULL, &dsv);
//////////////////////////////////////////////////////////////////////////////////////////////////////
ID3DBlob* vert_src;
hr = D3DCompileFromFile(L"tri.hlsl", NULL, NULL, "vert", "vs_5_0", 0, 0, &vert_src, NULL);
assert(SUCCEEDED(hr));
ID3D11VertexShader* vert_shd;
hr = ID3D11Device_CreateVertexShader(
device,
ID3D10Blob_GetBufferPointer(vert_src),
ID3D10Blob_GetBufferSize(vert_src),
NULL,
&vert_shd);
assert(SUCCEEDED(hr));
//////////////////////////////////////////////////////////////////////////////////////////////////////
ID3DBlob* pix_src;
hr = D3DCompileFromFile(L"tri.hlsl", NULL, NULL, "pix", "ps_5_0", 0, 0, &pix_src, NULL);
assert(SUCCEEDED(hr));
ID3D11PixelShader* pix_shd;
hr = ID3D11Device_CreatePixelShader(device,
ID3D10Blob_GetBufferPointer(pix_src),
ID3D10Blob_GetBufferSize(pix_src),
NULL,
&pix_shd);
assert(SUCCEEDED(hr));
//////////////////////////////////////////////////////////////////////////////////////////////////////
D3D11_RASTERIZER_DESC rasterizer_desc = {
.FillMode = D3D11_FILL_SOLID,
.CullMode = D3D11_CULL_BACK,
};
ID3D11RasterizerState* raster_state;
hr = ID3D11Device_CreateRasterizerState(device, &rasterizer_desc, &raster_state);
assert(SUCCEEDED(hr));
//////////////////////////////////////////////////////////////////////////////////////////////////////
D3D11_DEPTH_STENCIL_DESC depth_stencil_desc = {
.DepthEnable = TRUE,
.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL,
.DepthFunc = D3D11_COMPARISON_LESS,
};
ID3D11DepthStencilState* depth_stencil_state;
ID3D11Device_CreateDepthStencilState(device, &depth_stencil_desc, &depth_stencil_state);
//////////////////////////////////////////////////////////////////////////////////////////////////////
float clear_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
float width = (float)depth_tex_desc.Width;
float height = (float)depth_tex_desc.Height;
D3D11_VIEWPORT viewport = { 0.0f, 0.0f, width, height, 0.0f, 1.0f };
//////////////////////////////////////////////////////////////////////////////////////////////////////
for (;;) {
MSG msg;
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) {
return 0;
}
DispatchMessageA(&msg);
}
ID3D11DeviceContext_ClearRenderTargetView(ctx, rtv, clear_color);
ID3D11DeviceContext_ClearDepthStencilView(ctx, dsv, D3D11_CLEAR_DEPTH, 1.0f, 0);
ID3D11DeviceContext_IASetPrimitiveTopology(ctx, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ID3D11DeviceContext_VSSetShader(ctx, vert_shd, NULL, 0);
ID3D11DeviceContext_RSSetViewports(ctx, 1, &viewport);
ID3D11DeviceContext_RSSetState(ctx, raster_state);
ID3D11DeviceContext_PSSetShader(ctx, pix_shd, NULL, 0);
ID3D11DeviceContext_OMSetRenderTargets(ctx, 1, &rtv, dsv);
ID3D11DeviceContext_OMSetDepthStencilState(ctx, depth_stencil_state, 0);
ID3D11DeviceContext_OMSetBlendState(ctx, NULL, NULL, 0xffffffff);
ID3D11DeviceContext_Draw(ctx, 3, 0);
IDXGISwapChain_Present(swapchain, 1, 0);
}
}
struct PixelData {
float4 position : SV_POSITION;
float4 color : COL;
};
PixelData vert(uint v: SV_VertexID)
{
float2 positions[3] = { float2(0.5, -0.5), float2(-0.5, -0.5), float2(0.0, 0.5) };
PixelData pd;
pd.color = float4(v==0, v==1, v==2, 1.0);
pd.position = float4(positions[v], 0.0, 1);
return pd;
}
float4 pix(PixelData pd) : SV_TARGET
{
return pd.color;
}
@cshenton
Copy link
Author

cshenton commented Mar 7, 2024

Roughly based on d7samurai's C++ examples, such as https://gist.github.com/d7samurai/1e9a1f1a366740f7d8a3a20397fcfa6b

@cshenton
Copy link
Author

cshenton commented Mar 7, 2024

Compiling: zig cc -o d3d11_triangle.exe d3d11_triangle.c -ld3d11 -ld3dcompiler_47

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