D3D11创建绑定Unordered Access View的2D纹理返回E_INVALIDARG问题
问题说明
我尝试使用GPU对2D数组进行数学运算,将无mipmap、格式为R32_FLOAT的2D纹理绑定Shader Resource View传入计算着色器,该流程运行正常,纹理可成功传入着色器并正常寻址。
但我在为同类2D纹理创建Unordered Access View时遇到阻塞:调用CreateUnorderedAccessView(...)返回E_INVALIDARG,但我无法获取更详细的错误信息。只要使用D3D_BIND_UNORDERED_ACCESS标记,调用CreateTexture2D(...)也会出现相同问题。
我的设备支持D3D11_0和cs_5_0,对应实现代码如下:
HRESULT Create_Simple_Texture_2D(ID3D11Device* device, ID3D11Texture2D** texture, UINT width, UINT height, void* initdata, UINT initsize) { *texture = nullptr; UINT elementsize = sizeof(float); DXGI_FORMAT format = DXGI_FORMAT_R32_FLOAT; D3D11_TEXTURE2D_DESC desc = {}; { // 该配置可正常运行 // desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; // 输入到GPU // desc.Usage = D3D11_USAGE_DEFAULT; // GPU可读写 // desc.CPUAccessFlags = 0; // 无CPU访问权限 // 该配置也可正常运行 // desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; // 输入到GPU // desc.Usage = D3D11_USAGE_DYNAMIC; // CPU写入 -> GPU读取 // desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; // CPU可写入 // 该配置同样正常 // desc.BindFlags = 0; // // desc.Usage = D3D11_USAGE_STAGING; // // desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; // CPU可读取 // 但该配置无法运行: desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; desc.Usage = D3D11_USAGE_DEFAULT; // GPU可读写 desc.CPUAccessFlags = 0; // 除创建阶段外无CPU访问权限 desc.Width = width; desc.Height = height; desc.Format = format; // 见上方定义 desc.ArraySize = 1; // 单纹理 desc.MipLevels = 1; // 无额外mipmap desc.MiscFlags = 0; { desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN; } } const UINT expected = desc.Width * desc.Height * desc.ArraySize * elementsize; if (initdata && (initsize != expected)) wcprintf("\n\tWARNING: declared array size mismatch in Create_Simple_Texture_2D(...)\n\n"); D3D11_SUBRESOURCE_DATA sub = {}; { sub.pSysMem = (void*)(new char[expected]); sub.SysMemPitch = desc.Width * elementsize; sub.SysMemSlicePitch = 0; const UINT copysize = min(expected, initsize); if (sub.pSysMem && initdata && copysize) memcpy((void*)sub.pSysMem, initdata, copysize); } HRESULT result = device->CreateTexture2D(&desc, &sub, texture); if (sub.pSysMem) delete[] sub.pSysMem; return result; }
故障原因与修复方案
故障出在纹理描述的多重采样配置不符合UAV的创建要求:
- D3D11中Unordered Access View不支持多重采样纹理,你当前
SampleDesc.Count虽然设为1(非多重采样),但SampleDesc.Quality错误使用了D3D11_STANDARD_MULTISAMPLE_PATTERN,当采样计数为1时,Quality必须设置为0,否则会触发E_INVALIDARG错误。 - R32_FLOAT格式本身是支持UAV绑定的,其余参数配置无问题。
修复方法
将代码中SampleDesc的配置修改为如下内容即可:
desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0;
调试建议
如果后续遇到类似参数错误,可在创建设备时添加D3D11_CREATE_DEVICE_DEBUG标志开启调试层,即可在IDE的输出窗口看到详细的错误原因说明,大幅提升排查效率。
内容的提问来源于stack exchange,提问作者kppodd
相关产品推荐
相关产品推荐

