DirectX 11带初始数据创建纹理失败,HRESULT参数错误求助
解决DirectX 11创建带初始数据的R8_UINT纹理失败问题
我帮你排查出了问题的核心:初始数据的内存布局和纹理格式要求不匹配,这才导致CreateTexture2D返回"参数不正确"的错误。下面分点拆解原因,再给你修正后的代码:
1. 数据类型和纹理格式不匹配
你设置的纹理格式是DXGI_FORMAT_R8_UINT,这意味着每个像素只占1个无符号字节,但最开始你用UINT*(4字节/元素)来分配内存:
UINT* data = (UINT*)malloc(sri_w * sri_h * sizeof(UINT));
哪怕你把每个UINT都设为0,内存里每个"像素"实际占了4字节,和纹理期望的1字节完全对不上,DirectX根本没法正确解析这个数据,自然创建失败。
2. SysMemPitch参数设置错误
D3D11_SUBRESOURCE_DATA::SysMemPitch要求的是每行数据的字节数,不是像素数:
- 用
UINT*的时候,每行字节数应该是sri_w * sizeof(UINT),但R8_UINT纹理只认sri_w * sizeof(unsigned char)的行字节数,两者不匹配直接触发参数错误。 - 就算你后来改成
unsigned char*,如果没同步调整SysMemPitch的设置逻辑(或者代码改得不彻底),还是会出问题。
修正后的完整代码
下面是调整后的正确实现,解决了上面两个问题,还加了内存泄漏防护:
UINT dwRtWidth = 2560; UINT dwRtHeight = 1440; D3D11_TEXTURE2D_DESC srcDesc; ZeroMemory(&srcDesc, sizeof(srcDesc)); int sri_w = dwRtWidth / NV_VARIABLE_PIXEL_SHADING_TILE_WIDTH; int sri_h = dwRtHeight / NV_VARIABLE_PIXEL_SHADING_TILE_HEIGHT; srcDesc.Width = sri_w; srcDesc.Height = sri_h; srcDesc.ArraySize = 1; srcDesc.Format = DXGI_FORMAT_R8_UINT; srcDesc.SampleDesc.Count = 1; srcDesc.SampleDesc.Quality = 0; srcDesc.Usage = D3D11_USAGE_DEFAULT; srcDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; srcDesc.CPUAccessFlags = 0; srcDesc.MiscFlags = 0; D3D11_SUBRESOURCE_DATA initialData; // 用unsigned char匹配R8_UINT的1字节/像素格式 unsigned char* data = (unsigned char*)malloc(sri_w * sri_h * sizeof(unsigned char)); if (!data) { LOG("Failed to allocate memory for shading rate surface"); return; } // 用memset快速初始化所有像素为0(对应最低着色率) memset(data, 0, sri_w * sri_h * sizeof(unsigned char)); initialData.pSysMem = data; // SysMemPitch设为每行的字节数,R8_UINT下就是像素宽度×1字节 initialData.SysMemPitch = sri_w * sizeof(unsigned char); initialData.SysMemSlicePitch = 0; // 2D纹理不需要设置这个值 HRESULT hr = s_device->CreateTexture2D(&srcDesc, &initialData, &pShadingRateSurface); if (FAILED(hr)) { LOG("Texture not created"); LOG(std::system_category().message(hr)); free(data); // 创建失败也要释放内存,避免泄漏 } else { LOG("Texture created"); free(data); }
额外要注意的点
- 确认
NV_VARIABLE_PIXEL_SHADING_TILE_WIDTH和NV_VARIABLE_PIXEL_SHADING_TILE_HEIGHT是正确的常量(一般是16,对应VRS的16x16 tile),确保sri_w和sri_h是整数,不然纹理宽高设置无效也会触发参数错误。 - 内存分配后一定要做空指针检查,别直接访问非法内存。
- 不管纹理创建成功还是失败,都要释放堆上分配的
data缓冲区,避免内存泄漏。
内容的提问来源于stack exchange,提问作者Krzysztof Wolski




