I'm trying to create a buffer in GPU memory to upload data from CPU. GPU access will be readonly. Data will be used as an input buffer for a compute shader.
CreateBuffer() fails with error 0x80070057 (E_INVALIDARG). I read the docs and read it again without discovering which argument cause the failure.
InitDevice() return success.
Here is an extract from my code:
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;
The code which fails is the following:
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;
When calling the function, I pass uElementSize=2, uCount=100 and pInitData pointing to an allocated 200 bytes buffer in CPU memory.
I don't understand what I'm doing wrong. Any help appreciated.
The answer has been given by Chuck Walbourn to the C++ question I asked there DirectCompute CreateBuffer fails with error 0x80070057 (E_INVALIDARG)
The most important part to debug this error is simply look at Delphi Event Viewer and just look the error message the API is triggering when debugging is enabled (I I already had enabled debugging but didn't figured that messages where output to the events windows).