From 3aaa8e2dcb73ca91a488f21250aceb0267fb15d6 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Mon, 26 Mar 2018 23:20:54 -0700 Subject: Reworked debug message handling to allow user-specified callbacks --- Common/interface/FileWrapper.h | 2 +- Common/interface/FixedBlockMemoryAllocator.h | 2 +- Common/interface/HashUtils.h | 2 +- Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp | 7 + .../GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp | 7 + .../GraphicsTools/src/TextureUploaderD3D11.cpp | 1 + .../GraphicsTools/src/TextureUploaderD3D12.cpp | 1 + Graphics/GraphicsTools/src/TextureUploaderGL.cpp | 1 + Platforms/Android/include/AndroidDebug.h | 11 +- Platforms/Android/src/AndroidDebug.cpp | 26 +++- Platforms/Apple/include/AppleDebug.h | 11 +- Platforms/Apple/src/AppleDebug.mm | 26 ++-- Platforms/Basic/CMakeLists.txt | 1 - Platforms/Basic/interface/BasicPlatformDebug.h | 21 ++- Platforms/Basic/interface/Errors.h | 99 -------------- Platforms/Basic/src/BasicPlatformDebug.cpp | 40 +++++- Platforms/Linux/include/LinuxDebug.h | 11 +- Platforms/Linux/src/LinuxDebug.cpp | 25 ++-- Platforms/UWP/include/UWPDebug.h | 11 +- Platforms/UWP/src/UWPDebug.cpp | 25 ++-- Platforms/Win32/include/Win32Debug.h | 11 +- Platforms/Win32/src/Win32Debug.cpp | 32 +++-- Primitives/CMakeLists.txt | 2 + Primitives/interface/Errors.h | 142 +++++++++++++++++++++ Primitives/src/Errors.cpp | 36 ++++++ 25 files changed, 375 insertions(+), 178 deletions(-) delete mode 100644 Platforms/Basic/interface/Errors.h create mode 100644 Primitives/interface/Errors.h create mode 100644 Primitives/src/Errors.cpp diff --git a/Common/interface/FileWrapper.h b/Common/interface/FileWrapper.h index cd06b898..d0d27736 100644 --- a/Common/interface/FileWrapper.h +++ b/Common/interface/FileWrapper.h @@ -23,7 +23,7 @@ #pragma once -#include "../../Platforms/Basic/interface/Errors.h" +#include "../../Primitives/interface/Errors.h" #include "../../Platforms/Basic/interface/DebugUtilities.h" #include "../../Platforms/interface/FileSystem.h" diff --git a/Common/interface/FixedBlockMemoryAllocator.h b/Common/interface/FixedBlockMemoryAllocator.h index 28383691..c092c203 100644 --- a/Common/interface/FixedBlockMemoryAllocator.h +++ b/Common/interface/FixedBlockMemoryAllocator.h @@ -32,7 +32,7 @@ #include #include #include -#include "../../Platforms/Basic/interface/Errors.h" +#include "../../Primitives/interface/Errors.h" #include "../../Primitives/interface/MemoryAllocator.h" #include "STDAllocator.h" diff --git a/Common/interface/HashUtils.h b/Common/interface/HashUtils.h index c70fd4a8..679884c8 100644 --- a/Common/interface/HashUtils.h +++ b/Common/interface/HashUtils.h @@ -27,7 +27,7 @@ #include #include -#include "../../Platforms/Basic/interface/Errors.h" +#include "../../Primitives/interface/Errors.h" #include "../../Platforms/Basic/interface/DebugUtilities.h" #define LOG_HASH_CONFLICTS 1 diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp index 390b99cd..ff2d46de 100644 --- a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp @@ -52,7 +52,14 @@ static GLenum GetBufferBindTarget(const BufferDesc& Desc) Target = GL_UNIFORM_BUFFER; else if(Desc.BindFlags & BIND_INDIRECT_DRAW_ARGS) { +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable : 4127) // conditional expression is constant +#endif VERIFY(GL_DRAW_INDIRECT_BUFFER != 0, "Inidrect draw is not supported"); +#ifdef _MSC_VER +# pragma warning(pop) +#endif Target = GL_DRAW_INDIRECT_BUFFER; } else if (Desc.Usage == USAGE_CPU_ACCESSIBLE && Desc.CPUAccessFlags == CPU_ACCESS_WRITE) diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp index 46653e2a..46ee6ca2 100644 --- a/Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/BufferViewGLImpl.cpp @@ -42,7 +42,14 @@ namespace Diligent { if( ViewDesc.ViewType == BUFFER_VIEW_SHADER_RESOURCE && pBuffer->GetDesc().Mode == BUFFER_MODE_FORMATTED ) { +#ifdef _MSC_VER +# pragma warning(push) +# pragma warning(disable : 4127) // conditional expression is constant +#endif VERIFY( GL_TEXTURE_BUFFER != 0, "GL texture buffers are not supported"); +#ifdef _MSC_VER +# pragma warning(pop) +#endif auto *pContextGL = ValidatedCast(pContext); auto &ContextState = pContextGL->GetContextState(); diff --git a/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp b/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp index 25bb1e62..77fdd722 100644 --- a/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp +++ b/Graphics/GraphicsTools/src/TextureUploaderD3D11.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "TextureUploaderD3D11.h" diff --git a/Graphics/GraphicsTools/src/TextureUploaderD3D12.cpp b/Graphics/GraphicsTools/src/TextureUploaderD3D12.cpp index c5bfdb7b..98b3f40f 100644 --- a/Graphics/GraphicsTools/src/TextureUploaderD3D12.cpp +++ b/Graphics/GraphicsTools/src/TextureUploaderD3D12.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include "TextureUploaderD3D12.h" diff --git a/Graphics/GraphicsTools/src/TextureUploaderGL.cpp b/Graphics/GraphicsTools/src/TextureUploaderGL.cpp index 8f5e863b..9dc02199 100644 --- a/Graphics/GraphicsTools/src/TextureUploaderGL.cpp +++ b/Graphics/GraphicsTools/src/TextureUploaderGL.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include "TextureUploaderGL.h" namespace Diligent diff --git a/Platforms/Android/include/AndroidDebug.h b/Platforms/Android/include/AndroidDebug.h index 981ff767..b0cf7c80 100644 --- a/Platforms/Android/include/AndroidDebug.h +++ b/Platforms/Android/include/AndroidDebug.h @@ -27,6 +27,13 @@ struct AndroidDebug : public BasicPlatformDebug { - static void AssertionFailed( const Diligent::Char *Message, const char *Function, const char *File, int Line ); - static void OutputDebugMessage( DebugMessageSeverity Severity, const Diligent::Char *Message ); + static void AssertionFailed( const Diligent::Char *Message, + const char *Function, // type of __FUNCTION__ + const char *File, // type of __FILE__ + int Line ); + static void OutputDebugMessage( Diligent::DebugMessageSeverity Severity, + const Diligent::Char *Message, + const char *Function, // type of __FUNCTION__ + const char *File, // type of __FILE__ + int Line); }; diff --git a/Platforms/Android/src/AndroidDebug.cpp b/Platforms/Android/src/AndroidDebug.cpp index 8b8556ad..757fdf69 100644 --- a/Platforms/Android/src/AndroidDebug.cpp +++ b/Platforms/Android/src/AndroidDebug.cpp @@ -26,27 +26,39 @@ #include #include -void AndroidDebug :: AssertionFailed( const Diligent::Char *Message, const char *Function, const char *File, int Line ) +using namespace Diligent; + +void AndroidDebug :: AssertionFailed( const Char *Message, const char *Function, const char *File, int Line ) { auto AssertionFailedMessage = FormatAssertionFailedMessage(Message, Function, File, Line); - OutputDebugMessage( DebugMessageSeverity::Error, AssertionFailedMessage.c_str() ); + OutputDebugMessage( DebugMessageSeverity::Error, AssertionFailedMessage.c_str(), nullptr, nullptr, 0 ); raise( SIGTRAP ); }; -void AndroidDebug::OutputDebugMessage( DebugMessageSeverity Severity, const Diligent::Char *Message ) +void AndroidDebug::OutputDebugMessage(DebugMessageSeverity Severity, const Char *Message, const char *Function, const char *File, int Line) { + auto msg = FormatDebugMessage(Severity, Message, Function, File, Line); static const android_LogPriority Priorities[] = { ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL }; - __android_log_print( Priorities[static_cast(Severity)], "Diligent Engine", "%s", Message ); + __android_log_print( Priorities[static_cast(Severity)], "Diligent Engine", "%s", msg.c_str() ); } -void DebugAssertionFailed(const Diligent::Char* Message, const char* Function, const char* File, int Line) +void DebugAssertionFailed(const Char* Message, const char* Function, const char* File, int Line) { AndroidDebug :: AssertionFailed( Message, Function, File, Line ); } -void OutputDebugMessage(BasicPlatformDebug::DebugMessageSeverity Severity, const Diligent::Char* Message) +namespace +{ + +class SetDefaultDebugMessageCallback { - AndroidDebug::OutputDebugMessage( Severity, Message ); +public: + SetDefaultDebugMessageCallback() + { + SetDebugMessageCallback(AndroidDebug::OutputDebugMessage); + } +}static _SetDefaultDebugMessageCallback; + } diff --git a/Platforms/Apple/include/AppleDebug.h b/Platforms/Apple/include/AppleDebug.h index 0843ae85..77705243 100644 --- a/Platforms/Apple/include/AppleDebug.h +++ b/Platforms/Apple/include/AppleDebug.h @@ -27,6 +27,13 @@ struct AppleDebug : public BasicPlatformDebug { - static void AssertionFailed( const Diligent::Char *Message, const char *Function, const char *File, int Line ); - static void OutputDebugMessage( DebugMessageSeverity Severity, const Diligent::Char *Message ); + static void AssertionFailed( const Diligent::Char *Message, + const char *Function, // type of __FUNCTION__ + const char *File, // type of __FILE__ + int Line ); + static void OutputDebugMessage( Diligent::DebugMessageSeverity Severity, + const Diligent::Char *Message, + const char *Function, // type of __FUNCTION__ + const char *File, // type of __FILE__ + int Line); }; diff --git a/Platforms/Apple/src/AppleDebug.mm b/Platforms/Apple/src/AppleDebug.mm index cd0eba57..7db2729f 100644 --- a/Platforms/Apple/src/AppleDebug.mm +++ b/Platforms/Apple/src/AppleDebug.mm @@ -34,20 +34,17 @@ using namespace Diligent; void AppleDebug :: AssertionFailed( const Char *Message, const char *Function, const char *File, int Line ) { auto AssertionFailedMessage = FormatAssertionFailedMessage(Message, Function, File, Line); - OutputDebugMessage(DebugMessageSeverity::Error, AssertionFailedMessage.c_str()); + OutputDebugMessage(DebugMessageSeverity::Error, AssertionFailedMessage.c_str(), nullptr, nullptr, 0); raise( SIGTRAP ); }; -void AppleDebug::OutputDebugMessage( DebugMessageSeverity Severity, const Char *Message ) +void AppleDebug::OutputDebugMessage(DebugMessageSeverity Severity, const Char *Message, const char *Function, const char *File, int Line) { - static const Char* const strSeverities[] = { "Info: ", "Warning: ", "ERROR: ", "CRITICAL ERROR: " }; - auto* MessageSevery = strSeverities[static_cast(Severity)]; - String str = MessageSevery; - str += Message; + auto msg = FormatDebugMessage(Severity, Message, Function, File, Line); // NSLog truncates the log at 1024 symbols - printf("%s\n", str.c_str()); + printf("%s\n", msg.c_str()); //NSLog(@"%s", str.c_str()); } @@ -56,7 +53,16 @@ void DebugAssertionFailed(const Diligent::Char* Message, const char* Function, c AppleDebug :: AssertionFailed( Message, Function, File, Line ); } -void OutputDebugMessage(BasicPlatformDebug::DebugMessageSeverity Severity, const Diligent::Char* Message) +namespace { - AppleDebug::OutputDebugMessage( Severity, Message ); -} + +class SetDefaultDebugMessageCallback +{ +public: + SetDefaultDebugMessageCallback() + { + SetDebugMessageCallback(AppleDebug::OutputDebugMessage); + } +}static _SetDefaultDebugMessageCallback; + +} \ No newline at end of file diff --git a/Platforms/Basic/CMakeLists.txt b/Platforms/Basic/CMakeLists.txt index 0f87d74b..569af7de 100644 --- a/Platforms/Basic/CMakeLists.txt +++ b/Platforms/Basic/CMakeLists.txt @@ -13,7 +13,6 @@ set(INTERFACE interface/BasicPlatformDebug.h interface/BasicPlatformMisc.h interface/DebugUtilities.h - interface/Errors.h ) if(PLATFORM_LINUX OR PLATFORM_WIN32 OR PLATFORM_MACOS OR PLATFORM_IOS) diff --git a/Platforms/Basic/interface/BasicPlatformDebug.h b/Platforms/Basic/interface/BasicPlatformDebug.h index 09e36cf4..e424a9e0 100644 --- a/Platforms/Basic/interface/BasicPlatformDebug.h +++ b/Platforms/Basic/interface/BasicPlatformDebug.h @@ -23,21 +23,20 @@ #pragma once -#include "../../../Primitives/interface/BasicTypes.h" +#include "../../../Primitives/interface/Errors.h" struct BasicPlatformDebug { - enum class DebugMessageSeverity - { - Info, - Warning, - Error, - FatalError - }; - - static Diligent::String FormatAssertionFailedMessage(const Diligent::Char* Message, const char* Function, const char* File, int Line); + static Diligent::String FormatAssertionFailedMessage(const Diligent::Char* Message, + const char* Function, // type of __FUNCTION__ + const char* File, // type of __FILE__ + int Line); + static Diligent::String FormatDebugMessage(Diligent::DebugMessageSeverity Severity, + const Diligent::Char* Message, + const char* Function, // type of __FUNCTION__ + const char* File, // type of __FILE__ + int Line); }; // Forward declarations of platform-specific debug functions void DebugAssertionFailed(const Diligent::Char* Message, const char* Function, const char* File, int Line); -void OutputDebugMessage(BasicPlatformDebug::DebugMessageSeverity Severity, const Diligent::Char* Message); \ No newline at end of file diff --git a/Platforms/Basic/interface/Errors.h b/Platforms/Basic/interface/Errors.h deleted file mode 100644 index e48916b6..00000000 --- a/Platforms/Basic/interface/Errors.h +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright 2015-2018 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -#pragma once - -#include - -#include "../../../Primitives/interface/FormatMessage.h" -#include "BasicPlatformDebug.h" -#include "BasicFileSystem.h" - -template -void ThrowIf(std::string &&) -{ -} - -template<> -inline void ThrowIf(std::string &&msg) -{ - throw std::runtime_error( std::move(msg) ); -} - -template -void LogError( const char *strFunctionName, const char *strFullFilePath, int Line, const FirstArgType& first, const RestArgsType&... RestArgs ) -{ - std::string FileName; - BasicFileSystem::SplitFilePath( strFullFilePath, nullptr, &FileName ); - Diligent::MsgStream ss; - ss << "The following error occured in the " << strFunctionName << "() function (" << FileName << ", line " << Line << "):\n"; - Diligent::FormatMsg( ss, first, RestArgs... ); - auto strFullMessage = ss.str(); - OutputDebugMessage( bThrowException ? BasicPlatformDebug::DebugMessageSeverity::FatalError : BasicPlatformDebug::DebugMessageSeverity::Error, strFullMessage.c_str() ); - ThrowIf(std::move(strFullMessage)); -} - -#define LOG_ERROR(...)\ -do{ \ - LogError(__FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \ -}while(false) - -#define LOG_ERROR_ONCE(...)\ -do{ \ - static bool IsFirstTime = true; \ - if(IsFirstTime) \ - { \ - LogError(__FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \ - IsFirstTime = false; \ - } \ -}while(false) - -#define LOG_ERROR_AND_THROW(...)\ -do{ \ - LogError(__FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__);\ -}while(false) - -#define LOG_DEBUG_MESSAGE(Severity, ...)\ -do{ \ - Diligent::MsgStream ss; \ - Diligent::FormatMsg( ss, ##__VA_ARGS__ );\ - OutputDebugMessage( Severity, ss.str().c_str() );\ -}while(false) - -#define LOG_ERROR_MESSAGE(...) LOG_DEBUG_MESSAGE(BasicPlatformDebug::DebugMessageSeverity::Error, ##__VA_ARGS__) -#define LOG_WARNING_MESSAGE(...) LOG_DEBUG_MESSAGE(BasicPlatformDebug::DebugMessageSeverity::Warning, ##__VA_ARGS__) -#define LOG_INFO_MESSAGE(...) LOG_DEBUG_MESSAGE(BasicPlatformDebug::DebugMessageSeverity::Info, ##__VA_ARGS__) - -#define LOG_DEBUG_MESSAGE_ONCE(Severity, ...)\ -do{ \ - static bool IsFirstTime = true; \ - if(IsFirstTime) \ - { \ - LOG_DEBUG_MESSAGE(Severity, ##__VA_ARGS__);\ - IsFirstTime = false; \ - } \ -}while(false) - -#define LOG_ERROR_MESSAGE_ONCE(...) LOG_DEBUG_MESSAGE_ONCE(BasicPlatformDebug::DebugMessageSeverity::Error, ##__VA_ARGS__) -#define LOG_WARNING_MESSAGE_ONCE(...) LOG_DEBUG_MESSAGE_ONCE(BasicPlatformDebug::DebugMessageSeverity::Warning, ##__VA_ARGS__) -#define LOG_INFO_MESSAGE_ONCE(...) LOG_DEBUG_MESSAGE_ONCE(BasicPlatformDebug::DebugMessageSeverity::Info, ##__VA_ARGS__) diff --git a/Platforms/Basic/src/BasicPlatformDebug.cpp b/Platforms/Basic/src/BasicPlatformDebug.cpp index 5d93ac15..31e46692 100644 --- a/Platforms/Basic/src/BasicPlatformDebug.cpp +++ b/Platforms/Basic/src/BasicPlatformDebug.cpp @@ -28,14 +28,46 @@ using namespace Diligent; -String BasicPlatformDebug :: FormatAssertionFailedMessage( const Diligent::Char *Message, - const char *Function, - const char *File, +String BasicPlatformDebug :: FormatAssertionFailedMessage( const Char *Message, + const char *Function, // type of __FUNCTION__ + const char *File, // type of __FILE__ int Line ) { - std::string FileName; + String FileName; BasicFileSystem::SplitFilePath( File, nullptr, &FileName ); std::stringstream msgss; Diligent::FormatMsg( msgss, "Debug assertion failed in ", Function, "(), file ", FileName, ", line ", Line, ":\n", Message); return msgss.str(); } + +String BasicPlatformDebug::FormatDebugMessage(DebugMessageSeverity Severity, + const Char* Message, + const char* Function, // type of __FUNCTION__ + const char* File, // type of __FILE__ + int Line) +{ + std::stringstream msg_ss; + + static const Char* const strSeverities[] = { "Info", "Warning", "ERROR", "CRITICAL ERROR" }; + const auto* MessageSevery = strSeverities[static_cast(Severity)]; + + msg_ss << "Diligent Engine: " << MessageSevery; + if(Function != nullptr || File != nullptr) + { + msg_ss << " in "; + if(Function != nullptr) + { + msg_ss << Function << "()"; + if(File != nullptr) + msg_ss << " ("; + } + + if(File != nullptr) + { + msg_ss << File << ", " << Line << ')'; + } + } + msg_ss << ": " << Message << '\n'; + + return msg_ss.str(); +} diff --git a/Platforms/Linux/include/LinuxDebug.h b/Platforms/Linux/include/LinuxDebug.h index 6c271fd7..abef120f 100644 --- a/Platforms/Linux/include/LinuxDebug.h +++ b/Platforms/Linux/include/LinuxDebug.h @@ -27,6 +27,13 @@ struct LinuxDebug : public BasicPlatformDebug { - static void AssertionFailed( const Diligent::Char *Message, const char *Function, const char *File, int Line ); - static void OutputDebugMessage( DebugMessageSeverity Severity, const Diligent::Char *Message ); + static void AssertionFailed( const Diligent::Char *Message, + const char *Function, // type of __FUNCTION__ + const char *File, // type of __FILE__ + int Line ); + static void OutputDebugMessage( Diligent::DebugMessageSeverity Severity, + const Diligent::Char *Message, + const char *Function, // type of __FUNCTION__ + const char *File, // type of __FILE__ + int Line); }; diff --git a/Platforms/Linux/src/LinuxDebug.cpp b/Platforms/Linux/src/LinuxDebug.cpp index 776f6208..3d968873 100644 --- a/Platforms/Linux/src/LinuxDebug.cpp +++ b/Platforms/Linux/src/LinuxDebug.cpp @@ -32,20 +32,16 @@ using namespace Diligent; void LinuxDebug :: AssertionFailed( const Char *Message, const char *Function, const char *File, int Line ) { auto AssertionFailedMessage = FormatAssertionFailedMessage(Message, Function, File, Line); - OutputDebugMessage(DebugMessageSeverity::Error, AssertionFailedMessage.c_str()); + OutputDebugMessage(DebugMessageSeverity::Error, AssertionFailedMessage.c_str(), nullptr, nullptr, 0); raise( SIGTRAP ); }; -void LinuxDebug::OutputDebugMessage( DebugMessageSeverity Severity, const Char *Message ) +void LinuxDebug::OutputDebugMessage(DebugMessageSeverity Severity, const Char *Message, const char *Function, const char *File, int Line) { - static const Char* const strSeverities[] = { "Info: ", "Warning: ", "ERROR: ", "CRITICAL ERROR: " }; - auto* MessageSevery = strSeverities[static_cast(Severity)]; - String str = MessageSevery; - str += Message; - str += '\n'; - std::cerr << str; + auto msg = FormatDebugMessage(Severity, Message, Function, File, Line); + std::cerr << msg; } void DebugAssertionFailed(const Diligent::Char* Message, const char* Function, const char* File, int Line) @@ -53,7 +49,16 @@ void DebugAssertionFailed(const Diligent::Char* Message, const char* Function, c LinuxDebug :: AssertionFailed( Message, Function, File, Line ); } -void OutputDebugMessage(BasicPlatformDebug::DebugMessageSeverity Severity, const Diligent::Char* Message) +namespace { - LinuxDebug::OutputDebugMessage( Severity, Message ); + +class SetDefaultDebugMessageCallback +{ +public: + SetDefaultDebugMessageCallback() + { + SetDebugMessageCallback(LinuxDebug::OutputDebugMessage); + } +}static _SetDefaultDebugMessageCallback; + } diff --git a/Platforms/UWP/include/UWPDebug.h b/Platforms/UWP/include/UWPDebug.h index b193968e..f2acc23e 100644 --- a/Platforms/UWP/include/UWPDebug.h +++ b/Platforms/UWP/include/UWPDebug.h @@ -27,6 +27,13 @@ struct WindowsStoreDebug : public BasicPlatformDebug { - static void AssertionFailed( const Diligent::Char *Message, const char *Function, const char *File, int Line ); - static void OutputDebugMessage( DebugMessageSeverity Severity, const Diligent::Char *Message ); + static void AssertionFailed( const Diligent::Char *Message, + const char *Function, // type of __FUNCTION__ + const char *File, // type of __FILE__ + int Line ); + static void OutputDebugMessage( Diligent::DebugMessageSeverity Severity, + const Diligent::Char *Message, + const char *Function, // type of __FUNCTION__ + const char *File, // type of __FILE__ + int Line); }; diff --git a/Platforms/UWP/src/UWPDebug.cpp b/Platforms/UWP/src/UWPDebug.cpp index 8db12a04..3ee31ab6 100644 --- a/Platforms/UWP/src/UWPDebug.cpp +++ b/Platforms/UWP/src/UWPDebug.cpp @@ -35,7 +35,7 @@ using namespace Diligent; void WindowsStoreDebug :: AssertionFailed( const Diligent::Char *Message, const char *Function, const char *File, int Line ) { auto AssertionFailedMessage = FormatAssertionFailedMessage(Message, Function, File, Line); - OutputDebugMessage( DebugMessageSeverity::Error, AssertionFailedMessage.c_str() ); + OutputDebugMessage( DebugMessageSeverity::Error, AssertionFailedMessage.c_str(), nullptr, nullptr, 0 ); __debugbreak(); //int nCode = MessageBoxA(NULL, @@ -68,14 +68,10 @@ void WindowsStoreDebug :: AssertionFailed( const Diligent::Char *Message, const }; -void WindowsStoreDebug::OutputDebugMessage( DebugMessageSeverity Severity, const Diligent::Char *Message ) +void WindowsStoreDebug::OutputDebugMessage(DebugMessageSeverity Severity, const Char *Message, const char *Function, const char *File, int Line) { - static const Char* const strSeverities[] = { "Info: ", "Warning: ", "ERROR: ", "CRITICAL ERROR: " }; - auto* MessageSevery = strSeverities[static_cast(Severity)]; - String str = MessageSevery; - str += Message; - str += '\n'; - OutputDebugStringA( str.c_str() ); + auto msg = FormatDebugMessage(Severity, Message, Function, File, Line); + OutputDebugStringA( msg.c_str() ); } void DebugAssertionFailed(const Diligent::Char* Message, const char* Function, const char* File, int Line) @@ -83,7 +79,16 @@ void DebugAssertionFailed(const Diligent::Char* Message, const char* Function, c WindowsStoreDebug :: AssertionFailed( Message, Function, File, Line ); } -void OutputDebugMessage(BasicPlatformDebug::DebugMessageSeverity Severity, const Diligent::Char* Message) +namespace { - WindowsStoreDebug::OutputDebugMessage( Severity, Message ); + +class SetDefaultDebugMessageCallback +{ +public: + SetDefaultDebugMessageCallback() + { + SetDebugMessageCallback(WindowsStoreDebug::OutputDebugMessage); + } +}static _SetDefaultDebugMessageCallback; + } diff --git a/Platforms/Win32/include/Win32Debug.h b/Platforms/Win32/include/Win32Debug.h index de8fff31..3a937415 100644 --- a/Platforms/Win32/include/Win32Debug.h +++ b/Platforms/Win32/include/Win32Debug.h @@ -27,6 +27,13 @@ struct WindowsDebug : public BasicPlatformDebug { - static void AssertionFailed( const Diligent::Char *Message, const char *Function, const char *File, int Line ); - static void OutputDebugMessage( DebugMessageSeverity Severity, const Diligent::Char *Message ); + static void AssertionFailed( const Diligent::Char *Message, + const char *Function, // type of __FUNCTION__ + const char *File, // type of __FILE__ + int Line ); + static void OutputDebugMessage( Diligent::DebugMessageSeverity Severity, + const Diligent::Char *Message, + const char *Function, // type of __FUNCTION__ + const char *File, // type of __FILE__ + int Line); }; diff --git a/Platforms/Win32/src/Win32Debug.cpp b/Platforms/Win32/src/Win32Debug.cpp index 01904c81..85dc4870 100644 --- a/Platforms/Win32/src/Win32Debug.cpp +++ b/Platforms/Win32/src/Win32Debug.cpp @@ -34,7 +34,7 @@ using namespace Diligent; void WindowsDebug :: AssertionFailed( const Diligent::Char *Message, const char *Function, const char *File, int Line ) { auto AssertionFailedMessage = FormatAssertionFailedMessage(Message, Function, File, Line); - OutputDebugMessage( DebugMessageSeverity::Error, AssertionFailedMessage.c_str()); + OutputDebugMessage( DebugMessageSeverity::Error, AssertionFailedMessage.c_str(), nullptr, nullptr, 0); int nCode = MessageBoxA(NULL, AssertionFailedMessage.c_str(), @@ -65,19 +65,15 @@ void WindowsDebug :: AssertionFailed( const Diligent::Char *Message, const char return; }; -void WindowsDebug::OutputDebugMessage( DebugMessageSeverity Severity, const Diligent::Char *Message ) +void WindowsDebug::OutputDebugMessage( DebugMessageSeverity Severity, const Char *Message, const char *Function, const char *File, int Line) { - static const Char* const strSeverities[] = { "Info: ", "Warning: ", "ERROR: ", "CRITICAL ERROR: " }; - auto* MessageSevery = strSeverities[ static_cast(Severity) ]; - String str = MessageSevery; - str += Message; - str += '\n'; - OutputDebugStringA( str.c_str() ); + auto msg = FormatDebugMessage(Severity, Message, Function, File, Line); + OutputDebugStringA(msg.c_str()); if( Severity == DebugMessageSeverity::Error || Severity == DebugMessageSeverity::FatalError ) - std::cerr< +#include +#include + +#include "BasicTypes.h" +#include "FormatMessage.h" + +namespace Diligent +{ + +/// Describes debug message severity +enum class DebugMessageSeverity : Int32 +{ + /// Information message + Info = 0, + + /// Warning message + Warning, + + /// Error, with potential recovery + Error, + + /// Fatal error - recovery is not possible + FatalError +}; + +using DebugMessageCallbackType = void(*)(DebugMessageSeverity, const Char* Message, const char* Function, const char* File, int Line); +extern DebugMessageCallbackType DebugMessageCallback; + +void SetDebugMessageCallback(DebugMessageCallbackType DbgMessageCallback); + + +template +void ThrowIf(std::string &&) +{ +} + +template<> +inline void ThrowIf(std::string &&msg) +{ + throw std::runtime_error( std::move(msg) ); +} + +template +void LogError( const char *Function, const char *FullFilePath, int Line, const FirstArgType& first, const RestArgsType&... RestArgs ) +{ + std::string FileName(FullFilePath); + auto LastSlashPos = FileName.find_last_of("/\\"); + if(LastSlashPos != std::string::npos) + FileName.erase(0, LastSlashPos+1); + Diligent::MsgStream ss; + Diligent::FormatMsg( ss, first, RestArgs... ); + auto Msg = ss.str(); + if(DebugMessageCallback != nullptr) + { + DebugMessageCallback( bThrowException ? DebugMessageSeverity::FatalError : DebugMessageSeverity::Error, Msg.c_str(), Function, FileName.c_str(), Line); + } + else + { + // No callback set - output to cerr + std::cerr << "Diligent Engine: " << (bThrowException ? "Fatal Error" : "Error") << " in " << Function << "() (" << FileName << ", " << Line << "): " << Msg << '\n'; + } + ThrowIf(std::move(Msg)); +} + +} + + + +#define LOG_ERROR(...)\ +do{ \ + Diligent::LogError(__FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \ +}while(false) + + +#define LOG_ERROR_ONCE(...)\ +do{ \ + static bool IsFirstTime = true; \ + if(IsFirstTime) \ + { \ + LOG_ERROR(##__VA_ARGS__); \ + IsFirstTime = false; \ + } \ +}while(false) + + +#define LOG_ERROR_AND_THROW(...)\ +do{ \ + Diligent::LogError(__FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__);\ +}while(false) + + +#define LOG_DEBUG_MESSAGE(Severity, ...)\ +do{ \ + Diligent::MsgStream ss; \ + Diligent::FormatMsg( ss, ##__VA_ARGS__ );\ + if(Diligent::DebugMessageCallback != nullptr) Diligent::DebugMessageCallback( Severity, ss.str().c_str(), nullptr, nullptr, 0 );\ +}while(false) + +#define LOG_ERROR_MESSAGE(...) LOG_DEBUG_MESSAGE(Diligent::DebugMessageSeverity::Error, ##__VA_ARGS__) +#define LOG_WARNING_MESSAGE(...) LOG_DEBUG_MESSAGE(Diligent::DebugMessageSeverity::Warning, ##__VA_ARGS__) +#define LOG_INFO_MESSAGE(...) LOG_DEBUG_MESSAGE(Diligent::DebugMessageSeverity::Info, ##__VA_ARGS__) + + +#define LOG_DEBUG_MESSAGE_ONCE(Severity, ...)\ +do{ \ + static bool IsFirstTime = true; \ + if(IsFirstTime) \ + { \ + LOG_DEBUG_MESSAGE(Severity, ##__VA_ARGS__);\ + IsFirstTime = false; \ + } \ +}while(false) + +#define LOG_ERROR_MESSAGE_ONCE(...) LOG_DEBUG_MESSAGE_ONCE(Diligent::DebugMessageSeverity::Error, ##__VA_ARGS__) +#define LOG_WARNING_MESSAGE_ONCE(...) LOG_DEBUG_MESSAGE_ONCE(Diligent::DebugMessageSeverity::Warning, ##__VA_ARGS__) +#define LOG_INFO_MESSAGE_ONCE(...) LOG_DEBUG_MESSAGE_ONCE(Diligent::DebugMessageSeverity::Info, ##__VA_ARGS__) diff --git a/Primitives/src/Errors.cpp b/Primitives/src/Errors.cpp new file mode 100644 index 00000000..2fc552d1 --- /dev/null +++ b/Primitives/src/Errors.cpp @@ -0,0 +1,36 @@ +/* Copyright 2015-2018 Egor Yusov +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. +* +* In no event and under no legal theory, whether in tort (including negligence), +* contract, or otherwise, unless required by applicable law (such as deliberate +* and grossly negligent acts) or agreed to in writing, shall any Contributor be +* liable for any damages, including any direct, indirect, special, incidental, +* or consequential damages of any character arising as a result of this License or +* out of the use or inability to use the software (including but not limited to damages +* for loss of goodwill, work stoppage, computer failure or malfunction, or any and +* all other commercial damages or losses), even if such Contributor has been advised +* of the possibility of such damages. +*/ + +#include "Errors.h" + +namespace Diligent +{ + +DebugMessageCallbackType DebugMessageCallback = nullptr; + +void SetDebugMessageCallback(DebugMessageCallbackType DbgMessageCallback) +{ + DebugMessageCallback = DbgMessageCallback; +} + +} -- cgit v1.2.3