diff --git a/Source/Engine/Content/Upgraders/BinaryAssetUpgrader.h b/Source/Engine/Content/Upgraders/BinaryAssetUpgrader.h index 9cf459bfb..97bcf1c31 100644 --- a/Source/Engine/Content/Upgraders/BinaryAssetUpgrader.h +++ b/Source/Engine/Content/Upgraders/BinaryAssetUpgrader.h @@ -46,14 +46,7 @@ public: } // Create new chunk - const auto chunk = New(); - Output.Header.Chunks[index] = chunk; - - if (chunk == nullptr) - { - OUT_OF_MEMORY; - } - + Output.Header.Chunks[index] = New(); return false; } }; diff --git a/Source/Engine/ContentImporters/AssetsImportingManager.cpp b/Source/Engine/ContentImporters/AssetsImportingManager.cpp index b689cdc62..a37738c55 100644 --- a/Source/Engine/ContentImporters/AssetsImportingManager.cpp +++ b/Source/Engine/ContentImporters/AssetsImportingManager.cpp @@ -151,14 +151,7 @@ bool CreateAssetContext::AllocateChunk(int32 index) } // Create new chunk - const auto chunk = New(); - Data.Header.Chunks[index] = chunk; - - if (chunk == nullptr) - { - OUT_OF_MEMORY; - } - + Data.Header.Chunks[index] = New(); return false; } diff --git a/Source/Engine/Core/Log.cpp b/Source/Engine/Core/Log.cpp index a9d3268dc..fb4091572 100644 --- a/Source/Engine/Core/Log.cpp +++ b/Source/Engine/Core/Log.cpp @@ -146,8 +146,10 @@ void Log::Logger::Write(const StringView& msg) #endif } +#if !BUILD_RELEASE // Send message to platform logging Platform::Log(msg); +#endif // Write message to log file constexpr int32 LogMaxWriteSize = 1 * 1024 * 1024; // 1GB diff --git a/Source/Engine/Core/Memory/Allocation.h b/Source/Engine/Core/Memory/Allocation.h index 7ce02ca90..fa09e9765 100644 --- a/Source/Engine/Core/Memory/Allocation.h +++ b/Source/Engine/Core/Memory/Allocation.h @@ -148,27 +148,17 @@ public: { ASSERT_LOW_LAYER(!_data); _data = static_cast(Allocator::Allocate(capacity * sizeof(T))); -#if ENABLE_ASSERTION - if (!_data) - OUT_OF_MEMORY; -#endif } FORCE_INLINE void Relocate(const int32 capacity, int32 oldCount, int32 newCount) { T* newData = capacity != 0 ? static_cast(Allocator::Allocate(capacity * sizeof(T))) : nullptr; -#if ENABLE_ASSERTION - if (!newData && capacity != 0) - OUT_OF_MEMORY; -#endif - if (oldCount) { if (newCount > 0) Memory::MoveItems(newData, _data, newCount); Memory::DestructItems(_data, oldCount); } - Allocator::Free(_data); _data = newData; } diff --git a/Source/Engine/Engine/Engine.cpp b/Source/Engine/Engine/Engine.cpp index 7fea9cd6d..17dc8d333 100644 --- a/Source/Engine/Engine/Engine.cpp +++ b/Source/Engine/Engine/Engine.cpp @@ -71,6 +71,9 @@ Action Engine::Draw; Action Engine::Pause; Action Engine::Unpause; Action Engine::RequestingExit; +FatalErrorType Engine::FatalError = FatalErrorType::None; +bool Engine::IsRequestingExit = false; +int32 Engine::ExitCode = 0; Window* Engine::MainWindow = nullptr; int32 Engine::Main(const Char* cmdLine) @@ -201,7 +204,7 @@ int32 Engine::Main(const Char* cmdLine) PROFILE_CPU_NAMED("Platform.Tick"); Platform::Tick(); } - + // Update game logic if (Time::OnBeginUpdate(time)) { @@ -236,12 +239,13 @@ int32 Engine::Main(const Char* cmdLine) FileSystem::DeleteDirectory(Globals::TemporaryFolder); } - return Globals::ExitCode; + return ExitCode; } -void Engine::Exit(int32 exitCode) +void Engine::Exit(int32 exitCode, FatalErrorType error) { ASSERT(IsInMainThread()); + FatalError = error; // Call on exit event OnExit(); @@ -250,23 +254,23 @@ void Engine::Exit(int32 exitCode) exit(exitCode); } -void Engine::RequestExit(int32 exitCode) +void Engine::RequestExit(int32 exitCode, FatalErrorType error) { - if (Globals::IsRequestingExit) + if (IsRequestingExit) return; #if USE_EDITOR // Send to editor (will leave play mode if need to) - if (Editor::Managed->OnAppExit()) - { - Globals::IsRequestingExit = true; - Globals::ExitCode = exitCode; - RequestingExit(); - } -#else + if (!Editor::Managed->OnAppExit()) + return; +#endif + IsRequestingExit = true; + ExitCode = exitCode; + PRAGMA_DISABLE_DEPRECATION_WARNINGS; Globals::IsRequestingExit = true; Globals::ExitCode = exitCode; + PRAGMA_ENABLE_DEPRECATION_WARNINGS; + FatalError = error; RequestingExit(); -#endif } void Engine::OnFixedUpdate() @@ -407,7 +411,7 @@ bool Engine::IsReady() bool Engine::ShouldExit() { - return Globals::IsRequestingExit; + return IsRequestingExit; } bool Engine::IsEditor() diff --git a/Source/Engine/Engine/Engine.h b/Source/Engine/Engine/Engine.h index 2f1728aa2..692ff494b 100644 --- a/Source/Engine/Engine/Engine.h +++ b/Source/Engine/Engine/Engine.h @@ -14,9 +14,9 @@ class JsonAsset; /// API_CLASS(Static) class FLAXENGINE_API Engine { -DECLARE_SCRIPTING_TYPE_NO_SPAWN(Engine); -public: + DECLARE_SCRIPTING_TYPE_NO_SPAWN(Engine); +public: /// /// The engine start time (local time). /// @@ -38,7 +38,6 @@ public: API_FIELD(ReadOnly) static uint64 FrameCount; public: - /// /// Event called on engine fixed update. /// @@ -84,8 +83,22 @@ public: /// API_EVENT() static Action RequestingExit; -public: + /// + /// The current state of the fatal error. Set to None if no error occurred yet. + /// + API_FIELD(ReadOnly) static FatalErrorType FatalError; + /// + /// Flags set to true if engine needs to be closed (exit is pending). Use FatalError to determinate the exit reason (specific error or normal shutdown). + /// + API_FIELD(ReadOnly) static bool IsRequestingExit; + + /// + /// The current process exit code (pending to return). + /// + static int32 ExitCode; + +public: /// /// The main engine function (must be called from platform specific entry point). /// @@ -97,16 +110,17 @@ public: /// Exits the engine. /// /// The exit code. - API_FUNCTION(Attributes="DebugCommand") static void Exit(int32 exitCode = -1); + /// The fatal error type (or None on graceful exit). + API_FUNCTION(Attributes="DebugCommand") static void Exit(int32 exitCode = -1, FatalErrorType error = FatalErrorType::None); /// /// Requests normal engine exit. /// /// The exit code. - API_FUNCTION() static void RequestExit(int32 exitCode = 0); + /// The fatal error type (or None on graceful exit). + API_FUNCTION() static void RequestExit(int32 exitCode = 0, FatalErrorType error = FatalErrorType::None); public: - /// /// Fixed update callback used by the physics simulation (fixed stepping). /// @@ -138,7 +152,6 @@ public: static void OnExit(); public: - // Returns true if engine is running without main window (aka headless mode). API_PROPERTY() static bool IsHeadless(); @@ -184,7 +197,6 @@ public: API_PROPERTY() static bool HasGameViewportFocus(); private: - static void OnPause(); static void OnUnpause(); }; diff --git a/Source/Engine/Engine/Globals.cpp b/Source/Engine/Engine/Globals.cpp index 5aed2a958..fe38e9f93 100644 --- a/Source/Engine/Engine/Globals.cpp +++ b/Source/Engine/Engine/Globals.cpp @@ -18,9 +18,11 @@ String Globals::ProjectContentFolder; #if USE_MONO String Globals::MonoPath; #endif +PRAGMA_DISABLE_DEPRECATION_WARNINGS; bool Globals::FatalErrorOccurred; bool Globals::IsRequestingExit; int32 Globals::ExitCode; +PRAGMA_ENABLE_DEPRECATION_WARNINGS; uint64 Globals::MainThreadID; String Globals::EngineVersion(TEXT(FLAXENGINE_VERSION_TEXT)); int32 Globals::EngineBuildNumber = FLAXENGINE_VERSION_BUILD; diff --git a/Source/Engine/Engine/Globals.h b/Source/Engine/Engine/Globals.h index f204aff29..a51fb035b 100644 --- a/Source/Engine/Engine/Globals.h +++ b/Source/Engine/Engine/Globals.h @@ -10,8 +10,9 @@ /// API_CLASS(Static, Attributes="DebugCommand") class FLAXENGINE_API Globals { -DECLARE_SCRIPTING_TYPE_NO_SPAWN(Globals); + DECLARE_SCRIPTING_TYPE_NO_SPAWN(Globals); +public: // Paths // Main engine directory path. @@ -34,7 +35,6 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(Globals); API_FIELD(ReadOnly) static String BinariesFolder; #if USE_EDITOR - // Project specific cache folder path (editor-only). API_FIELD(ReadOnly) static String ProjectCacheFolder; @@ -43,43 +43,60 @@ DECLARE_SCRIPTING_TYPE_NO_SPAWN(Globals); // Game source code directory path (editor-only). API_FIELD(ReadOnly) static String ProjectSourceFolder; - #endif - // Project content directory path + // Project content directory path. API_FIELD(ReadOnly) static String ProjectContentFolder; #if USE_MONO - // Mono library folder path + // Mono library folder path. API_FIELD(ReadOnly) static String MonoPath; #endif +public: // State - // True if fatal error occurred (engine is exiting) - static bool FatalErrorOccurred; + // True if fatal error occurred (engine is exiting). + // [Deprecated in v1.10] + static DEPRECATED("Use Engine::FatalError instead.") bool FatalErrorOccurred; - // True if engine needs to be closed - static bool IsRequestingExit; + // True if engine needs to be closed. + // [Deprecated in v1.10] + static DEPRECATED("Use Engine::IsRequestingExit instead.") bool IsRequestingExit; /// - /// True if engine needs to be closed + /// Flags set to true if engine needs to be closed (exit is pending). + /// [Deprecated in v1.10] /// - API_PROPERTY() FORCE_INLINE static bool GetIsRequestingExit() { return IsRequestingExit; } + API_PROPERTY() DEPRECATED("Use Engine::IsRequestingExit instead.") FORCE_INLINE static bool GetIsRequestingExit() + { + PRAGMA_DISABLE_DEPRECATION_WARNINGS; + return IsRequestingExit; + PRAGMA_ENABLE_DEPRECATION_WARNINGS; + } /// - /// True if fatal error occurred (engine is exiting) + /// Flags set to true if fatal error occurred (engine is exiting). + /// [Deprecated in v1.10] /// - API_PROPERTY() FORCE_INLINE static bool GetFatalErrorOccurred() { return FatalErrorOccurred; } + API_PROPERTY() DEPRECATED("Use Engine::FatalError instead.") FORCE_INLINE static bool GetFatalErrorOccurred() + { + PRAGMA_DISABLE_DEPRECATION_WARNINGS; + return FatalErrorOccurred; + PRAGMA_ENABLE_DEPRECATION_WARNINGS; + } - // Exit code - static int32 ExitCode; + // Process exit code (pending to return). + // [Deprecated in v1.10] + static DEPRECATED("Use Engine::ExitCode instead.") int32 ExitCode; +public: // Threading - // Main Engine thread id + // Main Engine thread id. API_FIELD(ReadOnly) static uint64 MainThreadID; +public: // Config /// diff --git a/Source/Engine/Graphics/Async/GPUTasksContext.cpp b/Source/Engine/Graphics/Async/GPUTasksContext.cpp index e0ee8cae1..f285886f6 100644 --- a/Source/Engine/Graphics/Async/GPUTasksContext.cpp +++ b/Source/Engine/Graphics/Async/GPUTasksContext.cpp @@ -5,7 +5,7 @@ #include "Engine/Core/Log.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Threading/Threading.h" -#include "Engine/Engine/Globals.h" +#include "Engine/Engine/Engine.h" #define GPU_TASKS_USE_DEDICATED_CONTEXT 0 @@ -37,7 +37,7 @@ GPUTasksContext::~GPUTasksContext() auto task = tasks[i]; if (task->GetSyncPoint() <= _currentSyncPoint && task->GetState() != TaskState::Finished) { - if (!Globals::IsRequestingExit) + if (!Engine::IsRequestingExit) LOG(Warning, "{0} has been canceled before a sync", task->ToString()); task->CancelSync(); } @@ -62,7 +62,7 @@ void GPUTasksContext::OnCancelSync(GPUTask* task) _tasksDone.Remove(task); - if (!Globals::IsRequestingExit) + if (!Engine::IsRequestingExit) LOG(Warning, "{0} has been canceled before a sync", task->ToString()); } diff --git a/Source/Engine/Networking/NetworkStream.cpp b/Source/Engine/Networking/NetworkStream.cpp index fe597a848..1cbff2d1e 100644 --- a/Source/Engine/Networking/NetworkStream.cpp +++ b/Source/Engine/Networking/NetworkStream.cpp @@ -247,10 +247,6 @@ void NetworkStream::WriteBytes(const void* data, uint32 bytes) while (newLength < position + bytes) newLength *= 2; byte* newBuf = (byte*)Allocator::Allocate(newLength); - if (newBuf == nullptr) - { - OUT_OF_MEMORY; - } if (_buffer && _length) Platform::MemoryCopy(newBuf, _buffer, _length); if (_allocated) diff --git a/Source/Engine/Platform/Android/AndroidDefines.h b/Source/Engine/Platform/Android/AndroidDefines.h index 5cf857976..6fef09129 100644 --- a/Source/Engine/Platform/Android/AndroidDefines.h +++ b/Source/Engine/Platform/Android/AndroidDefines.h @@ -32,6 +32,7 @@ #endif #define PLATFORM_TYPE PlatformType::Android #define PLATFORM_CACHE_LINE_SIZE 64 +#define PLATFORM_OUT_OF_MEMORY_BUFFER_SIZE (64ull * 1024) // 64 kB #define USE_MONO_AOT_MODE MONO_AOT_MODE_NONE diff --git a/Source/Engine/Platform/Base/PlatformBase.cpp b/Source/Engine/Platform/Base/PlatformBase.cpp index 93b06b821..31830060f 100644 --- a/Source/Engine/Platform/Base/PlatformBase.cpp +++ b/Source/Engine/Platform/Base/PlatformBase.cpp @@ -49,6 +49,7 @@ float PlatformBase::CustomDpiScale = 1.0f; Array> PlatformBase::Users; Delegate PlatformBase::UserAdded; Delegate PlatformBase::UserRemoved; +void* OutOfMemoryBuffer = nullptr; const Char* ToString(NetworkConnectionType value) { @@ -150,6 +151,12 @@ bool PlatformBase::Init() srand((unsigned int)Platform::GetTimeCycles()); + // Preallocate safety dynamic buffer to be released before Out Of Memory reporting to ensure code can properly execute +#ifndef PLATFORM_OUT_OF_MEMORY_BUFFER_SIZE +#define PLATFORM_OUT_OF_MEMORY_BUFFER_SIZE (1ull * 1024 * 1024) // 1 MB +#endif + OutOfMemoryBuffer = Allocator::Allocate(PLATFORM_OUT_OF_MEMORY_BUFFER_SIZE); + return false; } @@ -188,6 +195,8 @@ void PlatformBase::BeforeExit() void PlatformBase::Exit() { + Allocator::Free(OutOfMemoryBuffer); + OutOfMemoryBuffer = nullptr; } #if COMPILE_WITH_PROFILER @@ -257,25 +266,35 @@ bool PlatformBase::Is64BitApp() #endif } -void PlatformBase::Fatal(const Char* msg, void* context) +void PlatformBase::Fatal(const StringView& msg, void* context, FatalErrorType error) { // Check if is already during fatal state - if (Globals::FatalErrorOccurred) + if (Engine::FatalError != FatalErrorType::None) { // Just send one more error to the log and back LOG(Error, "Error after fatal error: {0}", msg); return; } + // Free OOM safety buffer + Allocator::Free(OutOfMemoryBuffer); + OutOfMemoryBuffer = nullptr; + // Set flags + PRAGMA_DISABLE_DEPRECATION_WARNINGS; Globals::FatalErrorOccurred = true; Globals::IsRequestingExit = true; - Globals::ExitCode = -1; + Globals::ExitCode = -Math::Max((int32)error, 1); + PRAGMA_ENABLE_DEPRECATION_WARNINGS; + Engine::IsRequestingExit = true; + Engine::ExitCode = -Math::Max((int32)error, 1); + Engine::FatalError = error; Engine::RequestingExit(); // Collect crash info (platform-dependant implementation that might collect stack trace and/or create memory dump) { // Log separation for crash info + LOG_FLUSH(); Log::Logger::WriteFloor(); LOG(Error, ""); LOG(Error, "Critical error! Reason: {0}", msg); @@ -358,11 +377,11 @@ void PlatformBase::Fatal(const Char* msg, void* context) // Only main thread can call exit directly if (IsInMainThread()) { - Engine::Exit(-1); + Engine::Exit(Engine::ExitCode, error); } } -void PlatformBase::Error(const Char* msg) +void PlatformBase::Error(const StringView& msg) { #if PLATFORM_HAS_HEADLESS_MODE if (CommandLine::Options.Headless.IsTrue()) @@ -372,7 +391,7 @@ void PlatformBase::Error(const Char* msg) ansi += PLATFORM_LINE_TERMINATOR; printf("Error: %s\n", ansi.Get()); #else - std::cout << "Error: " << msg << std::endl; + std::cout << "Error: " << *msg << std::endl; #endif } else @@ -382,12 +401,12 @@ void PlatformBase::Error(const Char* msg) } } -void PlatformBase::Warning(const Char* msg) +void PlatformBase::Warning(const StringView& msg) { #if PLATFORM_HAS_HEADLESS_MODE if (CommandLine::Options.Headless.IsTrue()) { - std::cout << "Warning: " << msg << std::endl; + std::cout << "Warning: " << *msg << std::endl; } else #endif @@ -396,12 +415,12 @@ void PlatformBase::Warning(const Char* msg) } } -void PlatformBase::Info(const Char* msg) +void PlatformBase::Info(const StringView& msg) { #if PLATFORM_HAS_HEADLESS_MODE if (CommandLine::Options.Headless.IsTrue()) { - std::cout << "Info: " << msg << std::endl; + std::cout << "Info: " << *msg << std::endl; } else #endif @@ -410,24 +429,9 @@ void PlatformBase::Info(const Char* msg) } } -void PlatformBase::Fatal(const StringView& msg) +void PlatformBase::Fatal(const StringView& msg, FatalErrorType error) { - Fatal(*msg); -} - -void PlatformBase::Error(const StringView& msg) -{ - Error(*msg); -} - -void PlatformBase::Warning(const StringView& msg) -{ - Warning(*msg); -} - -void PlatformBase::Info(const StringView& msg) -{ - Info(*msg); + Fatal(msg, nullptr, error); } void PlatformBase::Log(const StringView& msg) @@ -443,28 +447,43 @@ void PlatformBase::Crash(int32 line, const char* file) { const StringAsUTF16<256> fileUTF16(file); const String msg = String::Format(TEXT("Fatal crash!\nFile: {0}\nLine: {1}"), fileUTF16.Get(), line); - LOG_STR(Fatal, msg); + LOG_STR(Error, msg); + Fatal(msg, nullptr, FatalErrorType::Assertion); } void PlatformBase::OutOfMemory(int32 line, const char* file) { - const StringAsUTF16<256> fileUTF16(file); - const String msg = String::Format(TEXT("Out of memory error!\nFile: {0}\nLine: {1}"), fileUTF16.Get(), line); - LOG_STR(Fatal, msg); + fmt_flax::allocator allocator; + fmt_flax::memory_buffer buffer(allocator); + static_assert(fmt::inline_buffer_size > 300, "Update stack buffer to prevent dynamic memory allocation on Out Of Memory."); + if (file) + { + const StringAsUTF16<256> fileUTF16(file); + fmt_flax::format(buffer, TEXT("Out of memory error!\nFile: {0}\nLine: {1}"), fileUTF16.Get(), line); + } + else + { + fmt_flax::format(buffer, TEXT("Out of memory error!")); + } + const StringView msg(buffer.data(), (int32)buffer.size()); + LOG_STR(Error, msg); + Fatal(msg, nullptr, FatalErrorType::OutOfMemory); } void PlatformBase::MissingCode(int32 line, const char* file, const char* info) { const StringAsUTF16<256> fileUTF16(file); const String msg = String::Format(TEXT("TODO: {0}\nFile: {1}\nLine: {2}"), String(info), fileUTF16.Get(), line); - LOG_STR(Fatal, msg); + LOG_STR(Error, msg); + Fatal(msg, nullptr, FatalErrorType::Assertion); } void PlatformBase::Assert(const char* message, const char* file, int line) { const StringAsUTF16<256> fileUTF16(file); const String msg = String::Format(TEXT("Assertion failed!\nFile: {0}\nLine: {1}\n\nExpression: {2}"), fileUTF16.Get(), line, String(message)); - LOG_STR(Fatal, msg); + LOG_STR(Error, msg); + Fatal(msg, nullptr, FatalErrorType::Assertion); } void PlatformBase::CheckFailed(const char* message, const char* file, int line) diff --git a/Source/Engine/Platform/Base/PlatformBase.h b/Source/Engine/Platform/Base/PlatformBase.h index d5ff4c59f..e34bf3015 100644 --- a/Source/Engine/Platform/Base/PlatformBase.h +++ b/Source/Engine/Platform/Base/PlatformBase.h @@ -125,6 +125,23 @@ enum class ThreadPriority extern FLAXENGINE_API const Char* ToString(ThreadPriority value); +/// +/// Possible fatal error types that cause engine exit. +/// +API_ENUM() enum class FatalErrorType +{ + // No fatal error set. + None, + // Not defined or custom error. + Unknown, + // Runtime exception caught by the handler (eg. stack overflow, invalid memory address access). + Exception, + // Data assertion failed (eg. invalid value or code usage). + Assertion, + // Program run out of memory to allocate. + OutOfMemory, +}; + API_INJECT_CODE(cpp, "#include \"Engine/Platform/Platform.h\""); /// @@ -457,32 +474,15 @@ public: /// /// The message content. /// The platform-dependent context for the stack trace collecting (eg. platform exception info). - static void Fatal(const Char* msg, void* context = nullptr); + /// The fatal error type. + API_FUNCTION() static void Fatal(const StringView& msg, void* context, FatalErrorType error = FatalErrorType::Unknown); - /// - /// Shows the error message to the user. - /// - /// The message content. - static void Error(const Char* msg); - - /// - /// Shows the warning message to the user. - /// - /// The message content. - static void Warning(const Char* msg); - - /// - /// Shows the information message to the user. - /// - /// The message content. - static void Info(const Char* msg); - -public: /// /// Shows the fatal error message to the user. /// /// The message content. - API_FUNCTION() static void Fatal(const StringView& msg); + /// The fatal error type. + API_FUNCTION() static void Fatal(const StringView& msg, FatalErrorType error = FatalErrorType::Unknown); /// /// Shows the error message to the user. @@ -527,7 +527,7 @@ public: /// /// The source line. /// The source file. - NO_RETURN static void OutOfMemory(int32 line, const char* file); + NO_RETURN static void OutOfMemory(int32 line = -1, const char* file = nullptr); /// /// Performs a fatal crash due to code not being implemented. diff --git a/Source/Engine/Platform/Unix/UnixPlatform.cpp b/Source/Engine/Platform/Unix/UnixPlatform.cpp index afa207d9c..5b065bfef 100644 --- a/Source/Engine/Platform/Unix/UnixPlatform.cpp +++ b/Source/Engine/Platform/Unix/UnixPlatform.cpp @@ -30,6 +30,8 @@ void* UnixPlatform::Allocate(uint64 size, uint64 alignment) // Calculate the offset and store it behind aligned pointer *((offset_t*)ptr - 1) = (offset_t)((uintptr_t)ptr - (uintptr_t)p); } + else + OutOfMemory(); #if COMPILE_WITH_PROFILER OnMemoryAlloc(ptr, size); #endif diff --git a/Source/Engine/Platform/Win32/Win32Platform.cpp b/Source/Engine/Platform/Win32/Win32Platform.cpp index a9aa784c2..5650a5839 100644 --- a/Source/Engine/Platform/Win32/Win32Platform.cpp +++ b/Source/Engine/Platform/Win32/Win32Platform.cpp @@ -259,6 +259,8 @@ void Win32Platform::Prefetch(void const* ptr) void* Win32Platform::Allocate(uint64 size, uint64 alignment) { void* ptr = _aligned_malloc((size_t)size, (size_t)alignment); + if (!ptr) + OutOfMemory(); #if COMPILE_WITH_PROFILER OnMemoryAlloc(ptr, size); #endif diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp index 57d46b1f8..41ea7a340 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp +++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp @@ -282,7 +282,7 @@ long __stdcall WindowsPlatform::SehExceptionHandler(EXCEPTION_POINTERS* ep) } // Skip if engine already crashed - if (Globals::FatalErrorOccurred) + if (Engine::FatalError != FatalErrorType::None) return EXCEPTION_CONTINUE_SEARCH; // Get exception info @@ -326,7 +326,7 @@ long __stdcall WindowsPlatform::SehExceptionHandler(EXCEPTION_POINTERS* ep) } // Crash engine - Platform::Fatal(errorMsg.Get(), ep); + Platform::Fatal(errorMsg.Get(), ep, FatalErrorType::Exception); return EXCEPTION_CONTINUE_SEARCH; } diff --git a/Source/Engine/Platform/iOS/iOSDefines.h b/Source/Engine/Platform/iOS/iOSDefines.h index f9482acbc..fb4ec876b 100644 --- a/Source/Engine/Platform/iOS/iOSDefines.h +++ b/Source/Engine/Platform/iOS/iOSDefines.h @@ -13,6 +13,7 @@ #define PLATFORM_ARCH ArchitectureType::ARM64 #define PLATFORM_CACHE_LINE_SIZE 128 #define PLATFORM_DEBUG_BREAK __builtin_trap() +#define PLATFORM_OUT_OF_MEMORY_BUFFER_SIZE (64ull * 1024) // 64 kB // Use AOT for Mono #define USE_MONO_AOT 1 diff --git a/Source/Engine/Serialization/MemoryWriteStream.cpp b/Source/Engine/Serialization/MemoryWriteStream.cpp index 27047e3fd..77358b116 100644 --- a/Source/Engine/Serialization/MemoryWriteStream.cpp +++ b/Source/Engine/Serialization/MemoryWriteStream.cpp @@ -14,18 +14,7 @@ MemoryWriteStream::MemoryWriteStream() MemoryWriteStream::MemoryWriteStream(uint32 capacity) : _capacity(capacity) { - if (capacity > 0) - { - _buffer = (byte*)Allocator::Allocate(capacity); - if (_buffer == nullptr) - { - OUT_OF_MEMORY; - } - } - else - { - _buffer = nullptr; - } + _buffer = capacity > 0 ? (byte*)Allocator::Allocate(capacity) : nullptr; _position = _buffer; } @@ -46,10 +35,6 @@ void* MemoryWriteStream::Move(uint32 bytes) while (newCapacity < position + bytes) newCapacity *= 2; byte* newBuf = (byte*)Allocator::Allocate(newCapacity); - if (newBuf == nullptr) - { - OUT_OF_MEMORY; - } Platform::MemoryCopy(newBuf, _buffer, _capacity); Allocator::Free(_buffer); @@ -73,10 +58,6 @@ void MemoryWriteStream::Reset(uint32 capacity) { Allocator::Free(_buffer); _buffer = (byte*)Allocator::Allocate(capacity); - if (_buffer == nullptr) - { - OUT_OF_MEMORY; - } _capacity = capacity; } @@ -142,10 +123,6 @@ void MemoryWriteStream::WriteBytes(const void* data, uint32 bytes) while (newCapacity < position + bytes) newCapacity *= 2; byte* newBuf = (byte*)Allocator::Allocate(newCapacity); - if (newBuf == nullptr) - { - OUT_OF_MEMORY; - } Platform::MemoryCopy(newBuf, _buffer, _capacity); Allocator::Free(_buffer); diff --git a/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp b/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp index 4ac46d67c..2ae617070 100644 --- a/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp +++ b/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp @@ -4,6 +4,7 @@ #include "Engine/Core/Log.h" #include "Engine/Core/Types/TimeSpan.h" #include "Engine/Core/Math/Math.h" +#include "Engine/Engine/Engine.h" #include "Engine/Level/Actors/BoxBrush.h" #include "Engine/Level/SceneQuery.h" #include "Engine/Renderer/Renderer.h" @@ -414,7 +415,7 @@ int32 ShadowsOfMordor::Builder::doWork() // Clear _wasBuildCalled = false; IsBakingLightmaps = false; - if (!Globals::FatalErrorOccurred) + if (Engine::FatalError == FatalErrorType::None) deleteState(); // Release scenes data diff --git a/Source/Engine/Video/Video.cpp b/Source/Engine/Video/Video.cpp index cb2881923..2b3ff8efb 100644 --- a/Source/Engine/Video/Video.cpp +++ b/Source/Engine/Video/Video.cpp @@ -328,11 +328,6 @@ void VideoBackendPlayer::UpdateVideoFrame(Span data, TimeSpan time, TimeSp if (VideoFrameMemory.Length() < (int32)slicePitch) { VideoFrameMemory.Allocate(slicePitch); - if (VideoFrameMemory.IsInvalid()) - { - OUT_OF_MEMORY; - return; - } } Platform::MemoryCopy(VideoFrameMemory.Get(), data.Get(), slicePitch);