我正在尝试在GPU内存中创建一个缓冲区以从CPU上传数据。GPU 访问将是只读的。数据将用作计算着色器的输入缓冲区。
CreateBuffer(( 失败,错误0x80070057 (E_INVALIDARG(。我阅读了文档并再次阅读,但没有发现哪个参数导致失败。
InitDevice(( 返回成功。
这是我的代码摘录:
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 和 pInitData 指向 CPU 内存中分配的 200 字节缓冲区。
我不明白我做错了什么。 任何帮助表示赞赏。
Chuck Walbourn 对我在那里提出的C++问题给出了答案 DirectCompute CreateBuffer 失败,错误0x80070057 (E_INVALIDARG(
调试此错误最重要的部分是简单地查看 Delphi 事件查看器,然后查看启用调试时 API 触发的错误消息(我已经启用了调试,但没有想到输出到事件窗口的消息(。