D3D11: E_OUTOFMEMORY при отображении буфера вершин - PullRequest
0 голосов
/ 08 мая 2018

В моей игре Unity мне нужно изменить множество графических ресурсов, таких как текстуры и буферы вершин, с помощью собственного кода, чтобы сохранить хорошую производительность.

Проблемы начинаются, когда код вызывает ID3D11ImmediateContext :: Map несколько раз за очень короткое время (я имею в виду очень короткий - вызывается из разных потоков, работающих параллельно). Нет правила, если отображение успешно или нет. Вызов метода выглядит как

ID3D11DeviceContext* sU_m_D_context;


void* BeginModifyingVBO(void* bufferHandle)
{
    ID3D11Buffer* d3dbuf = static_cast<ID3D11Buffer*>(bufferHandle);

    D3D11_MAPPED_SUBRESOURCE mapped;
    HRESULT res = sU_m_D_context->Map(d3dbuf, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);

    assert(mapped.pData);

    return mapped.pData;
}


void FinishModifyingVBO(void* bufferHandle)
{
    ID3D11Buffer* d3dbuf = static_cast<ID3D11Buffer*>(bufferHandle);

    sU_m_D_context->Unmap(d3dbuf, 0);
}



std::mutex sU_m_D_locker;

void Mesh::ApplyBuffer()
{
    sU_m_D_locker.lock();

    // map buffer
    VBVertex* mappedBuffer = (VBVertex*)BeginModifyingVBO(this->currentBufferPtr);

    memcpy(mappedBuffer, this->mainBuffer, this->mainBufferLength * sizeof(VBVertex));

    // unmap buffer
    FinishModifyingVBO(this->currentBufferPtr);

    sU_m_D_locker.unlock();

    this->markedAsChanged = false;
}

где d3dbuf - динамический буфер вершин. Я не знаю почему, но иногда результатом является E_OUTOFMEMORY, несмотря на то, что есть много свободной памяти. Я пытался окружить код мьютексами - безрезультатно.

Это действительно проблема с памятью или что-то менее очевидное?

1 Ответ

0 голосов
/ 08 мая 2018

Ни один из методов контекста устройства не является поточно-ориентированным. Если вы собираетесь использовать их из нескольких потоков, вам нужно будет либо вручную синхронизировать все вызовы, либо использовать несколько (отложенных) контекстов, по одному на поток. См. Введение в многопоточность в Direct3D 11 .

Также проверка ошибок должна быть лучше: вам нужно всегда проверять возвращенные HRESULT значения, потому что в случае сбоя что-то вроде assert(mapped.pData); все еще может быть успешным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...