Why does CreateDevice() for ID3D11Device return error 0x80070057: "The parameter is incorrect"?

94 Views Asked by At

I am trying to learn how to use D3D11 (I'm not a professional in graphics programming in any way), and in my code during the device creation function, it returns E_INVALIDARG.

#include <Windows.h>
#include <iostream>
#include <d3d11.h>
#include <dxgi.h>
#include <d3dcompiler.h>

#pragma comment(lib,"d3d11.lib")
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"d3dcompiler.lib")

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }

    return 0;
}

#define WndHeight 700
#define WndWidth 1000

HRESULT hres = 0;

void check(LPCWSTR str)
{
    if (hres != S_OK)
    {
        OutputDebugString(str);

        LPVOID errorMsg;
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
            NULL,
            hres,
            0, // Default language
            (LPWSTR)&errorMsg,
            0,
            NULL
        );

        // Create a buffer to hold the formatted message
        wchar_t buffer[256];
        swprintf_s(buffer, L"Error 0x%X: %s", hres, (errorMsg ? static_cast<LPCWSTR>(errorMsg) : L"Unknown error"));

        // Output the message to the debugger
        OutputDebugString(buffer);

        // Free the allocated buffer
        LocalFree(errorMsg);

        DWORD lastError = GetLastError();
        FormatMessage(
            FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
            NULL,
            lastError,
            0, // Default language
            (LPWSTR)&errorMsg,
            0,
            NULL
        );

        // Create a buffer for the additional system information
        swprintf_s(buffer, L"Additional system information: %s", (errorMsg ? static_cast<LPCWSTR>(errorMsg) : L"Unknown error"));

        // Output the additional system information to the debugger
        OutputDebugString(buffer);

        // Free the allocated buffer
        LocalFree(errorMsg);

        exit(-1);
    }
}

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPWSTR    lpCmdLine,
    _In_ int       nCmdShow)
{
    HWND hwnd;
    {
        WNDCLASS wc;
        wc.cbClsExtra = 0;
        wc.cbWndExtra = 0;
        wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
        wc.hCursor = NULL;
        wc.hIcon = NULL;
        wc.hInstance = hInstance;
        wc.lpfnWndProc = WndProc;
        wc.lpszClassName = L"MainClass";
        wc.lpszMenuName = nullptr;
        wc.style = CS_HREDRAW | CS_VREDRAW;

        if (!RegisterClass(&wc))
        {
            OutputDebugString(L"Class Registreation Failed!");
        }

        hwnd = CreateWindow(L"MainClass", L"simple quad", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
            CW_USEDEFAULT, CW_USEDEFAULT,
            WndHeight, WndWidth,
            NULL,
            NULL,
            hInstance,
            NULL);

        if (!hwnd)
        {
            OutputDebugString(L"Window Creation Failed!");
        }
    }

    ID3D11Device* device = nullptr;
    ID3D11DeviceContext* context = nullptr;
    D3D_FEATURE_LEVEL SSfeaturelvl[] = { D3D_FEATURE_LEVEL_11_0 };

    IDXGIFactory1* dxgiFactory = nullptr;
    {
        hres = CreateDXGIFactory1(IID_PPV_ARGS(&dxgiFactory));
        check(L"\nIDXGIFactory1 Creation Failed!\n");
    }

    IDXGIAdapter* adapter = nullptr;
    {
        hres = dxgiFactory->EnumAdapters(0, &adapter);
        check(L"\nIDXGIAdapter Creation Failed!\n");

        DXGI_ADAPTER_DESC adapterDesc = { 0 };
        adapter->GetDesc(&adapterDesc);

        OutputDebugString(L"\nGraphics device : ");
        OutputDebugString(adapterDesc.Description);
    }

    hres = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, SSfeaturelvl, 1, D3D11_SDK_VERSION, &device, NULL, &context);
    check(L"\nID3D11Device Creation Failed!\n");

    IDXGISwapChain* swapchain = nullptr;
    {
        DXGI_MODE_DESC modeDesc = { 0 };
        modeDesc.Width = WndWidth;
        modeDesc.Height = WndHeight;

        modeDesc.Format = DXGI_FORMAT_UNKNOWN;

        modeDesc.RefreshRate.Numerator = 30;
        modeDesc.RefreshRate.Denominator = 1;

        modeDesc.Scaling = DXGI_MODE_SCALING_STRETCHED;

        modeDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;

        DXGI_SWAP_CHAIN_DESC desc = { 0 };
        desc.BufferCount = 2;
        desc.BufferDesc = modeDesc;
        desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        desc.Flags = 0;
        desc.OutputWindow = hwnd;
        desc.SampleDesc.Count = 1;
        desc.SampleDesc.Quality = 0;
        desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
        desc.Windowed = TRUE;

        hres = dxgiFactory->CreateSwapChain(device, &desc, &swapchain);
        check(L"\nswapchain Creation Failed!\n");
    }

    ID3D11Buffer* vertexbuffer = nullptr;
    {
        int vertices[] = {
            //  X,    Y
               -500,  350,
               -500, -250,
                500, -250,
                500,  250
        };

        D3D11_BUFFER_DESC VBdesc = { 0 };
        VBdesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
        VBdesc.ByteWidth = sizeof(vertices);
        VBdesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
        VBdesc.MiscFlags = 0;
        VBdesc.StructureByteStride = 2 * sizeof(int);
        VBdesc.Usage = D3D11_USAGE_DEFAULT;

        D3D11_SUBRESOURCE_DATA VBdata = { 0 };
        VBdata.pSysMem = vertices;
        VBdata.SysMemPitch = 0;
        VBdata.SysMemSlicePitch = 0;

        hres = device->CreateBuffer(&VBdesc, &VBdata, &vertexbuffer);
        check(L"\nvertexbuffer Creation Failed!\n");
    }

    ID3D11Buffer* indexbuffer = nullptr;
    {
        int vertices[] = {
         // 1, 2, 3
            0, 1, 2,
            2, 3, 0
        };

        D3D11_BUFFER_DESC VBdesc = { 0 };
        VBdesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
        VBdesc.ByteWidth = sizeof(vertices);
        VBdesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
        VBdesc.MiscFlags = 0;
        VBdesc.StructureByteStride = 3 * sizeof(int);
        VBdesc.Usage = D3D11_USAGE_DEFAULT;

        D3D11_SUBRESOURCE_DATA VBdata = { 0 };
        VBdata.pSysMem = vertices;
        VBdata.SysMemPitch = 0;
        VBdata.SysMemSlicePitch = 0;

        device->CreateBuffer(&VBdesc, &VBdata, &indexbuffer);
        check(L"\nindexbuffer Creation Failed!\n");
    }

    ID3D11VertexShader* VertesShader = nullptr;
    ID3DBlob* vsBlob = nullptr;
    {
        hres = D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "vs_main", "vs_5_0", 0, 0, &vsBlob, 0);
        check(L"\nvsBlob Creation Failed!\n");

        hres = device->CreateVertexShader(vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), nullptr, &VertesShader);
        check(L"\nVertesShader Creation Failed!\n");
    }

    ID3D11PixelShader* pixelShader;
    ID3DBlob* psBlob = nullptr;
    {
        hres = D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "ps_main", "ps_5_0", 0, 0, &psBlob, 0);
        check(L"\npsBlob Creation Failed!\n");

        hres = device->CreatePixelShader(psBlob->GetBufferPointer(), psBlob->GetBufferSize(), nullptr, &pixelShader);
        check(L"\npixelShader Creation Failed!\n");
        psBlob->Release();
    }

    ID3D11InputLayout* IL = nullptr;
    {
        D3D11_INPUT_ELEMENT_DESC IEdesc[] =
        {
            {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
        };

        hres = device->CreateInputLayout(IEdesc, ARRAYSIZE(IEdesc), vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), &IL);
        check(L"\nID3D11InputLayout Creation Failed!\n");
    }
    
    ID3D11RenderTargetView* RTV = nullptr;
    {
        ID3D11Texture2D* d3d11FrameBuffer;
        hres = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&d3d11FrameBuffer);
        check(L"\ngetbuffer for RTV Failed!\n");

        hres = device->CreateRenderTargetView(d3d11FrameBuffer, 0, &RTV);
        check(L"\nID3D11RenderTargetView Creation Failed!\n");
        d3d11FrameBuffer->Release();
    }

    {
        context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
        context->IASetIndexBuffer(indexbuffer, DXGI_FORMAT_R32G32B32_SINT, 0);
        context->IASetInputLayout(IL);

        context->VSSetShader(VertesShader, NULL, NULL);
        context->PSSetShader(pixelShader, NULL, NULL);

        RECT winRect;
        GetClientRect(hwnd, &winRect);

        D3D11_VIEWPORT viewport = { 0 };
        viewport.TopLeftX = 0.0f;
        viewport.TopLeftY = 0.0f;
        viewport.Width = (FLOAT)(winRect.right - winRect.left);
        viewport.Height = (FLOAT)(winRect.bottom - winRect.top);
        viewport.MinDepth = 0.0f;
        viewport.MaxDepth = 0.0f;

        context->RSSetViewports(1, &viewport);

        context->OMSetRenderTargets(1, &RTV, NULL);
    }
    
    ShowWindow(hwnd, SW_SHOW);
    UpdateWindow(hwnd);

    MSG msg = { 0 };
    while (msg.message != WM_QUIT)
    {
        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        context->DrawIndexed(6, 0, 0);

        swapchain->Present(1, 0);
    }

    return 0;
}

At first, I couldn't figure out why, but then I changed the IDXGIAdapter argument to NULL and the function passed, but I feel it should have worked the first time. I want to know why this happens, and how I can use the IDXGIAdapter interface instead of NULL.

1

There are 1 best solutions below

0
Simon Mourier On

You can't pass a DXGI adapter reference and D3D_DRIVER_TYPE_HARDWARE as documented:

If you set the pAdapter parameter to a non-NULL value, you must also set the DriverType parameter to the D3D_DRIVER_TYPE_UNKNOWN value. If you set the pAdapter parameter to a non-NULL value and the DriverType parameter to the D3D_DRIVER_TYPE_HARDWARE value, D3D11CreateDevice returns an HRESULT of E_INVALIDARG.

So, you must do this:

hres = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, SSfeaturelvl, 1, D3D11_SDK_VERSION, &device, NULL, &context);

or this:

hres = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, SSfeaturelvl, 1, D3D11_SDK_VERSION, &device, NULL, &context);