DirectX 11: используйте UpdateSubresource для обновления буферов вершин и индексов

в моем научном моделировании я получил огромные наборы данных (около 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.

Должен ли я использовать карту / 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;

Любые другие предложения?

1

Решение

VertexBufferDesc.ByteWidth определяет размер ресурса, и после создания его невозможно расширить, как, например, с помощью. std::vector, Если существует известный верхний предел размера этого буфера, вы можете просто установить ByteWidth до максимального размера вам нужно. Если размер варьируется в широких пределах или обычно невелик, но иногда значительно больше, вы можете использовать какой-то гистерезис, чтобы решить, когда создавать новый буфер вершин. Например, если NewByteWidth > CurrentByteWidth тогда вы можете создать буфер, который в два раза больше, или если NewByteWidth <= CurrentByteWidth / 4 тогда вы можете сэкономить память, воссоздав ее вдвое меньше.

1

Другие решения

Спасибо за ваш ответ! Это многое объясняет.

Кажется, я должен создавать новый буфер каждый раз, когда обновляю сущность. Надеюсь, это не будет стоить слишком много производительности. Я постараюсь ответить позже.

0

По вопросам рекламы [email protected]