You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DirectX11动态纹理Map/Unmap上传后渲染噪点问题求助

问题根因

你的代码存在两个核心错误,直接导致动态纹理渲染花屏:

  • 错误修改Map返回的结构体参数:D3D11_MAPPED_SUBRESOURCE是Map调用成功后由D3D运行时/驱动填充的输出参数,你在数据拷贝完成后手动修改本地变量的RowPitch、DepthPitch字段完全没有任何作用——这两个值代表GPU端纹理内存的真实行/深度跨度,修改栈上的本地变量不会改变GPU内存布局。
  • 未考虑动态纹理的行对齐要求:D3D11动态纹理的内存行跨度(即RowPitch)几乎永远不会等于纹理宽度 * 单像素字节数,驱动会将每行内存对齐到特定边界(通常为16字节/256字节,由硬件和驱动决定),行尾会预留未使用的填充字节。你直接按照连续内存整块拷贝源数据,会导致第一行之后的所有像素数据错位写入填充区,最终出现噪点、花屏现象。

你之前使用不可变纹理时渲染正常,是因为创建纹理阶段传入D3D11_SUBRESOURCE_DATA初始数据时,驱动会在内部自动完成源数据到GPU对齐内存的拷贝,不需要手动处理行对齐;但Map/Unmap流程是直接将GPU端已对齐的内存指针映射到CPU地址空间,必须手动处理行偏移。

修复方案

删除手动修改RowPitch、DepthPitch的无效代码,改为按行拷贝数据,拷贝时目标地址使用Map返回的真实行跨度做偏移:

D3D11_MAPPED_SUBRESOURCE subResource = {};
HRESULT mapResult = ImmediateContext->Map(dx11Texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &subResource);
if (SUCCEEDED(mapResult))
{
    const UINT singlePixelBytes = GraphicsFormatUtils::get_format_size(texture->get_format());
    const UINT srcRowBytes = texture->get_width() * singlePixelBytes;
    uint8_t* dstPtr = static_cast<uint8_t*>(subResource.pData);
    const uint8_t* srcPtr = static_cast<const uint8_t*>(desc.DataSet[0]);

    // 逐行拷贝,跳过每行末尾的驱动对齐填充字节
    for (UINT rowIdx = 0; rowIdx < texture->get_height(); ++rowIdx)
    {
        Memory::copy(dstPtr, srcPtr, srcRowBytes);
        dstPtr += subResource.RowPitch; // 目标指针按GPU实际行跨度偏移
        srcPtr += srcRowBytes; // 源指针按像素真实行宽偏移
    }

    ImmediateContext->Unmap(dx11Texture, 0);
}
额外排查项

如果修复后仍有异常,逐一核对以下配置:

  • 动态纹理创建参数必须匹配:Usage字段设置为D3D11_USAGE_DYNAMIC,CPUAccessFlags必须包含D3D11_CPU_ACCESS_WRITE,BindFlags仅保留D3D11_BIND_SHADER_RESOURCE即可,不要添加其他不兼容的标记。
  • 源数据格式必须和纹理创建时指定的DXGI_FORMAT完全匹配,避免出现RGBA/BGRA顺序混淆、通道位数不匹配的问题。
  • 不要在调用Map前提前初始化或修改subResource结构体的任何字段,所有字段值以Map调用成功后运行时填充的结果为准。

内容的提问来源于stack exchange,提问作者Barış Üçkardeş

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 00:06:36