【问题标题】:Differences of DirectX11 D3D11_MAPDirectX11 D3D11_MAP 的区别
【发布时间】:2014-04-30 01:02:09
【问题描述】:

我有一个顶点缓冲区,它的某些部分需要每帧更新一次,所以我将它创建为D3D11_USAGE_DYNAMICD3D11_CPU_ACCESS_WRITE

由于有很多顶点(大约 150k),我不想遍历整个缓冲区,只遍历标记为要更新的部分。

为此,我使用DirtyVertexBuffer 标志标记每个“区域”,然后跳过未标记的区域。要更新缓冲区,我使用D3D11_MAP_WRITE_NO_OVERWRITE。代码是:

VertexType *vertices;
D3D11_MAPPED_SUBRESOURCE mappedResource;
Vertex *vertex;
HRESULT result;

result = context->Map(m_vertexBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
if (FAILED(result))
    return;

vertices = (DirectX::VertexPositionNormalTexture*)mappedResource.pData;

for (auto &material : materials) {
    if ((material.dirty & Material::Dirty::VertexBuffer) == 0) continue;

    material.dirty &= ~Material::Dirty::VertexBuffer;

    // Update vertex data
}

// release the access to the buffer
context->Unmap(m_vertexBuffer, 0);

我的问题是:为什么这里需要D3D_MAP_WRITE_NO_OVERWRITE,而不是D3D_MAP_WRITE_DISCARD

如果我使用后者,顶点缓冲区似乎是“归零”的(仅渲染更改的区域)。 MSDN 说:

D3D11_MAP_WRITE_DISCARD

为写入映射资源;资源的先前内容将是未定义的。

D3D11_MAP_WRITE_NO_OVERWRITE

为写入映射资源;资源的现有内容不能被覆盖(见备注)。

但是既然我映射了资源,难道不应该将整个缓冲区从 VRAM 复制到系统 RAM,然后在我取消映射时,再回到 VRAM 吗?

【问题讨论】:

    标签: c++ directx directx-11


    【解决方案1】:

    经过一番思考,我想我找到了答案,有人可以确认吗?

    当使用D3D11_USAGE_DYNAMICD3D11_CPU_ACCESS_WRITE 时,CPU 将只能用于写入(好的,这很清楚)。然后,在每次调用 ID3D11DeviceContext::Map 时,一个临时缓冲区(使用 _aligned_malloc 创建的东西),其状态未定义。

    然后,当使用D3D11_MAP_WRITE_DISCARD 时,先前的顶点缓冲区将被丢弃,这意味着只保留更改的部分,因为它们存在于该临时缓冲区中。

    另一方面,在使用D3D11_MAP_WRITE_NO_OVERWRITE 时,会保留之前的顶点缓冲区,只写入更改的部分。

    【讨论】:

    • 这或多或少是正确的。缓冲区并不是真正的“临时”,而只是未来命令将使用的新缓冲区,因此硬件不需要等到原始缓冲区完成使用。使用NO_OVERWRITE时,开发者承诺没有危险,硬件不需要等待,所以不需要额外的缓冲区。
    • 但是Map 不是“返回”一个 RAM 缓冲区吗?在这种情况下,我称之为“临时”,因为假设如果第一条语句为真,那么Unmap 在将 RAM 缓冲区复制到 VRAM 时会释放它。
    • 不完全是 - 在某些系统上,它直接通过视频内存。但是,是的,在离散 GPU 上,会创建一个单独的缓冲区。但是当您使用DISCARD 时,您丢失旧数据的原因是因为 video 内存未初始化,而不是因为映射内存未初始化。映射写入为write-combined,因此未初始化的数据不会被传输。
    • 非常感谢您的启发,现在我明白了这些缓冲区是如何工作的:)
    • 或者您可以使用 DX11.1+ 中的替代 ID3D11DeviceContext1::UpdateSubresource1 函数(基本上支持部分更新)
    猜你喜欢
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多