1

创建 DirectX 12 命令队列时出现一个奇怪的错误。其他 DX12 应用程序能够在同一台机器上成功启动。

我的电脑使用该D3D_FEATURE_LEVEL_11_0 if块。测试用的显卡是NVIDIA GT 740,驱动361.75

这是正在使用的代码(最小化):

#include <Windows.h>
#include <d3d12.h>
#include <dxgi1_4.h>
#include <comdef.h>
#include <D3d12sdklayers.h>
#include <string>

#pragma comment(lib,"d3d12.lib")
#pragma comment(lib,"dxgi.lib")
#pragma comment(lib,"d3dcompiler.lib")
using namespace std;

LRESULT WINAPI WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine, int nCmdShow) {
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(nCmdShow);
    UNREFERENCED_PARAMETER(lpCmdLine);

    wchar_t* WindowClass = L"Papergate";
    WNDCLASSEX wc;
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 2);
    wc.lpszClassName = WindowClass;

    if (!RegisterClassEx(&wc))
    {
        return 1;
    }

    HWND hwnd = CreateWindowEx(NULL, wc.lpszClassName, WindowClass,
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);

    if (!hwnd)
    {
        UnregisterClass(WindowClass, hInstance);
        return 1;
    }
    ShowWindow(hwnd, SW_SHOWDEFAULT);
    UpdateWindow(hwnd);

    ID3D12Device* device;
    HRESULT result = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_12_1,
        __uuidof(ID3D12Device), (void**)&device);
    if (FAILED(result))
    {
        result = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_12_0,
            __uuidof(ID3D12Device), (void**)&device);
        if (FAILED(result))
        {
            result = D3D12CreateDevice(NULL, D3D_FEATURE_LEVEL_11_0,
                __uuidof(ID3D12Device), (void**)&device);
            if (FAILED(result)) {
                _com_error error(result);
                MessageBox(hwnd, error.ErrorMessage(),
                    (wstring(L"Error: ") + to_wstring(__LINE__)).c_str(),
                    MB_OK);
                return 2;
            }
        }
    }

    ID3D12Debug* debugInterface;
    if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface))))
    {
        debugInterface->EnableDebugLayer();
    }

    D3D12_COMMAND_QUEUE_DESC commandQueueDesc;
    commandQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
    commandQueueDesc.NodeMask = 0;
    commandQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
    commandQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
    ID3D12CommandQueue* commandQueue;
    result = device->CreateCommandQueue(&commandQueueDesc, __uuidof(ID3D12CommandQueue), (void**)&commandQueue);
    if (FAILED(result)) {
        _com_error error(result);
        MessageBox(hwnd, error.ErrorMessage(),
            (wstring(L"Error: ") + to_wstring(__LINE__)).c_str(), MB_OK);
        result = device->GetDeviceRemovedReason();
        error = _com_error(result);
        MessageBox(hwnd, error.ErrorMessage(),
            (wstring(L"Error: ") + to_wstring(__LINE__)).c_str(), MB_OK);
        debugInterface->Release(); device->Release(); return 2;
    }

    MSG msg;
    ZeroMemory(&msg, sizeof(MSG));
    while (GetMessage(&msg, NULL, 0, 0) && msg.message != WM_QUIT)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    commandQueue->Release();
    device->Release();
    UnregisterClass(WindowClass, hInstance);
    return 0;
}

我分别在第 97 行和第 102 行收到以下错误:

The GPU device instance has been suspended. Use GetDeviceRemovedReason to determine the appropriate action.

第二个错误:

The GPU will not respond to more commands, most likely because some other application submitted invalid commands.
The calling application should re-create the device and continue.
4

1 回答 1

1

这似乎很可能是某种驱动程序错误。检查您的硬件是否有更新的驱动程序。您应该尝试在此VSIX中使用 Direct3D12 游戏模板,看看它们是否遇到相同类型的问题(有关模板的更多详细信息,请参阅此博客文章)。

您调用各种功能级别的级联模式D3D12CreateDevice是不寻常的,并且没有必要。如果您的应用程序可以在 Direct3D Feature Level 11.0 或更高版本上运行,则只需使用D3D_FEATURE_LEVEL_11_0一次。您应该将支持的最低功能级别传递给此函数。

如果 Direct3D 12 设备确实支持更高的功能级别,您可以通过检查单个功能或使用CheckFeatureSupportD3D12_FEATURE_FEATURE_LEVELS来发现:

// Create the DX12 API device object.
DX::ThrowIfFailed(D3D12CreateDevice(
    adapter.Get(),
    m_d3dMinFeatureLevel,
    IID_PPV_ARGS(&m_d3dDevice)
    ));

// Determine maximum supported feature level for this device
static const D3D_FEATURE_LEVEL s_featureLevels[] =
{
    D3D_FEATURE_LEVEL_12_1,
    D3D_FEATURE_LEVEL_12_0,
    D3D_FEATURE_LEVEL_11_1,
    D3D_FEATURE_LEVEL_11_0,
};

D3D12_FEATURE_DATA_FEATURE_LEVELS featLevels =
{
    _countof(s_featureLevels), s_featureLevels, D3D_FEATURE_LEVEL_11_0
};

HRESULT hr = m_d3dDevice->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS,
    &featLevels, sizeof(featLevels));
if (SUCCEEDED(hr))
{
    m_d3dFeatureLevel = featLevels.MaxSupportedFeatureLevel;
}
else
{
    m_d3dFeatureLevel = m_d3dMinFeatureLevel;
}

请记住,D3D_FEATURE_LEVEL_12_0本质D3D_FEATURE_LEVEL_12_1上只是D3D_FEATURE_LEVEL_11_1一些强制性的可选功能。如果您的应用程序已经在 11.x 中检查它们,那么没有理由“要求”12.0 或 12.1。请参阅MSDN

对于绝大多数 Direct3D 12 游戏和应用程序来说,D3D_FEATURE_LEVEL_11_0还是D3D_FEATURE_LEVEL_11_1不错的选择。请记住,虽然 AMD/ATI 很早就支持 Feature Level 11.1,但 NVIDIA DirectX 11 部件在一段时间内仅支持 11.0 和一些可选功能。

于 2016-02-13T18:16:10.117 回答