diff --git a/bin/windows/zmusic/arm64/zmusic.dll b/bin/windows/zmusic/arm64/zmusic.dll new file mode 100644 index 0000000000..9417d1e41a Binary files /dev/null and b/bin/windows/zmusic/arm64/zmusic.dll differ diff --git a/bin/windows/zmusic/arm64/zmusic.lib b/bin/windows/zmusic/arm64/zmusic.lib new file mode 100644 index 0000000000..4827759367 Binary files /dev/null and b/bin/windows/zmusic/arm64/zmusic.lib differ diff --git a/cmake/TargetArch.cmake b/cmake/TargetArch.cmake index 2cfef741b7..357bf3130d 100644 --- a/cmake/TargetArch.cmake +++ b/cmake/TargetArch.cmake @@ -29,7 +29,7 @@ # "There are many more known variants/revisions that we do not handle/detect." set(archdetect_c_code " -#if defined(__arm__) || defined(__TARGET_ARCH_ARM) +#if defined(__arm__) || defined(__TARGET_ARCH_ARM) || defined(_M_ARM64) #if defined(__ARM_ARCH_7__) \\ || defined(__ARM_ARCH_7A__) \\ || defined(__ARM_ARCH_7R__) \\ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c5eb802b80..1f0c2664e6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,6 +20,8 @@ else() find_package( ZMusic REQUIRED ) endif() +message("Building for target architecture: ${ZDOOM_TARGET_ARCH}") + if( MSVC AND NOT ZMUSIC_FOUND ) # Use prebuilt library set( ZMUSIC_ROOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../bin/windows/zmusic" ) @@ -27,6 +29,8 @@ if( MSVC AND NOT ZMUSIC_FOUND ) set( ZMUSIC_LIBRARIES zmusic ) if( ${ZDOOM_TARGET_ARCH} MATCHES "x86_64" ) link_directories( ${ZMUSIC_ROOT_PATH}/64bit ) + elseif( ${ZDOOM_TARGET_ARCH} MATCHES "arm" ) + link_directories( ${ZMUSIC_ROOT_PATH}/arm64 ) else() link_directories( ${ZMUSIC_ROOT_PATH}/32bit ) endif() @@ -97,7 +101,6 @@ if( WIN32 ) endif() set( ZDOOM_LIBS - opengl32 wsock32 winmm "${DX_dinput8_LIBRARY}" @@ -425,7 +428,6 @@ endif() set( PLAT_WIN32_SOURCES win32/i_steam.cpp common/platform/win32/hardware.cpp - common/platform/win32/i_crash.cpp common/platform/win32/i_input.cpp common/platform/win32/i_keyboard.cpp common/platform/win32/i_mouse.cpp @@ -446,6 +448,15 @@ set( PLAT_WIN32_SOURCES if (HAVE_VULKAN) set (PLAT_WIN32_SOURCES ${PLAT_WIN32_SOURCES} common/platform/win32/win32vulkanvideo.cpp ) endif() + +# todo: implement an actual crash catcher for ARM +# for now this is purely experimental +if (NOT ${ZDOOM_TARGET_ARCH} MATCHES "arm" ) + set (PLAT_WIN32_SOURCES ${PLAT_WIN32_SOURCES} common/platform/win32/i_crash.cpp ) +endif() +if (MSVC AND ${ZDOOM_TARGET_ARCH} MATCHES "arm") + add_definitions( -DNO_SSE -D__ARM__ -DRAPIDJSON_ENDIAN=RAPIDJSON_LITTLEENDIAN) +endif() set( PLAT_POSIX_SOURCES posix/i_steam.cpp diff --git a/src/common/engine/stats.h b/src/common/engine/stats.h index 563fc9529f..9ce5268a31 100644 --- a/src/common/engine/stats.h +++ b/src/common/engine/stats.h @@ -97,11 +97,13 @@ private: #else // Windows and macOS +#ifndef _M_ARM #include "x86.h" +#endif extern double PerfToSec, PerfToMillisec; -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(_M_ARM64) // Trying to include intrin.h here results in some bizarre errors, so I'm just // going to duplicate the function prototype instead. //#include @@ -111,6 +113,12 @@ inline unsigned __int64 rdtsc() { return __rdtsc(); } +#elif defined(_MSC_VER) && defined(_M_ARM64) +#include +inline unsigned __int64 rdtsc() +{ + return _ReadStatusReg(ARM64_SYSREG(0b11, 0b011, 0b1001, 0b1101, 0b000)); //_ReadStatusReg(PMCCNTR_EL0); +} #elif defined __APPLE__ && (defined __i386__ || defined __x86_64__) inline uint64_t rdtsc() { diff --git a/src/common/platform/win32/gl_sysfb.cpp b/src/common/platform/win32/gl_sysfb.cpp index 9a23028b6c..e373c3d3b0 100644 --- a/src/common/platform/win32/gl_sysfb.cpp +++ b/src/common/platform/win32/gl_sysfb.cpp @@ -52,6 +52,8 @@ extern HWND Window; +extern "C" PROC zd_wglGetProcAddress(LPCSTR name); + PFNWGLSWAPINTERVALEXTPROC myWglSwapIntervalExtProc; //========================================================================== @@ -78,15 +80,15 @@ SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) : Syst HDC hDC = GetDC(Window); const char *wglext = nullptr; - myWglSwapIntervalExtProc = (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); - auto myWglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); + myWglSwapIntervalExtProc = (PFNWGLSWAPINTERVALEXTPROC)zd_wglGetProcAddress("wglSwapIntervalEXT"); + auto myWglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)zd_wglGetProcAddress("wglGetExtensionsStringARB"); if (myWglGetExtensionsStringARB) { wglext = myWglGetExtensionsStringARB(hDC); } else { - auto myWglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)wglGetProcAddress("wglGetExtensionsStringEXT"); + auto myWglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)zd_wglGetProcAddress("wglGetExtensionsStringEXT"); if (myWglGetExtensionsStringEXT) { wglext = myWglGetExtensionsStringEXT(); diff --git a/src/common/platform/win32/i_main.cpp b/src/common/platform/win32/i_main.cpp index 6e1b2ea33f..1d59244c23 100644 --- a/src/common/platform/win32/i_main.cpp +++ b/src/common/platform/win32/i_main.cpp @@ -1076,10 +1076,13 @@ void CALLBACK ExitFatally (ULONG_PTR dummy) SetUnhandledExceptionFilter (ExitMessedUp); I_ShutdownGraphics (); RestoreConView (); +#ifndef _M_ARM64 DisplayCrashLog (); +#endif exit(-1); } +#ifndef _M_ARM64 //========================================================================== // // CatchAllExceptions @@ -1132,6 +1135,7 @@ LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info) } return EXCEPTION_CONTINUE_EXECUTION; } +#endif // !_M_ARM64 //========================================================================== // @@ -1155,7 +1159,11 @@ static void infiniterecursion(int foo) // which offers the very important feature to open a debugger and see the crash in context right away. CUSTOM_CVAR(Bool, disablecrashlog, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) { +#ifndef _M_ARM64 SetUnhandledExceptionFilter(!*self ? CatchAllExceptions : nullptr); +#else + SetUnhandledExceptionFilter(nullptr); +#endif } //========================================================================== @@ -1217,7 +1225,9 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int #ifndef _DEBUG if (MainThread != INVALID_HANDLE_VALUE) { +#ifndef _M_ARM64 SetUnhandledExceptionFilter (CatchAllExceptions); +#endif #ifdef _M_X64 static bool setJumpResult = false; diff --git a/src/common/platform/win32/win32glvideo.cpp b/src/common/platform/win32/win32glvideo.cpp index 034ec86918..e6d38d9d66 100644 --- a/src/common/platform/win32/win32glvideo.cpp +++ b/src/common/platform/win32/win32glvideo.cpp @@ -55,6 +55,13 @@ #include "gl_framebuffer.h" +extern "C" { +HGLRC zd_wglCreateContext(HDC Arg1); +BOOL zd_wglDeleteContext(HGLRC Arg1); +BOOL zd_wglMakeCurrent(HDC Arg1, HGLRC Arg2); +PROC zd_wglGetProcAddress(LPCSTR name); +} + EXTERN_CVAR(Int, vid_adapter) EXTERN_CVAR(Bool, vid_hdr) @@ -74,7 +81,7 @@ CUSTOM_CVAR(Bool, vr_enable_quadbuffered, false, CVAR_ARCHIVE | CVAR_GLOBALCONFI extern bool vid_hdr_active; // these get used before GLEW is initialized so we have to use separate pointers with different names -PFNWGLCHOOSEPIXELFORMATARBPROC myWglChoosePixelFormatARB; // = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); +PFNWGLCHOOSEPIXELFORMATARBPROC myWglChoosePixelFormatARB; // = (PFNWGLCHOOSEPIXELFORMATARBPROC)zd_wglGetProcAddress("wglChoosePixelFormatARB"); PFNWGLCREATECONTEXTATTRIBSARBPROC myWglCreateContextAttribsARB; @@ -224,15 +231,15 @@ bool Win32GLVideo::SetPixelFormat() ::SetPixelFormat(hDC, pixelFormat, &pfd); - hRC = wglCreateContext(hDC); - wglMakeCurrent(hDC, hRC); + hRC = zd_wglCreateContext(hDC); + zd_wglMakeCurrent(hDC, hRC); - myWglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)wglGetProcAddress("wglChoosePixelFormatARB"); - myWglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB"); + myWglChoosePixelFormatARB = (PFNWGLCHOOSEPIXELFORMATARBPROC)zd_wglGetProcAddress("wglChoosePixelFormatARB"); + myWglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)zd_wglGetProcAddress("wglCreateContextAttribsARB"); // any extra stuff here? - wglMakeCurrent(NULL, NULL); - wglDeleteContext(hRC); + zd_wglMakeCurrent(NULL, NULL); + zd_wglDeleteContext(hRC); ReleaseDC(dummy, hDC); ShutdownDummy(dummy); @@ -436,7 +443,7 @@ bool Win32GLVideo::InitHardware(HWND Window, int multisample) if (m_hRC == NULL && prof == WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) { - m_hRC = wglCreateContext(m_hDC); + m_hRC = zd_wglCreateContext(m_hDC); if (m_hRC == NULL) { I_Error("R_OPENGL: Unable to create an OpenGL render context.\n"); @@ -446,7 +453,7 @@ bool Win32GLVideo::InitHardware(HWND Window, int multisample) if (m_hRC != NULL) { - wglMakeCurrent(m_hDC, m_hRC); + zd_wglMakeCurrent(m_hDC, m_hRC); return true; } } @@ -465,8 +472,8 @@ void Win32GLVideo::Shutdown() { if (m_hRC) { - wglMakeCurrent(0, 0); - wglDeleteContext(m_hRC); + zd_wglMakeCurrent(0, 0); + zd_wglDeleteContext(m_hRC); } if (m_hDC) ReleaseDC(m_Window, m_hDC); } diff --git a/src/common/rendering/gl_load/gl_load.c b/src/common/rendering/gl_load/gl_load.c index 4bfbb78786..bf563afe00 100644 --- a/src/common/rendering/gl_load/gl_load.c +++ b/src/common/rendering/gl_load/gl_load.c @@ -67,10 +67,51 @@ static int TestPointer(const PROC pTest) return 1; } +static HMODULE opengl32dll; +static HGLRC(WINAPI* createcontext)(HDC); +static BOOL(WINAPI* deletecontext)(HGLRC); +static BOOL(WINAPI* makecurrent)(HDC, HGLRC); +static PROC(WINAPI* getprocaddress)(LPCSTR name); +static void CheckOpenGL(void) +{ + if (opengl32dll == 0) + { + opengl32dll = LoadLibrary(L"OpenGL32.DLL"); + createcontext = (HGLRC(WINAPI*)(HDC)) GetProcAddress(opengl32dll, "wglCreateContext"); + deletecontext = (BOOL(WINAPI*)(HGLRC)) GetProcAddress(opengl32dll, "wglDeleteContext"); + makecurrent = (BOOL(WINAPI*)(HDC, HGLRC)) GetProcAddress(opengl32dll, "wglMakeCurrent"); + getprocaddress = (PROC(WINAPI*)(LPCSTR)) GetProcAddress(opengl32dll, "wglGetProcAddress"); + } +} + +HGLRC zd_wglCreateContext(HDC dc) +{ + CheckOpenGL(); + return createcontext(dc); +} + +BOOL zd_wglDeleteContext(HGLRC context) +{ + CheckOpenGL(); + return deletecontext(context); +} + +BOOL zd_wglMakeCurrent(HDC dc, HGLRC context) +{ + CheckOpenGL(); + return makecurrent(dc, context); +} + +PROC zd_wglGetProcAddress(LPCSTR name) +{ + CheckOpenGL(); + return getprocaddress(name); +} + static PROC WinGetProcAddress(const char *name) { HMODULE glMod = NULL; - PROC pFunc = wglGetProcAddress((LPCSTR)name); + PROC pFunc = zd_wglGetProcAddress((LPCSTR)name); if(TestPointer(pFunc)) { return pFunc;