Skip to content

Instantly share code, notes, and snippets.

@akbyrd
Created July 30, 2020 19:31
Show Gist options
  • Select an option

  • Save akbyrd/c9d312048b49c5bd607ceba084d95bd0 to your computer and use it in GitHub Desktop.

Select an option

Save akbyrd/c9d312048b49c5bd607ceba084d95bd0 to your computer and use it in GitHub Desktop.

Revisions

  1. akbyrd revised this gist Jul 30, 2020. 2 changed files with 0 additions and 0 deletions.
    File renamed without changes.
    File renamed without changes.
  2. akbyrd created this gist Jul 30, 2020.
    277 changes: 277 additions & 0 deletions Full Sample.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,277 @@
    #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);
    }
    56 changes: 56 additions & 0 deletions Resource Creation.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,56 @@
    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);