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);
}