Why ID3D11DeviceContext::UpdateSubresource() is crashing my app?

Started by
2 comments, last by MarcusAseth 5 years, 10 months ago

I've been following this tutorial -> https://www.3dgep.com/introduction-to-directx-11/#The_Main_Function , did all the steps,and I ended up with the main.cpp you can see below.

The problem is the call at line 516 


g_d3dDeviceContext->UpdateSubresource(g_d3dConstantBuffers[CB_Frame], 0, nullptr, &g_ViewMatrix, 0, 0);

which is crashing the program, and the very odd thing is that the first time trough it works fine, it crash the app the second time it is called...

Can someone help me understand why? ?    I have no idea...



#include <Direct3D_11PCH.h>

//Shaders

using namespace DirectX;

// Globals

//Window
const unsigned g_WindowWidth = 1024;
const unsigned g_WindowHeight = 768;
const char* g_WindowClassName = "DirectXWindowClass";
const char* g_WindowName = "DirectX 11";
HWND g_WinHnd = nullptr;
const bool g_EnableVSync = true;

//Device and SwapChain
ID3D11Device* g_d3dDevice = nullptr;
ID3D11DeviceContext* g_d3dDeviceContext = nullptr;
IDXGISwapChain* g_d3dSwapChain = nullptr;

//RenderTarget view
ID3D11RenderTargetView* g_d3dRenderTargerView = nullptr;
//DepthStencil view
ID3D11DepthStencilView* g_d3dDepthStencilView = nullptr;
//Depth Buffer Texture
ID3D11Texture2D* g_d3dDepthStencilBuffer = nullptr;

// Define the functionality of the depth/stencil stages
ID3D11DepthStencilState* g_d3dDepthStencilState = nullptr;
// Define the functionality of the rasterizer stage
ID3D11RasterizerState*  g_d3dRasterizerState = nullptr;

D3D11_VIEWPORT g_Viewport{};


//Vertex Buffer data
ID3D11InputLayout* g_d3dInputLayout = nullptr;
ID3D11Buffer* g_d3dVertexBuffer = nullptr;
ID3D11Buffer* g_d3dIndexBuffer = nullptr;

//Shader Data
ID3D11VertexShader* g_d3dVertexShader = nullptr;
ID3D11PixelShader* g_d3dPixelShader = nullptr;

//Shader Resources
enum ConstantBuffer
{
	CB_Application,
	CB_Frame,
	CB_Object,
	NumConstantBuffers
};

ID3D11Buffer* g_d3dConstantBuffers[ConstantBuffer::NumConstantBuffers];


//Demo parameter
XMMATRIX g_WorldMatrix;
XMMATRIX g_ViewMatrix;
XMMATRIX g_ProjectionMatrix;


// Vertex data for a colored cube.
struct VertexPosColor
{
	XMFLOAT3 Position;
	XMFLOAT3 Color;
};

VertexPosColor g_Vertices[8] =
{
	{ XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT3(0.0f, 0.0f, 0.0f) }, // 0
	{ XMFLOAT3(-1.0f,  1.0f, -1.0f), XMFLOAT3(0.0f, 1.0f, 0.0f) }, // 1
	{ XMFLOAT3(1.0f,   1.0f, -1.0f), XMFLOAT3(1.0f, 1.0f, 0.0f) }, // 2
	{ XMFLOAT3(1.0f,  -1.0f, -1.0f), XMFLOAT3(1.0f, 0.0f, 0.0f) }, // 3
	{ XMFLOAT3(-1.0f, -1.0f,  1.0f), XMFLOAT3(0.0f, 0.0f, 1.0f) }, // 4
	{ XMFLOAT3(-1.0f,  1.0f,  1.0f), XMFLOAT3(0.0f, 1.0f, 1.0f) }, // 5
	{ XMFLOAT3(1.0f,   1.0f,  1.0f), XMFLOAT3(1.0f, 1.0f, 1.0f) }, // 6
	{ XMFLOAT3(1.0f,  -1.0f,  1.0f), XMFLOAT3(1.0f, 0.0f, 1.0f) }  // 7
};

WORD g_Indicies[36] =
{
	0, 1, 2, 0, 2, 3,
	4, 6, 5, 4, 7, 6,
	4, 5, 1, 4, 1, 0,
	3, 2, 6, 3, 6, 7,
	1, 5, 6, 1, 6, 2,
	4, 0, 3, 4, 3, 7
};

//Forward Declaration
LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

bool LoadContent();

int Run();
void Update(float deltaTime);
void Clear(const FLOAT clearColor[4], FLOAT clearDepth, UINT8 clearStencil);
void Present(bool vSync);
void Render();
void CleanUp();

int InitApplication(HINSTANCE hInstance, int cmdShow);
int InitDirectX(HINSTANCE hInstance, BOOL vsync);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmd, int cmdShow)
{

	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(cmd);

	// Check for DirectX Math library support.
	if (!XMVerifyCPUSupport())
	{
		MessageBox(nullptr, TEXT("Failed to verify DirectX Math library support."), nullptr, MB_OK);
		return -1;
	}

	if (InitApplication(hInstance, cmdShow) != 0)
	{
		MessageBox(nullptr, TEXT("Failed to create applicaiton window."), nullptr, MB_OK);
		return -1;
	}

	if (InitDirectX(hInstance, g_EnableVSync) != 0)
	{
		MessageBox(nullptr, TEXT("Failed to initialize DirectX."), nullptr, MB_OK);
		CleanUp();
		return -1;
	}

	if (!LoadContent())
	{
		MessageBox(nullptr, TEXT("Failed to load content."), nullptr, MB_OK);
		CleanUp();
		return -1;
	}



	int returnCode = Run();

	CleanUp();
	return returnCode;
}

int Run()
{
	MSG msg{};

	static DWORD previousTime = timeGetTime();
	static const float targetFramerate = 30.0f;
	static const float maxTimeStep = 1.0f / targetFramerate;

	while (msg.message != WM_QUIT)
	{
		if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			DWORD currentTime = timeGetTime();
			float deltaTime = (currentTime - previousTime) / 1000.0f;
			previousTime = currentTime;

			deltaTime = std::min<float>(deltaTime, maxTimeStep);

			Update(deltaTime);
			Render();
		}
	}
	return static_cast<int>(msg.wParam);
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

	PAINTSTRUCT paintstruct;
	HDC hDC;

	switch (msg) {

		case WM_PAINT:
		{
			hDC = BeginPaint(hwnd, &paintstruct);
			EndPaint(hwnd, &paintstruct);
		}break;

		case WM_DESTROY:
		{
			PostQuitMessage(0);
		}break;


		default:
			return DefWindowProc(hwnd, msg, wParam, lParam);
			break;
	}

	return 0;
}

int InitApplication(HINSTANCE hInstance, int cmdShow)
{
	//Register Window class
	WNDCLASSEX mainWindow{};

	mainWindow.cbSize = sizeof(WNDCLASSEX);
	mainWindow.style = CS_HREDRAW | CS_VREDRAW;
	mainWindow.lpfnWndProc = &WindowProc;
	mainWindow.hInstance = hInstance;
	mainWindow.hCursor = LoadCursor(NULL, IDC_ARROW);
	mainWindow.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
	mainWindow.lpszMenuName = nullptr;
	mainWindow.lpszClassName = g_WindowClassName;


	if (!RegisterClassEx(&mainWindow))
	{
		return -1;
	}

	RECT client{ 0,0,g_WindowWidth,g_WindowHeight };
	AdjustWindowRect(&client, WS_OVERLAPPEDWINDOW, false);


	// Create Window
	g_WinHnd = CreateWindowEx(NULL,
							  g_WindowClassName, g_WindowName,
							  WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,
							  client.right - client.left,
							  client.bottom - client.top,
							  nullptr, nullptr, hInstance, nullptr);

	if (!g_WinHnd)
	{
		return -1;
	}

	UpdateWindow(g_WinHnd);

	return 0;
}

int InitDirectX(HINSTANCE hInstance, BOOL vsync)
{

	assert(g_WinHnd != nullptr);

	RECT client{};
	GetClientRect(g_WinHnd, &client);

	unsigned int clientWidth = client.right - client.left;
	unsigned int clientHeight = client.bottom - client.top;


	//Direct3D Initialization
	HRESULT hr{};

	//SwapChainDesc
	DXGI_RATIONAL refreshRate = vsync ? DXGI_RATIONAL{ 1, 60 } : DXGI_RATIONAL{ 0, 1 };

	DXGI_SWAP_CHAIN_DESC swapChainDesc{};

	swapChainDesc.BufferDesc.Width = clientWidth;
	swapChainDesc.BufferDesc.Height = clientHeight;
	swapChainDesc.BufferDesc.RefreshRate = refreshRate;
	swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
	swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_CENTERED;
	swapChainDesc.SampleDesc.Count = 1;
	swapChainDesc.SampleDesc.Quality = 0;
	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
	swapChainDesc.BufferCount = 1;
	swapChainDesc.OutputWindow = g_WinHnd;
	swapChainDesc.Windowed = true;
	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;


	UINT createDeviceFlags{};
#if _DEBUG
	createDeviceFlags = D3D11_CREATE_DEVICE_DEBUG;
#endif

	//Feature levels
	const D3D_FEATURE_LEVEL features[]{
		D3D_FEATURE_LEVEL_11_0
	};

	D3D_FEATURE_LEVEL featureLevel;

	hr = D3D11CreateDeviceAndSwapChain(
		nullptr,
		D3D_DRIVER_TYPE_HARDWARE,
		nullptr,
		createDeviceFlags,
		features, _countof(features),
		D3D11_SDK_VERSION,
		&swapChainDesc,
		&g_d3dSwapChain,
		&g_d3dDevice,
		&featureLevel,
		&g_d3dDeviceContext
	);

	if (FAILED(hr))
	{
		return -1;
	}


	//Render Target View

	ID3D11Texture2D* backBuffer;

	hr = g_d3dSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer));
	if (FAILED(hr))
	{
		return -1;
	}

	hr = g_d3dDevice->CreateRenderTargetView(backBuffer, nullptr, &g_d3dRenderTargerView);
	if (FAILED(hr))
	{
		return -1;
	}

	SafeRelease(backBuffer);


	//Depth Stencil View

	D3D11_TEXTURE2D_DESC depthStencilBufferDesc{};
	depthStencilBufferDesc.Width = clientWidth;
	depthStencilBufferDesc.Height = clientHeight;
	depthStencilBufferDesc.MipLevels = 1;
	depthStencilBufferDesc.ArraySize = 1;
	depthStencilBufferDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
	depthStencilBufferDesc.SampleDesc.Count = 1;
	depthStencilBufferDesc.SampleDesc.Quality = 0;
	depthStencilBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	depthStencilBufferDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;


	hr = g_d3dDevice->CreateTexture2D(&depthStencilBufferDesc, nullptr, &g_d3dDepthStencilBuffer);
	if (FAILED(hr))
	{
		return -1;
	}

	hr = g_d3dDevice->CreateDepthStencilView(g_d3dDepthStencilBuffer, nullptr, &g_d3dDepthStencilView);
	if (FAILED(hr))
	{
		return -1;
	}


	//Set States
	D3D11_DEPTH_STENCIL_DESC depthStencilStateDesc{};

	depthStencilStateDesc.DepthEnable = true;
	depthStencilStateDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
	depthStencilStateDesc.DepthFunc = D3D11_COMPARISON_LESS;
	depthStencilStateDesc.StencilEnable = false;

	hr = g_d3dDevice->CreateDepthStencilState(&depthStencilStateDesc, &g_d3dDepthStencilState);
	if (FAILED(hr))
	{
		return -1;
	}

	D3D11_RASTERIZER_DESC rasterizerStateDesc{};
	rasterizerStateDesc.FillMode = D3D11_FILL_SOLID;
	rasterizerStateDesc.CullMode = D3D11_CULL_BACK;
	rasterizerStateDesc.FrontCounterClockwise = FALSE;
	rasterizerStateDesc.DepthClipEnable = TRUE;
	rasterizerStateDesc.ScissorEnable = FALSE;;
	rasterizerStateDesc.MultisampleEnable = FALSE;

	hr = g_d3dDevice->CreateRasterizerState(&rasterizerStateDesc, &g_d3dRasterizerState);
	if (FAILED(hr))
	{
		return -1;
	}

	//Set Viewport

	g_Viewport.Width = static_cast<float>(clientWidth);
	g_Viewport.Height = static_cast<float>(clientHeight);
	g_Viewport.TopLeftX = 0.0f;
	g_Viewport.TopLeftY = 0.0f;
	g_Viewport.MinDepth = 0.0f;
	g_Viewport.MaxDepth = 1.0f;

	return 0;
}

bool LoadContent()
{
	//Load Shaders
	HRESULT hr;
	assert(g_d3dDevice);

	//VS
	ID3DBlob* vsBlob = nullptr;
	D3DReadFileToBlob(L"../Shaders/SimpleVertexShader.cso", &vsBlob);

	assert(vsBlob);

	hr = g_d3dDevice->CreateVertexShader(vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), nullptr, &g_d3dVertexShader);
	if (FAILED(hr))
	{
		SafeRelease(vsBlob);
		return false;
	}

	//Create VS Input Layout
	D3D11_INPUT_ELEMENT_DESC vertexLayoutDesc[] = {
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(VertexPosColor, Position), D3D11_INPUT_PER_VERTEX_DATA ,0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(VertexPosColor, Color), D3D11_INPUT_PER_VERTEX_DATA ,0 }
	};

	hr = g_d3dDevice->CreateInputLayout(vertexLayoutDesc, _countof(vertexLayoutDesc),
										vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(),
										&g_d3dInputLayout);
	if (FAILED(hr))
	{
		SafeRelease(vsBlob);
		return false;
	}
	SafeRelease(vsBlob);

	//PS
	ID3DBlob* psBlob = nullptr;
	D3DReadFileToBlob(L"../Shaders/SimplePixelShader.cso", &psBlob);

	assert(psBlob);

	hr = g_d3dDevice->CreatePixelShader(psBlob->GetBufferPointer(), psBlob->GetBufferSize(), nullptr, &g_d3dPixelShader);
	SafeRelease(psBlob);
	if (FAILED(hr))
	{
		return false;
	}

	//Load Vertex Buffer
	D3D11_BUFFER_DESC vertexBufferDesc{};

	vertexBufferDesc.ByteWidth = sizeof(VertexPosColor) * _countof(g_Vertices);
	vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;

	D3D11_SUBRESOURCE_DATA resourceData{};
	resourceData.pSysMem = g_Vertices;

	hr = g_d3dDevice->CreateBuffer(&vertexBufferDesc, &resourceData, &g_d3dVertexBuffer);
	if (FAILED(hr))
	{
		return false;
	}

	//Load Index Buffer
	D3D11_BUFFER_DESC indexBufferDesc{};
	indexBufferDesc.ByteWidth = sizeof(WORD) * _countof(g_Indicies);
	indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;

	resourceData.pSysMem = g_Indicies;

	hr = g_d3dDevice->CreateBuffer(&indexBufferDesc, &resourceData, &g_d3dIndexBuffer);
	if (FAILED(hr))
	{
		return false;
	}

	//Load Constant Buffers
	D3D11_BUFFER_DESC cBufferDesc{};

	cBufferDesc.ByteWidth = sizeof(XMMATRIX);
	cBufferDesc.Usage = D3D11_USAGE_DEFAULT;
	cBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;

	for (size_t bufferID = 0; bufferID < NumConstantBuffers; bufferID++)
	{
		hr = g_d3dDevice->CreateBuffer(&cBufferDesc, nullptr, &g_d3dConstantBuffers[bufferID]);
		if (FAILED(hr))
		{
			return false;
		}
	}

	//Setup Projection Matrix
	RECT client{};
	GetClientRect(g_WinHnd, &client);

	float clientWidth = static_cast<float>(client.right - client.left);
	float clientHeight = static_cast<float>(client.bottom - client.top);

	g_ProjectionMatrix = DirectX::XMMatrixPerspectiveFovLH(XMConvertToRadians(45.0f), clientWidth / clientHeight, 0.1f, 100.0f);
	g_d3dDeviceContext->UpdateSubresource(g_d3dConstantBuffers[CB_Application], 0, nullptr, &g_ProjectionMatrix, 0, 0);


	return true;
}

void Update(float deltaTime)
{
	XMVECTOR eyePosition = XMVectorSet(0, 0, -10, 1);
	XMVECTOR focusPoint = XMVectorSet(0, 0, 0, 1);
	XMVECTOR upDirection = XMVectorSet(0, 1, 0, 0);
	g_ViewMatrix = DirectX::XMMatrixLookAtLH(eyePosition, focusPoint, upDirection);
	g_d3dDeviceContext->UpdateSubresource(g_d3dConstantBuffers[CB_Frame], 0, nullptr, &g_ViewMatrix, 0, 0);

	static float angle = 0.0f;
	angle += 90.0f * deltaTime;
	XMVECTOR rotationAxis = XMVectorSet(0, 1, 1, 0);
	g_WorldMatrix = DirectX::XMMatrixRotationAxis(rotationAxis, XMConvertToRadians(angle));
	g_d3dDeviceContext->UpdateSubresource(g_d3dConstantBuffers[CB_Object], 0, nullptr, &g_WorldMatrix, 0, 0);

}

void Clear(const FLOAT clearColor[4], FLOAT clearDepth, UINT8 clearStencil)
{
	g_d3dDeviceContext->ClearRenderTargetView(g_d3dRenderTargerView, clearColor);
	g_d3dDeviceContext->ClearDepthStencilView(g_d3dDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, clearDepth, clearStencil);
}

void Present(bool vSync)
{
	if (vSync)
	{
		g_d3dSwapChain->Present(1, 0);
	}
	else
	{
		g_d3dSwapChain->Present(0, 0);
	}
}

void Render()
{
	assert(g_d3dDevice);
	assert(g_d3dDeviceContext);

	Clear(Colors::CornflowerBlue, 1.0f, 0);

	//IA
	const UINT vertexStride = sizeof(VertexPosColor);
	const UINT offset = 0;

	g_d3dDeviceContext->IASetVertexBuffers(0, 1, &g_d3dVertexBuffer, &vertexStride, &offset);
	g_d3dDeviceContext->IASetInputLayout(g_d3dInputLayout);
	g_d3dDeviceContext->IASetIndexBuffer(g_d3dIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
	g_d3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	//VS
	g_d3dDeviceContext->VSSetShader(g_d3dVertexShader, nullptr, 0);
	g_d3dDeviceContext->VSGetConstantBuffers(0, NumConstantBuffers, g_d3dConstantBuffers);

	//RS
	g_d3dDeviceContext->RSSetState(g_d3dRasterizerState);
	g_d3dDeviceContext->RSSetViewports(1, &g_Viewport);

	//PS
	g_d3dDeviceContext->PSSetShader(g_d3dPixelShader, nullptr, 0);

	//OM
	g_d3dDeviceContext->OMSetRenderTargets(1, &g_d3dRenderTargerView, g_d3dDepthStencilView);
	g_d3dDeviceContext->OMSetDepthStencilState(g_d3dDepthStencilState, 1);

	//draw
	g_d3dDeviceContext->DrawIndexed(_countof(g_Indicies), 0, 0);

	Present(g_EnableVSync);
}

void CleanUp()
{
	SafeRelease(g_d3dVertexShader);
	SafeRelease(g_d3dPixelShader);
	SafeRelease(g_d3dVertexBuffer);
	SafeRelease(g_d3dIndexBuffer);
	SafeRelease(g_d3dInputLayout);
	SafeRelease(g_d3dDepthStencilBuffer);

	for (size_t bufferID = 0; bufferID < NumConstantBuffers; bufferID++)
	{
		SafeRelease(g_d3dConstantBuffers[bufferID]);
	}

	SafeRelease(g_d3dDepthStencilState);
	SafeRelease(g_d3dRasterizerState);
	SafeRelease(g_d3dRenderTargerView);
	SafeRelease(g_d3dDepthStencilView);
	SafeRelease(g_d3dSwapChain);
	SafeRelease(g_d3dDeviceContext);
	SafeRelease(g_d3dDevice);
}

 

Advertisement

On this line :


g_d3dDeviceContext->VSGetConstantBuffers(0, NumConstantBuffers, g_d3dConstantBuffers);

You are basically overwriting all the buffers that you previously created yourself here :


hr = g_d3dDevice->CreateBuffer(&cBufferDesc, nullptr, &g_d3dConstantBuffers[bufferID]);

 

On first glance that would be the cause of the error. Are you sure you didn't intent to use VSSetConstantBuffers instead of VSGetConstantBuffers ?

That totally fixed it, thanks! xD

I blame auto complete :P

also kind of scary that


g_d3dDeviceContext->VSGetConstantBuffers(0, NumConstantBuffers, g_d3dConstantBuffers);
g_d3dDeviceContext->VSSetConstantBuffers(0, NumConstantBuffers, g_d3dConstantBuffers);

1 single character mistake between the 2 lines above can f*@k this much everything else...isn't this a bad API design choice?

This topic is closed to new replies.

Advertisement