DirectX 11:使用UpdateSubresource更新Vertex和Index缓冲区

时间:2015-10-15 21:37:28

标签: c++ directx buffer indices vertices

在我的科学模拟中,我有大量数据集(大约600000个顶点)以常规时间间隔(大约1秒)更新。

对于第一个数据集,我创建了一个缓冲区,如下所示:

mVertexStride = sizeof(VertexType);

D3D11_BUFFER_DESC VertexBufferDesc;
ZeroMemory(&VertexBufferDesc, sizeof(VertexBufferDesc));
VertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
VertexBufferDesc.ByteWidth = sizeof(VertexType) * numOfVertices;
VertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; //use as a vertex buffer
VertexBufferDesc.CPUAccessFlags = 0; 
VertexBufferDesc.MiscFlags = 0;

D3D11_SUBRESOURCE_DATA InitialSubData;
ZeroMemory(&InitialSubData, sizeof(InitialSubData));
InitialSubData.pSysMem = vertices;

HRESULT hr = device->CreateBuffer(&VertexBufferDesc, &InitialSubData, &mVertexBuffer);
if (FAILED(hr)) { return false; }
return true;

我使用类似的调用来创建索引缓冲区。

然后在1秒后我想更新整个数据集。所以我想要交换整个顶点和索引缓冲区。旧的顶点和索引被丢弃,而新的顶点和索引应该被写入缓冲区。

这一点引起了实际问题。我的代码现在看起来像这样:

deviceContext->UpdateSubresource(mVertexBuffer, 0, NULL, vertices, 0, 0);

对于索引缓冲区

deviceContext->UpdateSubresource(mIndexBuffer, 0, NULL, indices, 0, 0);

该代码有效(大部分时间),但问题是缓冲区的大小不会自动扩展。

例如,首先我有一个650000个顶点的数据集,然后我有一个有700000个顶点的数据集。第二组将填充到缓冲区中,但仅显示650000个顶点。有可见的洞。我该如何应对?无法在网络上或Microsoft帮助中找到任何内容。

即使我没有更新每一帧,我还应该使用map / unmap吗?

感谢任何帮助!

修改

在我的情况下,UpdateSubresource()似乎是错误的方法。我现在正在做的是删除旧缓冲区并创建一个新缓冲区。模拟仍然表现良好,"交换"在几毫秒内完成。我的代码如下所示:

if (mVertexBuffer != NULL)
{
    mVertexBuffer->Release();
    mVertexBuffer = NULL;
}

mVertexStride = sizeof(VertexType);

D3D11_BUFFER_DESC VertexBufferDesc;
ZeroMemory(&VertexBufferDesc, sizeof(VertexBufferDesc));
VertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
VertexBufferDesc.ByteWidth = sizeof(VertexType) * numOfVertices;
VertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; //use as a vertex buffer
VertexBufferDesc.CPUAccessFlags = 0; //D3D11_CPU_ACCESS_WRITE; //allow CPU to write in buffer
VertexBufferDesc.MiscFlags = 0;

D3D11_SUBRESOURCE_DATA InitialSubData;
ZeroMemory(&InitialSubData, sizeof(InitialSubData));
InitialSubData.pSysMem = vertices;

HRESULT hr = device->CreateBuffer(&VertexBufferDesc, &InitialSubData, &mVertexBuffer); // 1a) create input buffer
if (FAILED(hr)) { return false; }
return true;

还有其他建议吗?

2 个答案:

答案 0 :(得分:1)

VertexBufferDesc.ByteWidth定义资源的大小,并且在创建之后,没有办法扩展它,因为有例如std::vector。如果此缓冲区的大小已知已知上限,则只需将ByteWidth设置为您需要的最大大小即可。如果大小变化很大,或者通常较小但有时大得多,则可以使用某种滞后来决定何时创建新的顶点缓冲区。例如,如果NewByteWidth > CurrentByteWidth那么你可以创建一个大两倍的缓冲区,或者如果NewByteWidth <= CurrentByteWidth / 4那么你可以通过将它重新创建为一半来保存一些内存。

答案 1 :(得分:0)

感谢您的回复!这解释了很多。

似乎每次更新实体时我都要创建一个新的缓冲区。希望这不会花费太多的性能。我稍后会尝试回复。