在 Directx10 和 11 中更新顶点缓冲区

Updating vertex buffer in Directx10 and 11

我在我的程序中使用 Directx10。当我尝试更改顶点的位置时出现错误:

Exception thrown at 0x558CA083 (d3d10core.dll) in NBodyProblemDebug.exe: 0xC0000005: Access violation reading location 0x00000000.

它发生在 运行 时间的下一个代码执行期间:

    D3D10_MAPPED_TEXTURE3D resourse;        
    ZeroMemory(&resourse, sizeof(D3D10_MAPPED_TEXTURE3D));
    g_pVertexBuffer->Map(D3D10_MAP_WRITE_DISCARD, 0, &resourse.pData); //exception is thrown here
    memcpy(resourse.pData, positions, 4 * n_bodies * sizeof(float));
    g_pVertexBuffer->Unmap();

其中veкtex缓冲区初始化如下:

    float * positions;
    ID3D10Buffer*  g_pVertexBuffer = nullptr;
    D3D10_BUFFER_DESC bd;
    ZeroMemory( &bd, sizeof(bd) );
    bd.Usage = D3D10_USAGE_DYNAMIC;
    bd.ByteWidth = sizeof( SimpleVertex ) * bodies;
    bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
    bd.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
    D3D10_SUBRESOURCE_DATA InitData;
    ZeroMemory( &InitData, sizeof(InitData) );
    InitData.pSysMem = positions;
    result = m_device->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );

应该怎么做才能修复它?此代码是否与 Directx11 中使用的代码相当:

 D3D11_MAPPED_SUBRESOURCE resourse;
 ZeroMemory(&resourse, sizeof(D3D11_MAPPED_SUBRESOURCE));
 g_pImmediateContext->Map(g_pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &resourse);
 memcpy(resourse.pData, positions, 4 * bodies * sizeof(float));     
 g_pImmediateContext->Unmap(g_pVertexBuffer, 0);

您的代码没有进行任何错误检查。每当 COM API return 是 HRESULT 时,您必须检查它是否失败。如果忽略 return 值是安全的,那么它将 return void。您应该使用 SUCCEEDEDFAILED 宏来检查结果,或者采用类似 ThrowIfFailed.

的方法
D3D11_MAPPED_SUBRESOURCE resource = {};
if ( SUCCEEDED(
    g_pImmediateContext->Map(g_pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD,
       0, &resource) )
{
    memcpy(resourse.pData, positions, 4 * bodies * sizeof(float));     
    g_pImmediateContext->Unmap(g_pVertexBuffer, 0);
}

如果您注意到异常在 Map 的行上抛出,那么您可能在程序的早期遗漏了一个失败的 HRESULT,导致 g_pImmediateContext 仍然是 nullptr .

Note that ZeroMemory is very old-school. You only need it if you are using a version of Visual C++ prior to VS 2013. With VS 2013 or later, C++11 uniform initialization rules means D3D11_MAPPED_SUBRESOURCE resource = {}; is guaranteed to be filling the structure with zeros.

如果在适当的地方检查了所有 HRESULTs ,调试 DirectX 应用程序的第二步是启用 DEBUG 设备。然后,这将在调试输出 window 中提供有关任何失败的更多详细信息,这将帮助您查明程序中的失败案例。参见 Anatomy of Direct3D 11 Create Device and Direct3D SDK Debug Layer Tricks

顺便说一句,根据您的风格,您正在为 COM 接口使用原始指针。你应该考虑采用像 ComPtr.

这样的智能指针

There's no reason at all to continue to use DirectX 10. All supported platforms that can run DirectX 10 can run DirectX 11. DirectX 11 supports more hardware, has better utility library support, better tool support, and is the current 'mainstream' version of DirectX. Don't use DirectX 10. The porting from DirectX 10 to DirectX 11 is very straight-forward. See MSDN, Living without D3DX, and Direct3D 11 Deployment for Game Developers