我正在尝试学习如何使用D3D11(我无论如何都不是图形编程的专业人士),并且在我的代码中的设备创建功能期间,它返回
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;
}
一开始我不明白为什么,但后来我将
IDXGIAdapter
参数更改为 NULL
并且函数通过了,但我觉得它应该第一次就可以工作。我想知道为什么会发生这种情况,以及如何使用 IDXGIAdapter
界面而不是 NULL
。
您无法传递 DXGI 适配器参考 和 D3D_DRIVER_TYPE_HARDWARE,如记录的:
如果将 pAdapter 参数设置为非 NULL 值,则还必须 将 DriverType 参数设置为 D3D_DRIVER_TYPE_UNKNOWN 值。如果 将 pAdapter 参数设置为非 NULL 值,并将 DriverType 设置为 D3D_DRIVER_TYPE_HARDWARE 值的参数,D3D11CreateDevice 返回 E_INVALIDARG 的 HRESULT。
所以,你必须这样做:
hres = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, SSfeaturelvl, 1, D3D11_SDK_VERSION, &device, NULL, &context);
或者这个:
hres = D3D11CreateDevice(adapter, D3D_DRIVER_TYPE_UNKNOWN, NULL, 0, SSfeaturelvl, 1, D3D11_SDK_VERSION, &device, NULL, &context);