DirectX/DirectCompute CreateBuffer 失败,错误为 0x80070057 (E_INVALIDARG)

DirectX/DirectCompute CreateBuffer failure with error 0x80070057 (E_INVALIDARG)

我正在尝试在 GPU 内存中创建缓冲区以从 CPU 上传数据。 GPU 访问将是只读的。数据将用作计算着色器的输入缓冲区。

CreateBuffer() 失败,错误为 0x80070057 (E_INVALIDARG)。我阅读了文档并再次阅读,但没有发现是哪个参数导致了失败。

InitDevice() return 成功。

这是我的代码的摘录:

function TGpuImageControl.InitDevice: HRESULT;
var
    hr                : HRESULT;
    createDeviceFlags : UINT;
    driverTypes       : array [0..0] of D3D_DRIVER_TYPE;
    numDriverTypes    : UINT;
    driverTypeIndex   : UINT;
    sd                : DXGI_SWAP_CHAIN_DESC;
    FeatureLevels     : D3D_FEATURE_LEVEL;
    featureLevel      : D3D_FEATURE_LEVEL;
const
    D3D10_SHADER_DEBUG = 1;
begin
    hr     := S_OK;

    createDeviceFlags := 0;
{$ifdef DEBUG}
    createDeviceFlags := createDeviceFlags or D3D11_CREATE_DEVICE_DEBUG;
{$endif}

{$ifdef WARP}
    driverTypes[0] := D3D_DRIVER_TYPE_REFERENCE;
{$else}
    driverTypes[0] := D3D_DRIVER_TYPE_HARDWARE;
{$endif}
    numDriverTypes := SizeOf(driverTypes) div SizeOf(driverTypes[0]);

    ZeroMemory(@sd, SizeOf(sd));
    sd.BufferCount                        := 1;
    sd.BufferDesc.Width                   := width;
    sd.BufferDesc.Height                  := height;
    sd.BufferDesc.Format                  := DXGI_FORMAT_R8G8B8A8_UNORM;
    sd.BufferDesc.RefreshRate.Numerator   := 60;
    sd.BufferDesc.RefreshRate.Denominator := 1;
    sd.BufferUsage                        := DXGI_USAGE_RENDER_TARGET_OUTPUT or
                                             DXGI_USAGE_UNORDERED_ACCESS;//     or
                                             //DXGI_USAGE_SHADER_INPUT;
    sd.OutputWindow                       := Handle;
    sd.SampleDesc.Count                   := 1;
    sd.SampleDesc.Quality                 := 0;
    sd.Windowed                           := TRUE;
    //sd.Flags                            := DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;

    FeatureLevels :=   D3D_FEATURE_LEVEL_11_0;

    for driverTypeIndex := 0 to numDriverTypes do begin
        g_driverType := driverTypes[driverTypeIndex];
        hr := D3D11CreateDeviceAndSwapChain(
                  nil,                    // Graphic Adapter, use default
                  g_driverType,           // Driver type to use
                  0,                      // HModule for software driver
                  createDeviceFlags,      // Create flags
                  @FeatureLevels,         // Feature levels
                  1,                      // Feature level size
                  D3D11_SDK_VERSION,      // SDK Version
                  @sd,                    // Swap Chain descriptor
                  g_pSwapChain,           // Out: Created swap chain
                  g_pd3dDevice,           // Out: Created device
                  featureLevel,           // Out: Feature level
                  g_pImmediateContext);   // Out: Context
        if SUCCEEDED(hr) then
            break;
    end;
    if FAILED(hr) then begin
        Result := hr;
        Exit;
    end;

    ImageResize();

    Result := S_OK;
end;

procedure TGpuImageControl.ImageResize;
var
    hr       : HRESULT;
    sd       : DXGI_SWAP_CHAIN_DESC;
    pTexture : ID3D11Texture2D;
    vp       : D3D11_VIEWPORT;
begin
    if g_pd3dDevice = nil then
        Exit;

    // release first else resize problem
    SAFE_RELEASE(IUnknown(g_pComputeOutput));

    g_pSwapChain.GetDesc(sd);
    hr := g_pSwapChain.ResizeBuffers(sd.BufferCount,
                                     Width,
                                     Height,
                                     sd.BufferDesc.Format,
                                     0);                   // Swap chain flags
    if FAILED(hr) then begin
        ShowError('SwapChain.ResizeBuffers failed with error %d', [hr]);
        Exit;
    end;

    hr := g_pSwapChain.GetBuffer(0, TGUID(ID3D11Texture2D), pTexture);
    if FAILED(hr) then begin
        ShowError('SwapChain.GetBuffer failed with error %d', [hr]);
        Exit;
    end;

    // create shader unordered access view on back buffer for compute shader to write into texture
    hr := g_pd3dDevice.CreateUnorderedAccessView(pTexture,
                                                 nil,
                                                 g_pComputeOutput);
    if FAILED(hr) then begin
        ShowError('pd3dDevice.CreateUnorderedAccessView failed with error %d', [hr]);
        Exit;
    end;

    pTexture := nil;

    // Setup the viewport
    vp.Width    := Width;
    vp.Height   := Height;
    vp.MinDepth := 0.0;
    vp.MaxDepth := 1.0;
    vp.TopLeftX := 0;
    vp.TopLeftY := 0;
    g_pImmediateContext.RSSetViewports(1, @vp);
end;

失败的代码如下:

function TGpuImageControl.CreateStructuredBuffer(
    uElementSize : UINT;
    uCount       : UINT;
    pInitData    : Pointer;
    out ppBufOut : ID3D11Buffer): HRESULT;
var
    desc     : D3D11_BUFFER_DESC;
    InitData : D3D11_SUBRESOURCE_DATA;
begin
    ppBufOut := nil;

    ZeroMemory(@desc, SizeOf(desc));
    desc.BindFlags           := D3D11_BIND_UNORDERED_ACCESS or
                                D3D11_BIND_SHADER_RESOURCE;
    desc.Usage               := D3D11_USAGE_DYNAMIC;
    desc.CPUAccessFlags      := D3D11_CPU_ACCESS_WRITE;
    desc.ByteWidth           := uElementSize * uCount;
    desc.MiscFlags           := UINT(D3D11_RESOURCE_MISC_BUFFER_STRUCTURED);
    desc.StructureByteStride := uElementSize;

    if pInitData <> nil then begin
        InitData.pSysMem := pInitData;
        Result := g_pd3dDevice.CreateBuffer(desc, @InitData, ppBufOut);
    end
    else
        Result := g_pd3dDevice.CreateBuffer(desc, nil, ppBufOut);
end;

调用该函数时,我传递了 uElementSize=2、uCount=100 和指向 CPU 内存中分配的 200 字节缓冲区的 pInitData。

我不明白我做错了什么。 任何帮助表示赞赏。

Chuck Walbourn 对我在那里提出的 C++ 问题给出了答案

调试此错误最重要的部分是简单地查看 Delphi 事件查看器并查看 API 在启用调试时触发的错误消息(我已经启用了调试但没有没想到消息输出到事件 windows).