c++ - DirectX11 D3D11_MAP 的差异

标签 c++ directx directx-11

我有一个顶点缓冲区,其中的某些部分每帧只需更新一次,因此我使用 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

Resource is mapped for writing; the previous contents of the resource will be undefined.

D3D11_MAP_WRITE_NO_OVERWRITE

Resource is mapped for writing; the existing contents of the resource cannot be overwritten (see Remarks).

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

最佳答案

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

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

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

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

关于c++ - DirectX11 D3D11_MAP 的差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23368880/

相关文章:

c++ - 硬编码 HLSL 着色器

directx - 如何判断系统DirectX是11还是11.1?

c++ - 编译 cpp 文件时出错 (ros)

c++ - 重载运算符

wpf - Windows 8 桌面应用程序的 future

c++ - IMFTransform::ProcessInput() "The buffer was too small to carry out the requested action."

c++ - Directx 11,将多个纹理发送到着色器

c++ - DirectX 项目模板在 Visual Studio 2017 中不可见

c++ - 如何在 C++ 中将枚举与用户输入一起使用

c++ - C++函数调用中参数括号()的结合性