【发布时间】:2014-04-30 01:02:09
【问题描述】:
我有一个顶点缓冲区,它的某些部分需要每帧更新一次,所以我将它创建为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 吗?
【问题讨论】:
标签: c++ directx directx-11