Last active
November 29, 2020 11:21
-
-
Save kayru/1537161 to your computer and use it in GitHub Desktop.
D3D11 Boilerplate code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// clang main.cpp | |
#include <tchar.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <windows.h> | |
#include <D3D11.h> | |
#include <D3Dcompiler.h> | |
#pragma comment(lib, "d3d11.lib") | |
#pragma comment(lib, "d3dcompiler.lib") | |
#pragma comment(lib, "dxguid.lib") | |
#pragma comment(lib, "dxgi.lib") | |
#pragma comment(lib, "user32.lib") | |
#pragma comment(lib, "gdi32.lib") | |
static const uint32_t WindowWidth = 1280; | |
static const uint32_t WindowHeight = 720; | |
static const char* WindowName = "Boilerplate D3D11 App"; | |
#define CHECKHR(hr) { if(FAILED(hr)){ printf("D3D Error: 0x%08x\n", (int)hr); DebugBreak();}} | |
struct Context | |
{ | |
HWND hwnd; | |
bool finished; | |
ID3D11Device* device; | |
ID3D11DeviceContext* device_context; | |
IDXGISwapChain* swap_chain; | |
ID3D11Texture2D* backbuffer_tex; | |
ID3D11RenderTargetView* backbuffer_view; | |
ID3D11Texture2D* depthstencil_tex; | |
ID3D11DepthStencilView* depthstencil_view; | |
}; | |
template <typename T> | |
inline void safe_release(T& x) | |
{ | |
if(x) | |
{ | |
x->Release(); | |
x=NULL; | |
} | |
} | |
LRESULT APIENTRY wnd_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) | |
{ | |
Context* ctx = reinterpret_cast<Context*>(GetWindowLongPtr(hwnd, GWLP_USERDATA)); | |
switch(msg) | |
{ | |
case WM_CLOSE: | |
ctx->finished = true; | |
default: | |
return (LONG)DefWindowProc(hwnd, msg, wparam, lparam); | |
} | |
} | |
Context* Init() | |
{ | |
Context* ctx = new Context; | |
ZeroMemory(ctx, sizeof(*ctx)); | |
ctx->finished = false; | |
// register window class | |
WNDCLASSEX wc = {0}; | |
HINSTANCE hInst = GetModuleHandle(NULL); | |
wc.cbSize = sizeof(WNDCLASSEX); | |
wc.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW |CS_VREDRAW; | |
wc.lpfnWndProc = wnd_proc; | |
wc.cbClsExtra = 0; | |
wc.cbWndExtra = 0; | |
wc.hInstance = hInst; | |
wc.hIcon = LoadIcon (NULL, IDI_APPLICATION); | |
wc.hCursor = LoadCursor (NULL, IDC_ARROW); | |
wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); | |
wc.lpszMenuName = NULL; | |
wc.lpszClassName = _T("BoilerplateWindowClass"); | |
wc.hIconSm = wc.hIcon; | |
RegisterClassEx(&wc); | |
uint32_t window_style = WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; | |
// find screen center and create our window there | |
int32_t pos_x = GetSystemMetrics(SM_CXSCREEN) / 2 - WindowWidth/2; | |
int32_t pos_y = GetSystemMetrics(SM_CYSCREEN) / 2 - WindowHeight/2; | |
// calculate window size for required client area | |
RECT client_rect = { pos_x, pos_y, LONG(pos_x+WindowWidth), LONG(pos_y+WindowHeight)}; | |
AdjustWindowRect(&client_rect, window_style, FALSE); | |
// create window | |
ctx->hwnd = CreateWindowA("BoilerplateWindowClass", WindowName, window_style, | |
client_rect.left, client_rect.top, | |
client_rect.right-client_rect.left, client_rect.bottom-client_rect.top, | |
NULL, NULL, hInst, NULL); | |
// setup window owner for message handling | |
SetWindowLongPtr(ctx->hwnd, GWLP_USERDATA, (LONG_PTR)ctx); | |
ShowWindow(ctx->hwnd, SW_SHOWNORMAL); | |
UpdateWindow(ctx->hwnd); | |
// Create D3D11 | |
DXGI_SWAP_CHAIN_DESC sd; | |
ZeroMemory( &sd, sizeof( sd ) ); | |
sd.BufferCount = 1; | |
sd.BufferDesc.Width = WindowWidth; | |
sd.BufferDesc.Height = WindowHeight; | |
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; | |
sd.BufferDesc.RefreshRate.Numerator = 60; | |
sd.BufferDesc.RefreshRate.Denominator = 1; | |
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; | |
sd.OutputWindow = ctx->hwnd; | |
sd.SampleDesc.Count = 1; | |
sd.SampleDesc.Quality = 0; | |
sd.Windowed = TRUE; | |
uint32_t flags = D3D11_CREATE_DEVICE_SINGLETHREADED; | |
D3D_DRIVER_TYPE type = D3D_DRIVER_TYPE_HARDWARE; | |
IDXGIAdapter* adapter = NULL; | |
IDXGIAdapter* enumerated_adapter = NULL; | |
IDXGIFactory* factory = NULL; | |
CHECKHR(CreateDXGIFactory(__uuidof(IDXGIFactory),(void**)&factory)); | |
for( uint32_t i=0; factory->EnumAdapters(i,&enumerated_adapter) != DXGI_ERROR_NOT_FOUND; ++i ) | |
{ | |
DXGI_ADAPTER_DESC adapter_desc; | |
if(enumerated_adapter->GetDesc(&adapter_desc) != S_OK) | |
{ | |
continue; | |
} | |
if(wcsstr(adapter_desc.Description,L"PerfHUD") != 0) | |
{ | |
type = D3D_DRIVER_TYPE_REFERENCE; | |
adapter = enumerated_adapter; | |
break; | |
} | |
} | |
safe_release(factory); | |
D3D_FEATURE_LEVEL features[] = | |
{ | |
D3D_FEATURE_LEVEL_11_0 | |
}; | |
const uint32_t num_features = sizeof(features) / sizeof(features[0]); | |
// Create device | |
D3D_FEATURE_LEVEL supported_features; | |
CHECKHR(D3D11CreateDeviceAndSwapChain(adapter, type, NULL, flags, features, num_features, | |
D3D11_SDK_VERSION, &sd, &ctx->swap_chain, &ctx->device, | |
&supported_features, &ctx->device_context)); | |
// Get default back buffer | |
CHECKHR(ctx->swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&ctx->backbuffer_tex)); | |
CHECKHR(ctx->device->CreateRenderTargetView(ctx->backbuffer_tex, NULL, &ctx->backbuffer_view)); | |
// Create default depth buffer | |
// create depth stencil | |
D3D11_TEXTURE2D_DESC depth_stencil_desc; | |
depth_stencil_desc.Width = WindowWidth; | |
depth_stencil_desc.Height = WindowHeight; | |
depth_stencil_desc.MipLevels = 1; | |
depth_stencil_desc.ArraySize = 1; | |
depth_stencil_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; | |
depth_stencil_desc.SampleDesc.Count = 1; | |
depth_stencil_desc.SampleDesc.Quality = 0; | |
depth_stencil_desc.Usage = D3D11_USAGE_DEFAULT; | |
depth_stencil_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; | |
depth_stencil_desc.CPUAccessFlags = 0; | |
depth_stencil_desc.MiscFlags = 0; | |
CHECKHR(ctx->device->CreateTexture2D(&depth_stencil_desc, NULL, &ctx->depthstencil_tex)); | |
// create depth stencil view | |
D3D11_DEPTH_STENCIL_VIEW_DESC depth_stencil_view_desc = CD3D11_DEPTH_STENCIL_VIEW_DESC(D3D11_DSV_DIMENSION_TEXTURE2D, DXGI_FORMAT_D24_UNORM_S8_UINT); | |
CHECKHR(ctx->device->CreateDepthStencilView(ctx->depthstencil_tex, &depth_stencil_view_desc, &ctx->depthstencil_view)); | |
// Set-up default Colour and Depth surfaces | |
ctx->device_context->OMSetRenderTargets(1, &ctx->backbuffer_view, ctx->depthstencil_view); | |
// All done, ready to rock | |
return ctx; | |
} | |
void Update(Context* ctx) | |
{ | |
float colour_array[4] = { 0.1f, 0.2f, 0.3f, 1.0f }; | |
ctx->device_context->ClearRenderTargetView(ctx->backbuffer_view, colour_array); | |
// [Do your rendering here] | |
// All done, now swap | |
CHECKHR(ctx->swap_chain->Present(0, 0)); | |
} | |
void Shutdown(Context* ctx) | |
{ | |
safe_release(ctx->depthstencil_view); | |
safe_release(ctx->depthstencil_tex); | |
safe_release(ctx->backbuffer_view); | |
safe_release(ctx->backbuffer_tex); | |
safe_release(ctx->swap_chain); | |
safe_release(ctx->device_context); | |
safe_release(ctx->device); | |
delete ctx; | |
} | |
int main() | |
{ | |
Context* ctx = Init(); | |
while(ctx->finished == false) | |
{ | |
MSG msg; | |
while( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ) | |
{ | |
TranslateMessage(&msg); | |
DispatchMessage(&msg); | |
} | |
Update(ctx); | |
} | |
Shutdown(ctx); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment