Skip to content

Instantly share code, notes, and snippets.

@lexmart
Created January 3, 2020 15:38
Show Gist options
  • Save lexmart/c8f2874d9ef024fec13b15739bccf5c7 to your computer and use it in GitHub Desktop.
Save lexmart/c8f2874d9ef024fec13b15739bccf5c7 to your computer and use it in GitHub Desktop.

Revisions

  1. lexmart created this gist Jan 3, 2020.
    293 changes: 293 additions & 0 deletions dx11minimal2.cpp
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,293 @@
    #define assert(expr) if(!(expr)) { *((int *)0) = 0; }
    #define invalidCodePath assert(false);
    #define arrlen(arr) (sizeof(arr)/sizeof((arr)[0]))

    #include "matrix.cpp"

    #include <windows.h>
    #include <d3d11.h>
    #include <dxgi.h>
    #include <stdint.h>
    #include <d3dcompiler.h>

    #pragma comment(lib, "d3dcompiler")
    #pragma comment(lib, "D3D11")
    #pragma comment(lib, "DXGI")

    struct Dx11State
    {
    IDXGISwapChain *swapChain;
    ID3D11Device *device;
    ID3D11DeviceContext *deviceContext;
    ID3D11RenderTargetView *renderTargetView;
    };

    struct Dx11VertexShader
    {
    ID3DBlob *buffer;
    ID3D11VertexShader *shader;
    };

    struct Dx11PixelShader
    {
    ID3DBlob *buffer;
    ID3D11PixelShader *shader;
    };

    struct Dx11VertexBuffer
    {
    };

    LRESULT CALLBACK win32EventHandler(HWND hwnd,UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }

    HWND win32OpenWindow(HINSTANCE inst, int width, int height)
    {
    HWND result = 0;

    WNDCLASSEX wndClass = {};
    wndClass.cbSize = sizeof(WNDCLASSEX);
    wndClass.style = 0;
    wndClass.lpfnWndProc = win32EventHandler;
    wndClass.hInstance = inst;
    wndClass.lpszClassName = "anim test";

    if (RegisterClassEx(&wndClass))
    {
    result = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, wndClass.lpszClassName, "anim test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, width, height, 0, 0, inst, 0);
    }

    return result;
    }

    Dx11State dxxInit(int width, int height, HWND window)
    {
    D3D_FEATURE_LEVEL featureLevels[] =
    {
    D3D_FEATURE_LEVEL_11_1,
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0,
    D3D_FEATURE_LEVEL_9_3,
    D3D_FEATURE_LEVEL_9_2,
    D3D_FEATURE_LEVEL_9_1
    };

    DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
    swapChainDesc.BufferDesc.Width = width;
    swapChainDesc.BufferDesc.Height = height;
    swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
    swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED;
    swapChainDesc.SampleDesc.Count = 1;
    swapChainDesc.SampleDesc.Quality = 0;
    swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapChainDesc.BufferCount = 2;
    swapChainDesc.OutputWindow = window;
    swapChainDesc.Windowed = TRUE;
    swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;

    Dx11State dx11 = {};

    HRESULT result = D3D11CreateDeviceAndSwapChain(0, D3D_DRIVER_TYPE_HARDWARE, 0, D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_DEBUG, featureLevels, 7, D3D11_SDK_VERSION,
    &swapChainDesc, &dx11.swapChain, &dx11.device, 0, &dx11.deviceContext);
    assert(!FAILED(result));

    // create render target
    ID3D11Texture2D *backBuffer = 0;
    dx11.swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)& backBuffer);
    dx11.device->CreateRenderTargetView(backBuffer, 0, &dx11.renderTargetView);

    // viewport settings
    D3D11_VIEWPORT viewport = {};
    viewport.Width = (float)width;
    viewport.Height = (float)height;
    viewport.MinDepth = 0.0f;
    viewport.MaxDepth = 1.0f;
    viewport.TopLeftX = 0;
    viewport.TopLeftY = 0;
    dx11.deviceContext->RSSetViewports(1, &viewport);

    // rasterizer settings
    ID3D11RasterizerState *rasterizer;
    D3D11_RASTERIZER_DESC rasterizerDesc;
    rasterizerDesc.FillMode = D3D11_FILL_SOLID;
    rasterizerDesc.CullMode = D3D11_CULL_FRONT;
    rasterizerDesc.FrontCounterClockwise = false;
    rasterizerDesc.DepthBias = false;
    rasterizerDesc.DepthBiasClamp = 0;
    rasterizerDesc.SlopeScaledDepthBias = 0;
    rasterizerDesc.DepthClipEnable = true;
    rasterizerDesc.ScissorEnable = false;
    rasterizerDesc.MultisampleEnable = false;
    rasterizerDesc.AntialiasedLineEnable = false;
    dx11.device->CreateRasterizerState(&rasterizerDesc, &rasterizer);
    dx11.deviceContext->RSSetState(rasterizer);

    return dx11;
    }

    Dx11VertexShader createVertexShader(Dx11State dx11, char *src, int srcBytes)
    {
    Dx11VertexShader vs = {};

    ID3DBlob *vsErrorBuffer = 0;
    HRESULT result = D3DCompile(src, srcBytes, "vs", 0, 0, "main", "vs_5_0", (1 << 0) | (1 << 11), 0, &vs.buffer, &vsErrorBuffer);
    if (vsErrorBuffer != 0)
    {
    OutputDebugString((char *)vsErrorBuffer->GetBufferPointer());
    invalidCodePath;
    }
    assert(!FAILED(result));
    result = dx11.device->CreateVertexShader(vs.buffer->GetBufferPointer(), vs.buffer->GetBufferSize(), 0, &vs.shader);
    assert(!FAILED(result));

    return vs;
    }

    Dx11PixelShader createPixelShader(Dx11State dx11, char *src, int srcBytes)
    {
    Dx11PixelShader ps = {};

    ID3DBlob *psErrorBuffer = 0;
    HRESULT result = D3DCompile(src, srcBytes, "ps", 0, 0, "main", "ps_5_0", (1 << 0) | (1 << 11), 0, &ps.buffer, &psErrorBuffer);
    if (psErrorBuffer != 0)
    {
    OutputDebugString((char *)psErrorBuffer->GetBufferPointer());
    invalidCodePath;
    }
    assert(!FAILED(result));
    result = dx11.device->CreatePixelShader(ps.buffer->GetBufferPointer(), ps.buffer->GetBufferSize(), 0, &ps.shader);
    assert(!FAILED(result));

    return ps;
    }

    ID3D11Buffer *createVertexBuffer(Dx11State dx11, float data[], int bytes)
    {
    D3D11_BUFFER_DESC bufferDesc = {};
    bufferDesc.Usage = D3D11_USAGE_DEFAULT;
    bufferDesc.ByteWidth = bytes;
    bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    bufferDesc.CPUAccessFlags = 0;
    bufferDesc.MiscFlags = 0;

    D3D11_SUBRESOURCE_DATA bufferResource = {};
    bufferResource.pSysMem = data;

    ID3D11Buffer *vertexBuffer = 0;
    HRESULT result = dx11.device->CreateBuffer(&bufferDesc, &bufferResource, &vertexBuffer);
    assert(!FAILED(result));

    return vertexBuffer;
    }

    ID3D11InputLayout *createInputLayout(Dx11State dx11, D3D11_INPUT_ELEMENT_DESC *inputLayoutData, int n, Dx11VertexShader vs)
    {
    ID3D11InputLayout *layout = 0;
    HRESULT result = dx11.device->CreateInputLayout(inputLayoutData, n, (void *)vs.buffer->GetBufferPointer(), vs.buffer->GetBufferSize(), &layout);
    assert(!FAILED(result));

    return layout;
    }

    char vertexShaderCode[] = R"STR(
    struct VertexShaderInput
    {
    float3 pos : POSITION;
    float3 color : COLOR;
    };
    struct VertexShaderOuput
    {
    float4 pos : SV_POSITION;
    float3 color : COLOR;
    };
    VertexShaderOuput main(VertexShaderInput input)
    {
    VertexShaderOuput output;
    output.pos = float4(input.pos, 1.0f);
    output.color = input.color;
    return output;
    }
    )STR";

    char pixelShaderCode[] = R"STR(
    struct PixelShaderInput
    {
    float4 pos : SV_POSITION;
    float3 color : COLOR;
    };
    float3 main(PixelShaderInput input) : SV_TARGET
    {
    return input.color;
    };
    )STR";

    int WinMain(HINSTANCE inst, HINSTANCE prevInst, char *cmdLine, int cmdShow)
    {
    testMatrixMath();

    int width = 800;
    int height = 600;

    HWND window = win32OpenWindow(inst, width, height);
    if(window)
    {
    Dx11State dx11 = dxxInit(width, height, window);
    Dx11VertexShader vs = createVertexShader(dx11, vertexShaderCode, sizeof(vertexShaderCode));
    Dx11PixelShader ps = createPixelShader(dx11, pixelShaderCode, sizeof(pixelShaderCode));

    // create vertex buffer
    float triangle[] =
    {
    0.0f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f,
    -0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
    0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f
    };
    uint32_t vertexBufferStride = 24;
    ID3D11Buffer *triangleVertexBuffer = createVertexBuffer(dx11, triangle, sizeof(triangle));

    // create vertex buffer laoyout
    D3D11_INPUT_ELEMENT_DESC inputLayoutData[] =
    {
    {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0}
    };
    ID3D11InputLayout *inputLayout = createInputLayout(dx11, inputLayoutData, arrlen(inputLayoutData), vs);


    float clearColor[] = { 0.0f, 0.0f, 0.0f, 0.0f };
    while (1)
    {
    dx11.deviceContext->OMSetRenderTargets(1, &dx11.renderTargetView, 0);

    // clear the back buffer
    //clearColor[0] -= 1.0f / 300.0f;
    dx11.deviceContext->ClearRenderTargetView(dx11.renderTargetView, clearColor);

    // setup IA
    uint32_t zero = 0;
    dx11.deviceContext->IASetVertexBuffers(0, 1, &triangleVertexBuffer, &vertexBufferStride, &zero);
    dx11.deviceContext->IASetInputLayout(inputLayout);
    dx11.deviceContext->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    // setup VS
    dx11.deviceContext->VSSetShader(vs.shader, 0, 0);

    // setup PS
    //deviceContext->RSSetState(rasterizer);
    dx11.deviceContext->PSSetShader(ps.shader, 0, 0);

    dx11.deviceContext->Draw(3, 0);
    dx11.swapChain->Present(1, 0);
    }
    }
    }