Differences of DirectX11 D3D11_MAP

Differences of DirectX11 D3D11_MAP

本文关键字:MAP D3D11 DirectX11 of Differences      更新时间:2023-10-16

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

由于有很多顶点(大约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吗?

经过思考,我想我找到了答案,有人能证实吗?

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

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

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