Created
July 30, 2020 19:31
-
-
Save akbyrd/c9d312048b49c5bd607ceba084d95bd0 to your computer and use it in GitHub Desktop.
DirectX 11 Swap Chain Format Support
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
DXGI_FORMAT renderTextureFormat = DXGI_FORMAT_B5G6R5_UNORM; | |
// Device | |
hr = D3D11CreateDevice( | |
nullptr, | |
D3D_DRIVER_TYPE_HARDWARE, | |
nullptr, | |
D3D11_CREATE_DEVICE_SINGLETHREADED | D3D11_CREATE_DEVICE_DEBUG, | |
nullptr, 0, | |
D3D11_SDK_VERSION, | |
&d3dDevice, | |
&featureLevel, | |
&d3dContext | |
); | |
// Render Texture | |
D3D11_TEXTURE2D_DESC renderTextureDesc = {}; | |
renderTextureDesc.Width = renderSize.x; | |
renderTextureDesc.Height = renderSize.y; | |
renderTextureDesc.MipLevels = 1; | |
renderTextureDesc.ArraySize = 1; | |
renderTextureDesc.Format = renderTextureFormat; | |
renderTextureDesc.SampleDesc.Count = 1; | |
renderTextureDesc.SampleDesc.Quality = 0; | |
renderTextureDesc.Usage = D3D11_USAGE_DEFAULT; | |
renderTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; | |
renderTextureDesc.CPUAccessFlags = 0; | |
renderTextureDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; | |
hr = d3dDevice->CreateTexture2D(&renderTextureDesc, nullptr, &d3dRenderTexture); | |
// Swap Chain | |
DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; | |
swapChainDesc.BufferDesc.Width = renderSize.x; | |
swapChainDesc.BufferDesc.Height = renderSize.y; | |
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; | |
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; | |
swapChainDesc.BufferDesc.Format = renderTextureFormat; | |
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; | |
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; | |
swapChainDesc.SampleDesc.Count = 1; | |
swapChainDesc.SampleDesc.Quality = 0; | |
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; | |
swapChainDesc.BufferCount = 1; | |
swapChainDesc.OutputWindow = hwnd; | |
swapChainDesc.Windowed = true; | |
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; | |
swapChainDesc.Flags = 0; | |
hr = dxgiFactory->CreateSwapChain(d3dDevice.Get(), &swapChainDesc, &swapChain); |
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
#include <stdint.h> | |
#include <exception> | |
using u32 = uint32_t; | |
using i32 = int32_t; | |
using c8 = char; | |
using b8 = bool; | |
struct v2u { u32 x; u32 y; }; | |
#define Assert(condition) if (!(condition)) { *((c8 *) 0) = 0; } | |
#pragma comment(lib, "D3D11.lib") | |
#pragma comment(lib, "DXGI.lib") | |
#pragma warning(push, 0) | |
#define D3D_DEBUG_INFO | |
#include <InitGuid.h> | |
#include <d3d11sdklayers.h> | |
#include <dxgidebug.h> | |
#include <dxgi1_3.h> | |
#include <d3d11.h> | |
#include <wrl\client.h> | |
using Microsoft::WRL::ComPtr; | |
#pragma warning(pop) | |
#if false | |
DXGI_FORMAT renderTextureFormat = DXGI_FORMAT_B8G8R8A8_UNORM; | |
#else | |
DXGI_FORMAT renderTextureFormat = DXGI_FORMAT_B5G6R5_UNORM; | |
#endif | |
const c8 previewWindowClass[] = "Preview Window Class"; | |
const u32 WM_PREVIEWWINDOWCLOSED = WM_USER + 0; | |
i32 CALLBACK | |
WinMain(HINSTANCE hInstance, HINSTANCE, c8*, i32) | |
{ | |
HRESULT hr; | |
b8 success; | |
v2u renderSize = { 320, 240 }; | |
ComPtr<ID3D11Device> d3dDevice; | |
ComPtr<ID3D11DeviceContext> d3dContext; | |
ComPtr<IDXGIFactory1> dxgiFactory; | |
ComPtr<ID3D11Texture2D> d3dRenderTexture;; | |
HWND hwnd; | |
ComPtr<IDXGISwapChain> swapChain; | |
ComPtr<ID3D11Texture2D> backBuffer; | |
v2u nonClientSize; | |
// Renderer | |
// Create device | |
{ | |
UINT createDeviceFlags = D3D11_CREATE_DEVICE_SINGLETHREADED; | |
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; | |
D3D_FEATURE_LEVEL featureLevel; | |
hr = D3D11CreateDevice( | |
nullptr, | |
D3D_DRIVER_TYPE_HARDWARE, | |
nullptr, | |
createDeviceFlags, | |
nullptr, 0, | |
D3D11_SDK_VERSION, | |
&d3dDevice, | |
&featureLevel, | |
&d3dContext | |
); | |
Assert(!FAILED(hr)); | |
// Check feature level | |
Assert((featureLevel & D3D_FEATURE_LEVEL_11_0) == D3D_FEATURE_LEVEL_11_0); | |
// Obtain the DXGI factory used to create the current device. | |
ComPtr<IDXGIDevice1> dxgiDevice; | |
hr = d3dDevice.As(&dxgiDevice); | |
Assert(!FAILED(hr)); | |
ComPtr<IDXGIAdapter> dxgiAdapter; | |
hr = dxgiDevice->GetAdapter(&dxgiAdapter); | |
Assert(!FAILED(hr)); | |
hr = dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory)); | |
Assert(!FAILED(hr)); | |
// Check for the WARP driver | |
DXGI_ADAPTER_DESC desc = {}; | |
hr = dxgiAdapter->GetDesc(&desc); | |
Assert(!FAILED(hr)); | |
Assert(!((desc.VendorId == 0x1414) && (desc.DeviceId == 0x8c))); | |
} | |
// Configure debugging | |
{ | |
ComPtr<IDXGIDebug1> dxgiDebug; | |
hr = DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)); | |
Assert(!FAILED(hr)); | |
dxgiDebug->EnableLeakTrackingForThread(); | |
ComPtr<IDXGIInfoQueue> dxgiInfoQueue; | |
hr = DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiInfoQueue)); | |
Assert(!FAILED(hr)); | |
hr = dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_ERROR, true); | |
Assert(!FAILED(hr)); | |
hr = dxgiInfoQueue->SetBreakOnSeverity(DXGI_DEBUG_ALL, DXGI_INFO_QUEUE_MESSAGE_SEVERITY_CORRUPTION, true); | |
Assert(!FAILED(hr)); | |
// Ignore warning for not using a flip-mode swap chain | |
DXGI_INFO_QUEUE_MESSAGE_ID ids[] = { 294 }; | |
DXGI_INFO_QUEUE_FILTER filter = {}; | |
filter.DenyList.NumIDs = 1; | |
filter.DenyList.pIDList = ids; | |
hr = dxgiInfoQueue->PushStorageFilter(DXGI_DEBUG_DXGI, &filter); | |
Assert(!FAILED(hr)); | |
} | |
// Create render texture | |
{ | |
D3D11_TEXTURE2D_DESC renderTextureDesc = {}; | |
renderTextureDesc.Width = renderSize.x; | |
renderTextureDesc.Height = renderSize.y; | |
renderTextureDesc.MipLevels = 1; | |
renderTextureDesc.ArraySize = 1; | |
renderTextureDesc.Format = renderTextureFormat; | |
renderTextureDesc.SampleDesc.Count = 1; | |
renderTextureDesc.SampleDesc.Quality = 0; | |
renderTextureDesc.Usage = D3D11_USAGE_DEFAULT; | |
renderTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; | |
renderTextureDesc.CPUAccessFlags = 0; | |
renderTextureDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED; | |
hr = d3dDevice->CreateTexture2D(&renderTextureDesc, nullptr, &d3dRenderTexture); | |
Assert(!FAILED(hr)); | |
} | |
// Preview Window | |
// Create Window | |
{ | |
LRESULT CALLBACK | |
PreviewWndProc(HWND, u32, WPARAM, LPARAM); | |
WNDCLASSA windowClass = {}; | |
windowClass.style = 0; | |
windowClass.lpfnWndProc = PreviewWndProc; | |
windowClass.cbClsExtra = 0; | |
windowClass.cbWndExtra = 0; | |
windowClass.hInstance = hInstance; | |
windowClass.hIcon = nullptr; | |
windowClass.hCursor = LoadCursorW(nullptr, IDC_ARROW); | |
windowClass.hbrBackground = nullptr; | |
windowClass.lpszMenuName = nullptr; | |
windowClass.lpszClassName = previewWindowClass; | |
ATOM classAtom = RegisterClassA(&windowClass); | |
Assert(classAtom != INVALID_ATOM); | |
u32 windowStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE; | |
RECT windowRect = { 0, 0, (i32) renderSize.x, (i32) renderSize.y }; | |
success = AdjustWindowRect(&windowRect, (u32) windowStyle, false); | |
Assert(success); | |
nonClientSize.x = (windowRect.right - windowRect.left) - renderSize.x; | |
nonClientSize.y = (windowRect.bottom - windowRect.top) - renderSize.y; | |
hwnd = CreateWindowA( | |
windowClass.lpszClassName, | |
"Preview", | |
(u32) windowStyle, | |
CW_USEDEFAULT, CW_USEDEFAULT, | |
(i32) (renderSize.x + nonClientSize.x), | |
(i32) (renderSize.y + nonClientSize.y), | |
nullptr, | |
nullptr, | |
hInstance, | |
nullptr | |
); | |
Assert(hwnd != INVALID_HANDLE_VALUE); | |
success = SetForegroundWindow(hwnd); | |
Assert(success); | |
} | |
// Attach Renderer | |
{ | |
DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; | |
swapChainDesc.BufferDesc.Width = renderSize.x; | |
swapChainDesc.BufferDesc.Height = renderSize.y; | |
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60; | |
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; | |
swapChainDesc.BufferDesc.Format = renderTextureFormat; | |
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; | |
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; | |
swapChainDesc.SampleDesc.Count = 1; | |
swapChainDesc.SampleDesc.Quality = 0; | |
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; | |
swapChainDesc.BufferCount = 1; | |
swapChainDesc.OutputWindow = hwnd; | |
swapChainDesc.Windowed = true; | |
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; | |
swapChainDesc.Flags = 0; | |
// Create the swap chain | |
hr = dxgiFactory->CreateSwapChain(d3dDevice.Get(), &swapChainDesc, &swapChain); | |
Assert(!FAILED(hr)); | |
// Get the back buffer | |
hr = swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)); | |
Assert(!FAILED(hr)); | |
// Associate the window | |
hr = dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER); | |
Assert(!FAILED(hr)); | |
} | |
// Main loop | |
for(;;) | |
{ | |
// Pump messages | |
MSG msg = {}; | |
while (PeekMessageA(&msg, nullptr, 0, 0, PM_REMOVE)) | |
{ | |
TranslateMessage(&msg); | |
DispatchMessageA(&msg); | |
switch (msg.message) | |
{ | |
case WM_PREVIEWWINDOWCLOSED: | |
case WM_QUIT: | |
return (i32) msg.wParam; | |
} | |
} | |
} | |
return 0; | |
} | |
LRESULT CALLBACK | |
PreviewWndProc(HWND hwnd, u32 uMsg, WPARAM wParam, LPARAM lParam) | |
{ | |
switch (uMsg) | |
{ | |
case WM_KEYDOWN: | |
{ | |
switch (wParam) | |
{ | |
case VK_ESCAPE: | |
PostQuitMessage(0); | |
return 0; | |
} | |
break; | |
} | |
case WM_CLOSE: | |
{ | |
b8 success = PostMessageA(nullptr, WM_PREVIEWWINDOWCLOSED, 0, 0); | |
Assert(success); | |
return 0; | |
} | |
} | |
return DefWindowProcA(hwnd, uMsg, wParam, lParam); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment