nvwgf2umx.dll CComPtr Crash Sometimes

631 Views Asked by At

I am receiving a very strange bug right now. I'm currently writing a small project in DirectX 11 and making use of ATL CComPtr's for the COM components. In one instance, I'm wrapping an ID3D11Buffer in a CComPtr. In most of my application, this has been fine and seen no crashes, however, for some reason in this very particular instance, I'm crashing occasionally.

ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
bd.ByteWidth = sizeof(MiscCBuffer);
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
hr = device->CreateBuffer(&bd, nullptr, &_gcVoxelBuffer);
if (FAILED(hr)) { 
    throw std::exception("[E] Creating constant buffer in TerrainComponent onAwake."); 
}

This is the code I'm using to create the constant buffer. The CPU buffer's values are set like this

float dimX = _instanceDimensions.x;
float dimY = _instanceDimensions.y;
float dimZ = _instanceDimensions.z;
_cVoxelBuffer.misc.x = dimX;
_cVoxelBuffer.misc.y = dimY;
_cVoxelBuffer.misc.z = dimZ;
_cVoxelBuffer.misc.w = 0;

The MiscCBuffer struct only holds a XMFLOAT4. Finally, to update the constant buffer on the GPU with the CPU data, I use this code.

updateD11Buffer(_gcVoxelBuffer, _cVoxelBuffer, context);

template <class T>
updateD11Buffer(const CComPtr<ID3D11Buffer>& gcBuffer, const T& cbuffer, const CComPtr<ID3D11DeviceContext>& ctx){
    D3D11_MAPPED_SUBRESOURCE mappedResource;
    ZeroMemory(&mappedResource, sizeof(D3D11_MAPPED_SUBRESOURCE));
    ctx->Map(gcBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
    memcpy(mappedResource.pData, &cbuffer, sizeof(cbuffer));
    ctx->Unmap(gcBuffer, 0);
}

As for the error itself, it sometimes happens when the program first launches. It could successfully launch 10 times in a row, and then fail the next 3 times.

Exception thrown at 0x00007FFB003B273B (nvwgf2umx.dll) in ECS_Simulation.exe: 0xC0000005: Access violation reading location 0x000001BE69F9F000.

I have tried reading online but a lot of posts regarding nvwgf2umx.dll crashing with an access violation come from shipped game titles, other posts regarding access violations are usually caused by NULL pointers. In my case, I have checked the _gcVoxelBuffer and _gcVoxelBuffer.p, both of which are valid pointers.

In addition, the D3D Context object is pointing to a valid location, and the CPU side buffer object is also valid to the best of my knowledge.

1

There are 1 best solutions below

3
Chuck Walbourn On

I'm not sure if this is really the problem, but it's a problem.

Instead try:

template <class T>
updateD11Buffer(const CComPtr<ID3D11Buffer>& gcBuffer, const T& cbuffer, const CComPtr<ID3D11DeviceContext>& ctx)
{
    D3D11_MAPPED_SUBRESOURCE mappedResource = {};
    if (SUCCEEDED(ctx->Map(gcBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource))
    {
        memcpy(mappedResource.pData, &cbuffer, sizeof(cbuffer));
        ctx->Unmap(gcBuffer, 0);
    }
}

ZeroMemory is ancient Win32 pattern. With C++11 or later compilers, uniform initialization is much easier to use.

Note that a more flexible design would be:

template <class T>
updateD11Buffer(ID3D11Buffer* gcBuffer, const T& cbuffer, ID3D11DeviceContext* ctx)
{
...
}

// call using updateD11Buffer(_gcVoxelBuffer.Get(), _cVoxelBuffer, context.Get());

This version doesn't force the use of a particular smart-pointer, and is less of a "thick syntax forest".

PS: ATL's CComPtr is a bit dated and has a few quirks to it. For example, &_gcVoxelBuffer assumes that _gcVoxelBuffer is always null so you can easily get resource leaks.

You should take a look at WRL's ComPtr which is "ATL 2.0". See this article.