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

如何将DirectX11 Texture2D转换为可在CPU上处理的图像

DirectX11 Texture2D 转CPU可访问图像实现方案

前置说明

只有源Texture2D绑定了D3D11_BIND_RENDER_TARGET或D3D11_BIND_SHADER_RESOURCE,且Usage类型不是D3D11_USAGE_IMMUTABLE时,才能通过资源复制的方式读取数据。如果源纹理是深度缓冲、多重采样纹理这类特殊资源,需要先做格式解析/转换再执行后续步骤。


具体实现步骤

步骤1:创建CPU可读的Staging纹理

Staging纹理是DX11专门用于CPU-GPU数据交互的资源类型,创建参数必须严格符合要求:

// 先获取源纹理的参数
D3D11_TEXTURE2D_DESC srcDesc;
pSrcTexture->GetDesc(&srcDesc);

D3D11_TEXTURE2D_DESC stagingDesc = {};
stagingDesc.Width = srcDesc.Width;
stagingDesc.Height = srcDesc.Height;
stagingDesc.MipLevels = 1; // 需要读取全Mip链就和srcDesc.MipLevels保持一致
stagingDesc.ArraySize = 1;
stagingDesc.Format = srcDesc.Format;
stagingDesc.SampleDesc.Count = 1;
stagingDesc.SampleDesc.Quality = 0;
stagingDesc.Usage = D3D11_USAGE_STAGING;
stagingDesc.BindFlags = 0;
stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
stagingDesc.MiscFlags = 0;

ID3D11Texture2D* pStagingTexture = nullptr;
HRESULT hr = pD3DDevice->CreateTexture2D(&stagingDesc, nullptr, &pStagingTexture);
if (FAILED(hr)) {
    // 自行添加错误处理逻辑
    return;
}

步骤2:复制源纹理数据到Staging纹理

调用CopyResource执行GPU侧的资源复制,该操作为异步执行,如果需要立即读取数据可以增加事件查询做同步,避免读取到未完成的脏数据:

// 多重采样纹理需要先执行ResolveSubresource解析为非多重采样纹理再复制
if (srcDesc.SampleDesc.Count > 1) {
    pImmediateContext->ResolveSubresource(pStagingTexture, 0, pSrcTexture, 0, srcDesc.Format);
} else {
    pImmediateContext->CopyResource(pStagingTexture, pSrcTexture);
}

步骤3:映射纹理获取CPU侧可操作数据

映射后拿到的指针可以直接拷贝到自定义缓冲区做后续处理(像素计算、格式转换、存盘等):

D3D11_MAPPED_SUBRESOURCE mappedRes;
hr = pImmediateContext->Map(pStagingTexture, 0, D3D11_MAP_READ, 0, &mappedRes);
if (SUCCEEDED(hr)) {
    // 按纹理格式计算单像素字节数,此处以常用的R8G8B8A8_UNORM为例
    const uint32_t pixelByteSize = 4;
    // 自行管理缓冲区生命周期,此处仅做示例
    uint8_t* pCpuImageBuffer = new uint8_t[srcDesc.Width * srcDesc.Height * pixelByteSize];
    
    // *不要直接按宽高整块拷贝,RowPitch存在对齐填充,必须逐行拷贝避免数据错位*
    for (uint32_t y = 0; y < srcDesc.Height; y++) {
        memcpy(
            pCpuImageBuffer + y * srcDesc.Width * pixelByteSize,
            (uint8_t*)mappedRes.pData + y * mappedRes.RowPitch,
            srcDesc.Width * pixelByteSize
        );
    }
    
    // 处理完成后必须调用Unmap释放资源
    pImmediateContext->Unmap(pStagingTexture, 0);
    // 此处pCpuImageBuffer就是CPU侧可自由处理的图像数据
}
// 用完释放Staging纹理资源,高频使用场景可以复用Staging纹理避免反复创建销毁开销
pStagingTexture->Release();

注意事项

  • 如果源纹理是BCn等压缩格式,映射拿到的是压缩后的数据,需要自行解压才能得到原始像素值,也可以在创建Staging纹理时指定非压缩格式,复制时由硬件完成格式转换
  • 同步逻辑如果处理不当会引发GPU-CPU互相等待的性能问题,非必要场景不要每帧都执行纹理读取操作

内容的提问来源于stack exchange,提问作者Mike Hawk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 05:54:01