报错: ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&basePsoDesc, IID_PPV_ARGS(&mPSO))); 参数错误
当 md3dDevice->CreateGraphicsPipelineState
调用返回 “参数错误” 时,意味着传递给该函数的 D3D12_GRAPHICS_PIPELINE_STATE_DESC
结构体(即 basePsoDesc
)中的某些参数存在问题。下面为你详细分析可能的原因及对应的解决办法:
1. 根签名(pRootSignature
)问题
- 问题描述:在
D3D12_GRAPHICS_PIPELINE_STATE_DESC
中,pRootSignature
是一个重要的参数。如果设置为nullptr
但实际上需要有效的根签名,或者根签名对象本身无效,就会导致创建管道状态对象失败。 - 解决办法:
- 确保根签名已经正确创建。如果需要使用根签名,在创建管道状态对象之前创建根签名,并将其指针赋值给
basePsoDesc.pRootSignature
。示例代码如下:
- 确保根签名已经正确创建。如果需要使用根签名,在创建管道状态对象之前创建根签名,并将其指针赋值给
// 创建根签名
CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc;
// 配置根签名描述符
// ...Microsoft::WRL::ComPtr<ID3DBlob> serializedRootSig = nullptr;
Microsoft::WRL::ComPtr<ID3DBlob> errorBlob = nullptr;
HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D12_ROOT_SIGNATURE_VERSION_1, &serializedRootSig, &errorBlob);
if (errorBlob != nullptr)
{OutputDebugStringA((char*)errorBlob->GetBufferPointer());
}
ThrowIfFailed(hr);ThrowIfFailed(md3dDevice->CreateRootSignature(0,serializedRootSig->GetBufferPointer(),serializedRootSig->GetBufferSize(),IID_PPV_ARGS(&mRootSignature)));// 设置管道状态对象描述符的根签名
basePsoDesc.pRootSignature = mRootSignature.Get();
2. 着色器字节码问题
- 问题描述:
VS
和PS
成员分别表示顶点着色器和像素着色器的字节码。如果字节码无效,例如编译着色器时出错,或者字节码指针和大小设置不正确,就会导致创建失败。 - 解决办法:
- 确保着色器编译成功。在编译着色器时,检查返回的
HRESULT
值,并处理可能的错误。示例代码如下:
- 确保着色器编译成功。在编译着色器时,检查返回的
Microsoft::WRL::ComPtr<ID3DBlob> vertexShaderBlob;
Microsoft::WRL::ComPtr<ID3DBlob> pixelShaderBlob;
UINT compileFlags = 0;
#if defined(DEBUG) || defined(_DEBUG)compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
#endif
HRESULT hr = D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "VS", "vs_5_0", compileFlags, 0, &vertexShaderBlob, nullptr);
if (FAILED(hr))
{if (D3D12_ERROR_FILE_NOT_FOUND == hr){throw std::exception("shaders.hlsl not found.");}else{// 获取编译错误信息ID3DBlob* errorBlob;D3DGetBlobPart(vertexShaderBlob.Get(), D3D_BLOB_ERROR_MESSAGE, 0, &errorBlob);if (errorBlob){std::cerr << static_cast<const char*>(errorBlob->GetBufferPointer()) << std::endl;errorBlob->Release();}throw std::exception("Vertex shader compilation failed.");}
}
ThrowIfFailed(hr);hr = D3DCompileFromFile(L"shaders.hlsl", nullptr, nullptr, "PS", "ps_5_0", compileFlags, 0, &pixelShaderBlob, nullptr);
ThrowIfFailed(hr);// 设置管道状态对象描述符的着色器字节码
basePsoDesc.VS = { vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize() };
basePsoDesc.PS = { pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize() };
3. 输入布局(InputLayout
)问题
- 问题描述:
InputLayout
定义了顶点数据的格式。如果输入布局的描述不正确,例如元素数量为 0 或者元素的格式设置错误,就会导致创建失败。 - 解决办法:
- 确保输入布局的描述正确。检查输入元素的数量、格式和偏移量等信息。示例代码如下:
std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout =
{{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};
basePsoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
4. 其他参数问题
- 问题描述:
D3D12_GRAPHICS_PIPELINE_STATE_DESC
中的其他参数,如RasterizerState
、BlendState
、DepthStencilState
等,如果设置不正确,也可能导致创建失败。 - 解决办法:
- 确保这些参数的设置符合你的需求。可以使用
CD3DX12
辅助类来设置默认值,例如:
- 确保这些参数的设置符合你的需求。可以使用
basePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
basePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
basePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);