Advertisement

simple direct3d program - works on 1 computer, crashes on another - problem with constant buffer section

Started by November 23, 2021 02:43 AM
4 comments, last by domagoj2 3 years ago

SOLVED! I'll leave it posted, but answer was annoyingly obvious. Why is it that I always find the answer immediately after I post?

The problem is the byte width in the constant buffer description. The size of XMMATRIX is 64. I set the size to 16. Changed to 64 and now it works fine. Although it does make me wonder… why does this not cause the DESKTOP version to crash?

I am getting into DirectX. And by getting into, I mean literally just slogging my way through beginner instruction videos on YouTube. See code, copy code, and hopefully compile/run code. I have been working on these DirectX tutorials on my PC, but I recently bought a laptop and wanted to practice on my laptop as well. I used GitHub to clone my Visual Studio project from the desktop to my laptop. The code on my desktop runs fine. But when I try to run the exact same code on the laptop, I receive an error. The code that generates the error is in the Map(), CopyMemory(), Unmap() section for constant buffers. If I comment this section out in the laptop version, it runs fine (albeit nothing shows up on the screen - as expected). But if I try to run this section, it immediately crashes out with the error “Unhandled exception at 0x00…. (ntdll.dll) in DX11.exe: A heap has been corrupted.”

This is the function where the error occurs:

void Graphics::RenderFrame()
{
	float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
	deviceContext->ClearRenderTargetView(backBuffer.Get(), color);
	deviceContext->ClearDepthStencilView(depthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

	deviceContext->IASetInputLayout(vertexShader.GetInputLayout());
	deviceContext->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
	deviceContext->RSSetState(rasterizerState.Get());
	deviceContext->OMSetDepthStencilState(depthStencilState.Get(), 0);

	deviceContext->VSSetShader(vertexShader.GetShader(), NULL, 0);
	deviceContext->PSSetShader(pixelShader.GetShader(), NULL, 0);

	UINT offset = 0;
	float aspectRatio = static_cast<float>(pWindow->GetHeight()) / static_cast<float>(pWindow->GetWidth());

	DirectX::XMMATRIX worldMatrix = DirectX::XMMatrixIdentity();
	DirectX::XMVECTOR eyePos = DirectX::XMVectorSet(3.0f + xOffset, 3.0f + yOffset, -5.0f + zOffset, 0.0f);
	DirectX::XMVECTOR lookAt = DirectX::XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
	DirectX::XMVECTOR up = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
	DirectX::XMMATRIX viewMatrix = DirectX::XMMatrixLookAtLH(eyePos, DirectX::XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f), up);
	DirectX::XMMATRIX projMatrix = DirectX::XMMatrixPerspectiveFovLH(DirectX::XMConvertToRadians(90.0f), aspectRatio, 0.1f, 1000.0f);

	CBuffer_VS data;
	data.matrix = worldMatrix * viewMatrix * projMatrix;
	data.matrix = DirectX::XMMatrixTranspose(data.matrix);
	
	D3D11_MAPPED_SUBRESOURCE ms;
	deviceContext->Map(constantBuffer.GetBuffer().Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &ms);
	CopyMemory(ms.pData, &data, sizeof(CBuffer_VS));
	deviceContext->Unmap(constantBuffer.GetBuffer().Get(), 0);
	
	deviceContext->VSSetConstantBuffers(0, 1, constantBuffer.GetBuffer().GetAddressOf());

	deviceContext->IASetVertexBuffers(0, 1, vertexBuffer.GetBuffer().GetAddressOf(), reinterpret_cast<const UINT *>(vertexBuffer.GetStridePointer()), &offset);
	deviceContext->IASetIndexBuffer(indexBuffer.GetBuffer().Get(), DXGI_FORMAT_R32_UINT, 0);
	deviceContext->DrawIndexed(indexBuffer.GetBufferSize(), 0, 0);

	swapChain->Present(1, 0);
}

In particular, the problem section is:

D3D11_MAPPED_SUBRESOURCE ms;
	deviceContext->Map(constantBuffer.GetBuffer().Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &ms);
	CopyMemory(ms.pData, &data, sizeof(CBuffer_VS));
	deviceContext->Unmap(constantBuffer.GetBuffer().Get(), 0);

And although not shown in the code snippets above, I have used HRESULTs in all areas possible to ensure that it returns S_OK. So I don't seem to generate any errors based on the return values from these functions.

And lastly, here is the code for the constant buffer stuff:

struct CBuffer_VS
{
	DirectX::XMMATRIX matrix;
};

class ConstantBuffer
{
public:
	ConstantBuffer() {}
	void CreateBuffer(Microsoft::WRL::ComPtr<ID3D11Device> device);
	Microsoft::WRL::ComPtr<ID3D11Buffer> GetBuffer() { return constantBuffer; }
private:
	Microsoft::WRL::ComPtr<ID3D11Buffer> constantBuffer;
};

void ConstantBuffer::CreateBuffer(Microsoft::WRL::ComPtr<ID3D11Device> device)
{
	D3D11_BUFFER_DESC bd;
	ZeroMemory(&bd, sizeof(bd));

	bd.Usage = D3D11_USAGE_DYNAMIC;
	bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	bd.MiscFlags = 0;
	bd.ByteWidth = 16;
	bd.StructureByteStride = 0;

	device->CreateBuffer(&bd, NULL, constantBuffer.GetAddressOf());
}

My desktop specs are:

Intel Core i7-7700K CPU @ 4.20GHz, Windows 10 Pro 64 bit, GeForce GTX 1060 6 GB

My laptop specs are:

Intel Core i7-10870H CPU @ 2.20GHz, Windows 11 Pro 64 bit, GeForce RTX 3070

Any help is appreciated.

docyoung83 said:
Why is it that I always find the answer immediately after I post

Because you didn't take enough time to think about the issue?

docyoung83 said:
why does this not cause the DESKTOP version to crash?

We can just guess but I think this is due to different hardware is handling these type of error different. I had the same ‘issue’ in OpenGL for different areas, when NVidia hardware threw an error and AMD didn't or vice versa while the other just silently ‘fixed’ it for you.

Mobile hardware is another complexity because they're often cheaper and their drivers are less ‘flexible’

Advertisement

docyoung83 said:
Why is it that I always find the answer immediately after I post?

It's a variation of the “rubber duck debugging” effect wherein the “rubber duck” person is yourself. By explaining the problem you're having with precision, you come to better understand it. You see aspects of it that you couldn't before because those aspects were hidden by the limitations of your working memory. You make connections between things that before were only implicit because they are now visible and obvious to you by virtue of having been written down.

As a working programmer, I have found it tremendously helpful to weaponize this effect by keeping a detailed dev journal. Highly recommend taking up the practice if you haven't already.

docyoung83 said:
Although it does make me wonder… why does this not cause the DESKTOP version to crash?

Could the issue be related to alignment, perhaps? When it was crashing, what was the address of the matrix when you loaded it into the cbuffer?

Stack Overflow is an amazing debugging tool. When I have a problem, I start asking a question there, and then think of all the objections and stupid questions that Random People on the Internet will come back with to downvote the question, and answer each of them in the post, ahead of time. And, like magic, one of those questions will usually explain the problem I'm having, so I don't need to press the “Post” button at all!

Separately: D3D experience tells me: Always enable the debug layer for Direct3D, except for the fully packaged, with-installer, release-candidate builds. Also, always assert that all return values are OK, not error, even in release mode, and fail with a helpful stack trace / error message if possible.

enum Bool { True, False, FileNotFound };

hplus0603 said:

Stack Overflow is an amazing debugging tool. When I have a problem, I start asking a question there, and then think of all the objections and stupid questions that Random People on the Internet will come back with to downvote the question, and answer each of them in the post, ahead of time. And, like magic, one of those questions will usually explain the problem I'm having, so I don't need to press the “Post” button at all!

Separately: D3D experience tells me: Always enable the debug layer for Direct3D, except for the fully packaged, with-installer, release-candidate builds. Also, always assert that all return values are OK, not error, even in release mode, and fail with a helpful stack trace / error message if possible.

I hope that this post will change the World.
#Thank you hplus0603

This topic is closed to new replies.

Advertisement