в моем научном моделировании я получил огромные наборы данных (около 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;
Любые другие предложения?
VertexBufferDesc.ByteWidth
определяет размер ресурса, и после создания его невозможно расширить, как, например, с помощью. std::vector
, Если существует известный верхний предел размера этого буфера, вы можете просто установить ByteWidth
до максимального размера вам нужно. Если размер варьируется в широких пределах или обычно невелик, но иногда значительно больше, вы можете использовать какой-то гистерезис, чтобы решить, когда создавать новый буфер вершин. Например, если NewByteWidth > CurrentByteWidth
тогда вы можете создать буфер, который в два раза больше, или если NewByteWidth <= CurrentByteWidth / 4
тогда вы можете сэкономить память, воссоздав ее вдвое меньше.
Спасибо за ваш ответ! Это многое объясняет.
Кажется, я должен создавать новый буфер каждый раз, когда обновляю сущность. Надеюсь, это не будет стоить слишком много производительности. Я постараюсь ответить позже.