bvle-voxels/src/app/main.cpp

188 lines
6.4 KiB
C++
Raw Normal View History

#include "WickedEngine.h"
#include "voxel/VoxelRenderer.h"
#include <fstream>
#include <DbgHelp.h>
#pragma comment(lib, "dbghelp.lib")
// ── BVLE Voxels - Prototype Application ─────────────────────────
// Wicked Engine based voxel engine prototype for performance validation.
// ── Crash handler: writes stack trace + minidump on unhandled exception ──
static LONG WINAPI CrashHandler(EXCEPTION_POINTERS* ep) {
std::ofstream crash("bvle_crash.log", std::ios::trunc);
crash << "=== BVLE CRASH REPORT ===" << std::endl;
DWORD code = ep->ExceptionRecord->ExceptionCode;
PVOID addr = ep->ExceptionRecord->ExceptionAddress;
crash << "Exception code: 0x" << std::hex << code << std::endl;
crash << "Crash address: 0x" << addr << std::endl;
if (code == EXCEPTION_ACCESS_VIOLATION && ep->ExceptionRecord->NumberParameters >= 2) {
ULONG_PTR type = ep->ExceptionRecord->ExceptionInformation[0];
ULONG_PTR target = ep->ExceptionRecord->ExceptionInformation[1];
crash << (type == 0 ? "Reading" : "Writing") << " address: 0x" << std::hex << target << std::endl;
}
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
SymInitialize(process, NULL, TRUE);
CONTEXT* ctx = ep->ContextRecord;
STACKFRAME64 frame = {};
frame.AddrPC.Offset = ctx->Rip; frame.AddrPC.Mode = AddrModeFlat;
frame.AddrFrame.Offset = ctx->Rbp; frame.AddrFrame.Mode = AddrModeFlat;
frame.AddrStack.Offset = ctx->Rsp; frame.AddrStack.Mode = AddrModeFlat;
crash << "\nStack trace:" << std::endl;
for (int i = 0; i < 32; i++) {
if (!StackWalk64(IMAGE_FILE_MACHINE_AMD64, process, thread, &frame,
ctx, NULL, SymFunctionTableAccess64, SymGetModuleBase64, NULL))
break;
char symbolBuf[sizeof(SYMBOL_INFO) + 256];
SYMBOL_INFO* symbol = (SYMBOL_INFO*)symbolBuf;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
symbol->MaxNameLen = 255;
DWORD64 disp64 = 0;
crash << " [" << i << "] 0x" << std::hex << frame.AddrPC.Offset;
if (SymFromAddr(process, frame.AddrPC.Offset, &disp64, symbol))
crash << " " << symbol->Name << " +0x" << disp64;
IMAGEHLP_LINE64 line = {}; line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
DWORD disp32 = 0;
if (SymGetLineFromAddr64(process, frame.AddrPC.Offset, &disp32, &line))
crash << " (" << line.FileName << ":" << std::dec << line.LineNumber << ")";
crash << std::endl;
}
HANDLE dumpFile = CreateFileA("bvle_crash.dmp", GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (dumpFile != INVALID_HANDLE_VALUE) {
MINIDUMP_EXCEPTION_INFORMATION mei;
mei.ThreadId = GetCurrentThreadId();
mei.ExceptionPointers = ep;
mei.ClientPointers = FALSE;
MiniDumpWriteDump(process, GetCurrentProcessId(), dumpFile,
MiniDumpWithDataSegs, &mei, NULL, NULL);
CloseHandle(dumpFile);
}
crash.close();
SymCleanup(process);
return EXCEPTION_EXECUTE_HANDLER;
}
static wi::Application application;
static voxel::VoxelRenderPath renderPath;
int APIENTRY wWinMain(
_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
SetUnhandledExceptionFilter(CrashHandler);
// Win32 window setup
static auto WndProc = [](HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -> LRESULT
{
switch (message)
{
case WM_SIZE:
case WM_DPICHANGED:
if (application.is_window_active)
application.SetWindow(hWnd);
break;
case WM_CHAR:
switch (wParam)
{
case VK_BACK:
wi::gui::TextInputField::DeleteFromInput();
break;
case VK_RETURN:
break;
default:
wi::gui::TextInputField::AddInput((const wchar_t)wParam);
break;
}
break;
case WM_INPUT:
wi::input::rawinput::ParseMessage((void*)lParam);
break;
case WM_KILLFOCUS:
application.is_window_active = false;
break;
case WM_SETFOCUS:
application.is_window_active = true;
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
};
SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
WNDCLASSEXW wcex = {};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszClassName = L"BVLEVoxels";
RegisterClassExW(&wcex);
HWND hWnd = CreateWindowW(
wcex.lpszClassName,
L"BVLE Voxels - Prototype",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0,
1920, 1080,
nullptr, nullptr, hInstance, nullptr
);
ShowWindow(hWnd, SW_SHOWMAXIMIZED);
// Initialize Wicked Engine (selects DX12 by default on Windows, Vulkan on Linux)
// Pass "vulkan" as command line argument to force Vulkan backend
// Pass "debugdevice" for D3D debug layer, "gpuvalidation" for GPU-based validation
application.SetWindow(hWnd);
wi::arguments::Parse(lpCmdLine);
// Redirect Wicked Engine log to file
wi::backlog::SetLogFile("bvle_backlog.txt");
// Info display
application.infoDisplay.active = true;
application.infoDisplay.watermark = false;
application.infoDisplay.resolution = true;
application.infoDisplay.fpsinfo = true;
application.infoDisplay.heap_allocation_counter = true;
// Check for "debug" argument to enable face-color debug mode
if (wi::arguments::HasArgument("debug")) {
renderPath.debugMode = true;
}
// Activate our custom voxel render path
application.ActivatePath(&renderPath);
// Main loop
MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else {
application.Run();
}
}
wi::jobsystem::ShutDown();
return (int)msg.wParam;
}