DirectX Shaders API Reference

Overview

DirectX shaders are small programs that run on the GPU to implement rendering effects, compute operations, and more. They are written in the High Level Shader Language (HLSL) and compiled into bytecode that Direct3D consumes.

Shader Types

HLSL Basics

HLSL syntax is similar to C. Below is a minimal vertex shader example:

// SimpleVertexShader.hlsl
struct VSInput {
    float3 pos   : POSITION;
    float4 color : COLOR;
};

struct VSOutput {
    float4 pos   : SV_POSITION;
    float4 color : COLOR;
};

VSOutput main(VSInput input) {
    VSOutput output;
    output.pos   = float4(input.pos, 1.0);
    output.color = input.color;
    return output;
}

Compilation & Pipeline Integration

Shaders are compiled with D3DCompile or the newer DXC compiler. The resulting bytecode is then bound to the device context.

// Example using D3DCompile
ID3DBlob* shaderBlob = nullptr;
ID3DBlob* errorBlob = nullptr;
HRESULT hr = D3DCompileFromFile(
    L"SimpleVertexShader.hlsl",
    nullptr,
    nullptr,
    "main",
    "vs_5_0",
    0,
    0,
    &shaderBlob,
    &errorBlob);
if (FAILED(hr)) {
    OutputDebugStringA((char*)errorBlob->GetBufferPointer());
}
device->CreateVertexShader(shaderBlob->GetBufferPointer(),
                           shaderBlob->GetBufferSize(),
                           nullptr,
                           &vertexShader);

Sample Code

Below is a complete minimal Direct3D 11 initialization that loads a vertex and pixel shader and draws a colored triangle.

#include <d3d11.h>
#pragma comment(lib, "d3d11.lib")
#include <d3dcompiler.h>
#pragma comment(lib, "d3dcompiler.lib")

// Vertex structure and data
struct Vertex { float3 pos; float4 color; };
Vertex vertices[] = {
    { { 0.0f,  0.5f, 0.0f }, {1,0,0,1} },
    { { 0.5f, -0.5f, 0.0f }, {0,1,0,1} },
    { { -0.5f,-0.5f, 0.0f }, {0,0,1,1} }
};

int main() {
    // (Window creation code omitted for brevity)

    // Initialize D3D device and swap chain
    D3D_FEATURE_LEVEL featureLevel;
    ID3D11Device* device = nullptr;
    ID3D11DeviceContext* context = nullptr;
    IDXGISwapChain* swapChain = nullptr;
    DXGI_SWAP_CHAIN_DESC scDesc = {};
    // ... fill scDesc and create device/swapChain ...

    // Compile shaders
    ID3DBlob* vsBlob; ID3DBlob* psBlob;
    D3DCompileFromFile(L"SimpleVertexShader.hlsl", nullptr, nullptr,
        "main", "vs_5_0", 0, 0, &vsBlob, nullptr);
    D3DCompileFromFile(L"SimplePixelShader.hlsl", nullptr, nullptr,
        "main", "ps_5_0", 0, 0, &psBlob, nullptr);

    // Create shaders
    ID3D11VertexShader* vs; ID3D11PixelShader* ps;
    device->CreateVertexShader(vsBlob->GetBufferPointer(),
        vsBlob->GetBufferSize(), nullptr, &vs);
    device->CreatePixelShader(psBlob->GetBufferPointer(),
        psBlob->GetBufferSize(), nullptr, &ps);
    context->VSSetShader(vs, nullptr, 0);
    context->PSSetShader(ps, nullptr, 0);

    // Input layout
    D3D11_INPUT_ELEMENT_DESC layoutDesc[] = {
        { "POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT,0,0,
          D3D11_INPUT_PER_VERTEX_DATA,0 },
        { "COLOR",0,DXGI_FORMAT_R32G32B32A32_FLOAT,0,12,
          D3D11_INPUT_PER_VERTEX_DATA,0 }
    };
    ID3D11InputLayout* layout;
    device->CreateInputLayout(layoutDesc, 2, vsBlob->GetBufferPointer(),
        vsBlob->GetBufferSize(), &layout);
    context->IASetInputLayout(layout);

    // Vertex buffer
    D3D11_BUFFER_DESC vbDesc = { sizeof(vertices), D3D11_USAGE_DEFAULT,
        D3D11_BIND_VERTEX_BUFFER, 0, 0, 0 };
    D3D11_SUBRESOURCE_DATA initData = { vertices, 0, 0 };
    ID3D11Buffer* vertexBuffer;
    device->CreateBuffer(&vbDesc, &initData, &vertexBuffer);
    UINT stride = sizeof(Vertex);
    UINT offset = 0;
    context->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
    context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    // Main loop (simplified)
    while (true) {
        // Clear screen
        float clearColor[4] = {0.1f,0.1f,0.1f,1.0f};
        ID3D11RenderTargetView* rtv; // obtained from swap chain
        context->ClearRenderTargetView(rtv, clearColor);

        // Draw
        context->Draw(3, 0);

        // Present
        swapChain->Present(1,0);
    }
}

References