D3D11:映射顶点缓冲区时的E_OUTOFMEMORY

时间:2018-05-08 11:09:33

标签: c++ unity3d directx

在我的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 :(得分:4)

没有任何设备上下文方法是线程安全的。如果要从多个线程中使用它们,则需要手动同步所有调用,或使用多个(延迟)上下文,每个线程一个。请参阅Introduction to Multithreading in Direct3D 11

错误检查也应该更好:您需要始终检查返回的HRESULT值,因为如果失败,assert(mapped.pData);之类的内容仍可能成功。