DirectX11 D3D11_MAP的差异

时间:2014-04-29 15:24:53

标签: c++ directx directx-11

我有一个顶点缓冲区,它的某些部分需要每帧更新一次,因此我使用D3D11_USAGE_DYNAMIC将其创建为D3D11_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?

1 个答案:

答案 0 :(得分:1)

经过一番思考后,我想我找到了答案,有人可以证实这一点吗?

使用D3D11_USAGE_DYNAMICD3D11_CPU_ACCESS_WRITE时,CPU只能进行写入访问(确定,非常清楚)。然后,在每次调用ID3D11DeviceContext::Map时,临时缓冲区(使用_aligned_malloc创建的东西),状态未定义。

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

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