#include "WickedEngine.h" #include "voxel/VoxelRenderer.h" #include #include #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; } // Check for "debugsmooth" argument to enable smooth blending debug scene if (wi::arguments::HasArgument("debugsmooth")) { renderPath.debugSmooth = 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; }