DirectCompute CreateBuffer 失败并出现错误 0x80070057 (E_INVALIDARG)
DirectCompute CreateBuffer fails with error 0x80070057 (E_INVALIDARG)
我正在尝试在 GPU 内存中创建缓冲区以从 CPU 上传数据。 GPU 访问将是只读的。数据将用作计算着色器的输入缓冲区。
CreateBuffer() 失败,错误为 0x80070057 (E_INVALIDARG)。我阅读了文档并再次阅读,但没有发现是哪个参数导致了失败。
这是我标记失败的代码摘录:
HRESULT hr = S_OK;
RECT rc;
GetClientRect( g_hWnd, &rc );
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
UINT createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_DRIVER_TYPE driverTypes[] =
{
#ifdef WARP
D3D_DRIVER_TYPE_REFERENCE,
#else
D3D_DRIVER_TYPE_HARDWARE,
#endif
};
UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] );
DXGI_SWAP_CHAIN_DESC sd;
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 | DXGI_USAGE_UNORDERED_ACCESS | DXGI_USAGE_SHADER_INPUT;
sd.OutputWindow = g_hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
D3D_FEATURE_LEVEL FeatureLevels = D3D_FEATURE_LEVEL_11_0;
for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
{
g_driverType = driverTypes[driverTypeIndex];
hr = D3D11CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, &FeatureLevels,1,
D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, NULL, &g_pImmediateContext );
if( SUCCEEDED( hr ) )
break;
}
if( FAILED( hr ) )
return hr;
// check if GPU supports doubles
D3D11_FEATURE_DATA_DOUBLES fdDoubleSupport;
g_pd3dDevice->CheckFeatureSupport( D3D11_FEATURE_DOUBLES, &fdDoubleSupport, sizeof(fdDoubleSupport) );
GPUcanDoDoubles = fdDoubleSupport.DoublePrecisionFloatShaderOps;
D3D11_BUFFER_DESC desc;
BYTE Data[200];
D3D11_SUBRESOURCE_DATA InitData;
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.ByteWidth = 200;
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
desc.StructureByteStride = 2;
InitData.pSysMem = Data;
hr = g_pd3dDevice->CreateBuffer(&desc, &InitData, &g_pcbFractal); // <== E_INVALIARG here
// Create constant buffer
D3D11_BUFFER_DESC Desc;
Desc.Usage = D3D11_USAGE_DYNAMIC;
Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
Desc.MiscFlags = 0;
Desc.ByteWidth = ((( (GPUcanDoDoubles) ? sizeof(MandelConstantsDoubles) : sizeof(MandelConstantsNoDoubles) ) + 15)/16)*16; // must be multiple of 16 bytes
hr = g_pd3dDevice->CreateBuffer( &Desc, NULL, &g_pcbFractal); // This one succeed
感谢任何帮助。
启用 Direct3D 11 Device Debugging 并查看调试输出 window 回答了您的问题:
D3D11 ERROR: ID3D11Device::CreateBuffer: When creating a buffer with the MiscFlag D3D11_RESOURCE_MISC_BUFFER_STRUCTURED specified, the StructureByteStride must be greater than zero, no greater than 2048, and a multiple of 4. [ STATE_CREATION ERROR #2097339: CREATEBUFFER_INVALIDSTRUCTURESTRIDE]
如果你解决了这个问题,你会得到:
D3D11 ERROR: ID3D11Device::CreateBuffer: A D3D11_USAGE_DYNAMIC Resource cannot be bound to certain parts of the graphics pipeline, but must have at least one BindFlags bit set. The BindFlags bits (0x88) have the following settings: D3D11_BIND_STREAM_OUTPUT (0), D3D11_BIND_RENDER_TARGET (0), D3D11_BIND_DEPTH_STENCIL (0), D3D11_BIND_UNORDERED_ACCESS (1). [ STATE_CREATION ERROR #64: CREATEBUFFER_INVALIDBINDFLAGS]
这基本上是在告诉您不能将 D3D11_USAGE_DYNAMIC
与 D3D11_BIND_UNORDERED_ACCESS
结合使用
我正在尝试在 GPU 内存中创建缓冲区以从 CPU 上传数据。 GPU 访问将是只读的。数据将用作计算着色器的输入缓冲区。
CreateBuffer() 失败,错误为 0x80070057 (E_INVALIDARG)。我阅读了文档并再次阅读,但没有发现是哪个参数导致了失败。
这是我标记失败的代码摘录:
HRESULT hr = S_OK;
RECT rc;
GetClientRect( g_hWnd, &rc );
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
UINT createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_DRIVER_TYPE driverTypes[] =
{
#ifdef WARP
D3D_DRIVER_TYPE_REFERENCE,
#else
D3D_DRIVER_TYPE_HARDWARE,
#endif
};
UINT numDriverTypes = sizeof( driverTypes ) / sizeof( driverTypes[0] );
DXGI_SWAP_CHAIN_DESC sd;
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 | DXGI_USAGE_UNORDERED_ACCESS | DXGI_USAGE_SHADER_INPUT;
sd.OutputWindow = g_hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
D3D_FEATURE_LEVEL FeatureLevels = D3D_FEATURE_LEVEL_11_0;
for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
{
g_driverType = driverTypes[driverTypeIndex];
hr = D3D11CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, &FeatureLevels,1,
D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, NULL, &g_pImmediateContext );
if( SUCCEEDED( hr ) )
break;
}
if( FAILED( hr ) )
return hr;
// check if GPU supports doubles
D3D11_FEATURE_DATA_DOUBLES fdDoubleSupport;
g_pd3dDevice->CheckFeatureSupport( D3D11_FEATURE_DOUBLES, &fdDoubleSupport, sizeof(fdDoubleSupport) );
GPUcanDoDoubles = fdDoubleSupport.DoublePrecisionFloatShaderOps;
D3D11_BUFFER_DESC desc;
BYTE Data[200];
D3D11_SUBRESOURCE_DATA InitData;
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.ByteWidth = 200;
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
desc.StructureByteStride = 2;
InitData.pSysMem = Data;
hr = g_pd3dDevice->CreateBuffer(&desc, &InitData, &g_pcbFractal); // <== E_INVALIARG here
// Create constant buffer
D3D11_BUFFER_DESC Desc;
Desc.Usage = D3D11_USAGE_DYNAMIC;
Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
Desc.MiscFlags = 0;
Desc.ByteWidth = ((( (GPUcanDoDoubles) ? sizeof(MandelConstantsDoubles) : sizeof(MandelConstantsNoDoubles) ) + 15)/16)*16; // must be multiple of 16 bytes
hr = g_pd3dDevice->CreateBuffer( &Desc, NULL, &g_pcbFractal); // This one succeed
感谢任何帮助。
启用 Direct3D 11 Device Debugging 并查看调试输出 window 回答了您的问题:
D3D11 ERROR: ID3D11Device::CreateBuffer: When creating a buffer with the MiscFlag D3D11_RESOURCE_MISC_BUFFER_STRUCTURED specified, the StructureByteStride must be greater than zero, no greater than 2048, and a multiple of 4. [ STATE_CREATION ERROR #2097339: CREATEBUFFER_INVALIDSTRUCTURESTRIDE]
如果你解决了这个问题,你会得到:
D3D11 ERROR: ID3D11Device::CreateBuffer: A D3D11_USAGE_DYNAMIC Resource cannot be bound to certain parts of the graphics pipeline, but must have at least one BindFlags bit set. The BindFlags bits (0x88) have the following settings: D3D11_BIND_STREAM_OUTPUT (0), D3D11_BIND_RENDER_TARGET (0), D3D11_BIND_DEPTH_STENCIL (0), D3D11_BIND_UNORDERED_ACCESS (1). [ STATE_CREATION ERROR #64: CREATEBUFFER_INVALIDBINDFLAGS]
这基本上是在告诉您不能将 D3D11_USAGE_DYNAMIC
与 D3D11_BIND_UNORDERED_ACCESS