From 3a61b4ef47b7123cb56f64d105a7a29e8fbe63d4 Mon Sep 17 00:00:00 2001 From: vinsentli Date: Wed, 27 Nov 2024 15:05:39 -0800 Subject: [PATCH 1/9] igl | opengl | Fix memory leak in RenderPipelineState::activeAttributesLocations_ (#187) Summary: When a RenderCommandEncoder sequentially binds two IRenderPipelineStates, if both of these states have the same VertexInputState, the previous IRenderPipelineState is unable to execute unbindVertexAttributes(). As a result, the activeAttributesLocations_ of the previous RenderPipelineState remains in a continuous state of memory growth and cannot be released. Pull Request resolved: https://github.com/facebook/igl/pull/187 Reviewed By: KyleFung, rameshviswanathan Differential Revision: D64312736 Pulled By: corporateshark fbshipit-source-id: b8dc13146184c9e88a09f08b6897cb60b7e0391b --- src/igl/opengl/RenderCommandAdapter.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/igl/opengl/RenderCommandAdapter.cpp b/src/igl/opengl/RenderCommandAdapter.cpp index d6f9794a17..d82931cfa9 100644 --- a/src/igl/opengl/RenderCommandAdapter.cpp +++ b/src/igl/opengl/RenderCommandAdapter.cpp @@ -224,12 +224,11 @@ void RenderCommandAdapter::clearDependentResources( clearFragmentTexture(); } - if (!newStateOpenGL || !curStateOpenGL->matchesVertexInputState(*newStateOpenGL)) { - // We do need to clear vertex attributes, when pipelinestate is modified. - // If we don't, subsequent draw calls might try to read from these locations - // and crashes might happen. - unbindVertexAttributes(); + if (curStateOpenGL && newStateOpenGL) { + newStateOpenGL->savePrevPipelineStateAttributesLocations(*curStateOpenGL); + } + if (!newStateOpenGL || !curStateOpenGL->matchesVertexInputState(*newStateOpenGL)) { // Don't reuse previously set vertex buffers. clearVertexBuffers(); } @@ -343,6 +342,7 @@ void RenderCommandAdapter::willDraw() { // Vertex Buffers must be bound before pipelineState->bind() if (pipelineState) { + pipelineState->clearActiveAttributesLocations(); for (size_t bufferIndex = 0; bufferIndex < IGL_VERTEX_BUFFER_MAX; ++bufferIndex) { if (IS_DIRTY(vertexBuffersDirty_, bufferIndex)) { auto& bufferState = vertexBuffers_[bufferIndex]; @@ -352,6 +352,7 @@ void RenderCommandAdapter::willDraw() { CLEAR_DIRTY(vertexBuffersDirty_, bufferIndex); } } + pipelineState->unbindPrevPipelineVertexAttributes(); if (isDirty(StateMask::PIPELINE)) { pipelineState->bind(); clearDirty(StateMask::PIPELINE); From 990964e8be3a59a58ed88169a098ffc80fecb1d0 Mon Sep 17 00:00:00 2001 From: generatedunixname89002005232357 Date: Thu, 28 Nov 2024 01:16:25 -0800 Subject: [PATCH 2/9] Revert D66435523 Reviewed By: corporateshark Differential Revision: D66535307 fbshipit-source-id: 6a05ca37e7e271417238d604ba976e5502d058d8 --- shell/ios/ViewController.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/ios/ViewController.mm b/shell/ios/ViewController.mm index f8455d15cc..6d3b7b4c31 100644 --- a/shell/ios/ViewController.mm +++ b/shell/ios/ViewController.mm @@ -207,7 +207,6 @@ - (void)loadView { kEAGLDrawablePropertyColorFormat, nil]; self.view = openGLView; - self.view.layer.contentsScale = [UIScreen mainScreen].scale; #endif break; } From be1e25aa7b5c5785f1e854e4056a2fa88a835bdd Mon Sep 17 00:00:00 2001 From: vinsentli Date: Mon, 2 Dec 2024 10:55:08 -0800 Subject: [PATCH 3/9] deps.json : add nanovg download (#220) Summary: Pull Request resolved: https://github.com/facebook/igl/pull/220 Reviewed By: rokuz Differential Revision: D66584824 Pulled By: corporateshark fbshipit-source-id: b1531dd52b15d6b5cfe62ec5962178bc90fd1315 --- LICENSE.md | 3 ++ third-party/bootstrap-deps.json | 13 +++++++ third-party/deps/patches/nanovg.patch | 56 +++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) create mode 100644 third-party/deps/patches/nanovg.patch diff --git a/LICENSE.md b/LICENSE.md index 59b9f246f1..1318ea301e 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -80,6 +80,9 @@ https://github.com/corporateshark/lightweightvk/blob/main/LICENSE.md Meshoptimizer https://github.com/zeux/meshoptimizer/blob/master/LICENSE.md +NanoVG +https://github.com/memononen/nanovg/blob/master/LICENSE.txt + Spark SL https://github.com/facebook/igl/releases/download/SparkSL/SparkSL.LICENSE diff --git a/third-party/bootstrap-deps.json b/third-party/bootstrap-deps.json index 65cad073f7..85482ef215 100644 --- a/third-party/bootstrap-deps.json +++ b/third-party/bootstrap-deps.json @@ -194,5 +194,18 @@ "url": "https://github.com/facebook/gfxreconstruct.git", "revision": "99a2ac03e7386c9773804c7b25a3712fd867f458" } +}, +{ + "name": "nanovg", + "postprocess" : { + "type" : "patch", + "file" : "nanovg.patch", + "pnum" : "0" + }, + "source": { + "type": "git", + "url": "https://github.com/memononen/nanovg", + "revision": "f93799c078fa11ed61c078c65a53914c8782c00b" + } } ] diff --git a/third-party/deps/patches/nanovg.patch b/third-party/deps/patches/nanovg.patch new file mode 100644 index 0000000000..04725a2366 --- /dev/null +++ b/third-party/deps/patches/nanovg.patch @@ -0,0 +1,56 @@ +Binary files ./example/.DS_Store and ./example_new/.DS_Store differ +diff --exclude=.git --exclude=.hg -rupN ./example/demo.c ./example_new/demo.c +--- ./example/demo.c 2024-11-30 17:10:38 ++++ ./example_new/demo.c 2024-11-30 17:09:45 +@@ -5,9 +5,7 @@ + #ifdef NANOVG_GLEW + # include + #endif +-#include + #include "nanovg.h" +-#define STB_IMAGE_WRITE_IMPLEMENTATION + #include "stb_image_write.h" + + +@@ -1212,6 +1210,7 @@ static void flipHorizontal(unsigned char* image, int w + } + } + ++#if 0 + void saveScreenShot(int w, int h, int premult, const char* name) + { + unsigned char* image = (unsigned char*)malloc(w*h*4); +@@ -1226,3 +1225,4 @@ void saveScreenShot(int w, int h, int premult, const c + stbi_write_png(name, w, h, 4, image, w*4); + free(image); + } ++#endif +diff --exclude=.git --exclude=.hg -rupN ./example/perf.c ./example_new/perf.c +--- ./example/perf.c 2024-11-30 17:10:39 ++++ ./example_new/perf.c 2024-11-30 17:10:04 +@@ -5,7 +5,6 @@ + #ifdef NANOVG_GLEW + # include + #endif +-#include + #include "nanovg.h" + + #ifdef _MSC_VER +@@ -38,7 +37,7 @@ void initGPUTimer(GPUtimer* timer) + glGenQueries(GPU_QUERY_COUNT, timer->queries); + }*/ + } +- ++#if 0 + void startGPUTimer(GPUtimer* timer) + { + if (!timer->supported) +@@ -72,7 +71,7 @@ int stopGPUTimer(GPUtimer* timer, float* times, int ma + } + return n; + } +- ++#endif + + void initGraph(PerfGraph* fps, int style, const char* name) + { From 412a6ce5818403171f991eb56e911bc08201ff47 Mon Sep 17 00:00:00 2001 From: Eric Griffith Date: Mon, 2 Dec 2024 13:38:07 -0800 Subject: [PATCH 4/9] IGL: Experimentally re-enable code coverage Reviewed By: syeh1 Differential Revision: D66664863 fbshipit-source-id: d7fc75e1543bef885f8c1f46b23e01f51943852f --- shell/shared/fileLoader/win/FileLoaderWin.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/shell/shared/fileLoader/win/FileLoaderWin.cpp b/shell/shared/fileLoader/win/FileLoaderWin.cpp index bab6c1b2cf..b08fc017f6 100644 --- a/shell/shared/fileLoader/win/FileLoaderWin.cpp +++ b/shell/shared/fileLoader/win/FileLoaderWin.cpp @@ -5,8 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -// @fb-only - #include #include From bae00886cf255cb29a7cdf9e8285bceefc26790d Mon Sep 17 00:00:00 2001 From: Nikita Lutsenko Date: Mon, 2 Dec 2024 14:06:16 -0800 Subject: [PATCH 5/9] igl | Fix tiny android sample build. Reviewed By: corporateshark Differential Revision: D66667095 fbshipit-source-id: bf3fc341d2fc26f249d960665e4d92aea4655480 --- samples/android/vulkan/jni/Tiny.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/android/vulkan/jni/Tiny.cpp b/samples/android/vulkan/jni/Tiny.cpp index ebf7a47170..a7bf3a74b0 100644 --- a/samples/android/vulkan/jni/Tiny.cpp +++ b/samples/android/vulkan/jni/Tiny.cpp @@ -178,7 +178,7 @@ void render() { // VK_EXT_debug_utils support doesn't exist yet // commands->pushDebugGroupLabel("Render Triangle", igl::Color(1, 0, 0)); - commands->draw(PrimitiveType::Triangle, 0, 3); + commands->draw(3, 0, 3); // commands->popDebugGroupLabel(); commands->endEncoding(); From e3888a955ea3c11c498d5443f0d4f84026f76ddd Mon Sep 17 00:00:00 2001 From: Sergey Kosarevsky Date: Mon, 2 Dec 2024 14:48:48 -0800 Subject: [PATCH 6/9] igl | Fixed naming and comment formatting (#223) Summary: Pull Request resolved: https://github.com/facebook/igl/pull/223 Reviewed By: KyleFung Differential Revision: D66671775 Pulled By: corporateshark fbshipit-source-id: 987c027ad5daf6ea0d5093caa3c13b79087594d0 --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 24c71324a0..9c98e4d5e9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Contributing to igl +# Contributing to IGL We want to make contributing to this project as easy and transparent as possible. @@ -11,7 +11,7 @@ We actively welcome your pull requests. 4. Ensure the test suite passes. 5. Make sure your code lints. 6. If you haven't already, complete the Contributor License Agreement ("CLA"). -7. Please respect // @fb-only comments and do not delete them! +7. Please respect `// @fb-only` comments and do not delete them! ## Contributor License Agreement ("CLA") In order to accept your pull request, we need you to submit a CLA. You only need From 76e0d4a109b25027157ac060b313e29b1bcea9e6 Mon Sep 17 00:00:00 2001 From: Eric Griffith Date: Mon, 2 Dec 2024 15:50:24 -0800 Subject: [PATCH 7/9] IGL: Harmonize params for _IGLVerify, _IGLSoftError and IGLSoftError Reviewed By: ChristianK275, corporateshark Differential Revision: D66471679 fbshipit-source-id: f1d38b9ac2b79aba214b8b001a0f0aa9c30abc6c --- src/igl/Assert.cpp | 5 +- src/igl/Assert.h | 105 +++++++++++++++++++------- src/igl/tests/util/TestErrorGuard.cpp | 5 +- src/igl/tests/util/TestErrorGuard.h | 5 +- 4 files changed, 85 insertions(+), 35 deletions(-) diff --git a/src/igl/Assert.cpp b/src/igl/Assert.cpp index 39f8b6bad4..1bfcddf5da 100644 --- a/src/igl/Assert.cpp +++ b/src/igl/Assert.cpp @@ -60,10 +60,11 @@ void _IGLDebugBreak() { namespace { // Default handler is no-op. // If there's an error, IGL_DEBUG_VERIFY will trap in dev builds -void IGLReportErrorDefault(const char* /* file */, +void IGLReportErrorDefault(const char* /* category */, + const char* /* reason */, + const char* /* file */, const char* /* func */, int /* line */, - const char* /* category */, const char* /* format */, ...) {} diff --git a/src/igl/Assert.h b/src/igl/Assert.h index 3fca5b456b..0e5c4b6430 100644 --- a/src/igl/Assert.h +++ b/src/igl/Assert.h @@ -56,6 +56,8 @@ #include +#define IGL_ERROR_CATEGORY "IGL" + #if IGL_DEBUG || defined(IGL_FORCE_ENABLE_LOGS) #define IGL_VERIFY_ENABLED 1 #else @@ -76,6 +78,7 @@ void setDebugBreakEnabled(bool enabled); template [[nodiscard]] static inline const T& _IGLVerify(const T& cond, + [[maybe_unused]] const char* category, [[maybe_unused]] const char* reason, [[maybe_unused]] const char* func, [[maybe_unused]] const char* file, @@ -84,7 +87,7 @@ template ...) { #if IGL_VERIFY_ENABLED if (!cond) { - IGLLog(IGLLogError, "[IGL] %s in '%s' (%s:%d): ", reason, func, file, line); + IGLLog(IGLLogError, "[%s] %s in '%s' (%s:%d): ", category, reason, func, file, line); va_list ap; va_start(ap, format); IGLLogV(IGLLogError, format, ap); @@ -99,19 +102,43 @@ template #if IGL_VERIFY_ENABLED -#define _IGL_DEBUG_ABORT(cond, format, ...) \ - (void)::igl::_IGLVerify( \ - cond, "Abort requested", IGL_FUNCTION, __FILE__, __LINE__, (format), ##__VA_ARGS__) -#define _IGL_DEBUG_ASSERT(cond, format, ...) \ - (void)::igl::_IGLVerify( \ - cond, "Assert failed", IGL_FUNCTION, __FILE__, __LINE__, (format), ##__VA_ARGS__) +#define _IGL_DEBUG_ABORT(cond, format, ...) \ + (void)::igl::_IGLVerify(cond, \ + IGL_ERROR_CATEGORY, \ + "Abort requested", \ + IGL_FUNCTION, \ + __FILE__, \ + __LINE__, \ + (format), \ + ##__VA_ARGS__) +#define _IGL_DEBUG_ASSERT(cond, format, ...) \ + (void)::igl::_IGLVerify(cond, \ + IGL_ERROR_CATEGORY, \ + "Assert failed", \ + IGL_FUNCTION, \ + __FILE__, \ + __LINE__, \ + (format), \ + ##__VA_ARGS__) #define _IGL_DEBUG_VERIFY(cond, format, ...) \ - ::igl::_IGLVerify( \ - (cond), "Verify failed", IGL_FUNCTION, __FILE__, __LINE__, (format), ##__VA_ARGS__) + ::igl::_IGLVerify((cond), \ + IGL_ERROR_CATEGORY, \ + "Verify failed", \ + IGL_FUNCTION, \ + __FILE__, \ + __LINE__, \ + (format), \ + ##__VA_ARGS__) #define _IGL_DEBUG_VERIFY_NOT(cond, format, ...) \ - (!::igl::_IGLVerify( \ - 0 == !!(cond), "Verify failed", IGL_FUNCTION, __FILE__, __LINE__, (format), ##__VA_ARGS__)) + (!::igl::_IGLVerify(0 == !!(cond), \ + IGL_ERROR_CATEGORY, \ + "Verify failed", \ + IGL_FUNCTION, \ + __FILE__, \ + __LINE__, \ + (format), \ + ##__VA_ARGS__)) #else @@ -156,25 +183,26 @@ template ///-------------------------------------- /// MARK: - Custom -#define IGL_ERROR_CATEGORY "IGL" - -using IGLSoftErrorFunc = void (*)(const char* file, +using IGLSoftErrorFunc = void (*)(const char* category, + const char* reason, + const char* file, const char* func, int line, - const char* category, const char* format, ...); IGL_API void IGLSetSoftErrorHandler(IGLSoftErrorFunc handler); IGL_API IGLSoftErrorFunc IGLGetSoftErrorHandler(void); -IGL_API void IGLSoftError(const char* file, +IGL_API void IGLSoftError(const char* category, + const char* reason, + const char* file, const char* func, int line, - const char* category, const char* format, ...); namespace igl { template [[nodiscard]] static inline const T& _IGLSoftError(const T& cond, + [[maybe_unused]] const char* category, [[maybe_unused]] const char* reason, [[maybe_unused]] const char* func, [[maybe_unused]] const char* file, @@ -182,14 +210,14 @@ template [[maybe_unused]] const char* format, [[maybe_unused]] const Args&... args) { #if IGL_VERIFY_ENABLED - const auto& verifiedCond = _IGLVerify(cond, reason, func, file, line, format, args...); + const auto& verifiedCond = _IGLVerify(cond, category, reason, func, file, line, format, args...); #else const auto& verifiedCond = cond; #endif // IGL_VERIFY_ENABLED #if IGL_SOFT_ERROR_ENABLED if (!verifiedCond) { - IGLGetSoftErrorHandler()(file, func, line, IGL_ERROR_CATEGORY, format, args...); + IGLGetSoftErrorHandler()(category, reason, file, func, line, format, args...); } #endif // IGL_SOFT_ERROR_ENABLED @@ -199,18 +227,37 @@ template #if IGL_SOFT_ERROR_ENABLED -#define _IGL_SOFT_ERROR(cond, format, ...) \ - (void)::igl::_IGLSoftError( \ - cond, "Soft error", IGL_FUNCTION, __FILE__, __LINE__, (format), ##__VA_ARGS__) -#define _IGL_SOFT_ASSERT(cond, format, ...) \ - (void)::igl::_IGLSoftError( \ - cond, "Soft assert failed", IGL_FUNCTION, __FILE__, __LINE__, (format), ##__VA_ARGS__) - -#define _IGL_SOFT_VERIFY(cond, format, ...) \ - ::igl::_IGLSoftError( \ - (cond), "Soft verify failed", IGL_FUNCTION, __FILE__, __LINE__, (format), ##__VA_ARGS__) +#define _IGL_SOFT_ERROR(cond, format, ...) \ + (void)::igl::_IGLSoftError(cond, \ + IGL_ERROR_CATEGORY, \ + "Soft error", \ + IGL_FUNCTION, \ + __FILE__, \ + __LINE__, \ + (format), \ + ##__VA_ARGS__) +#define _IGL_SOFT_ASSERT(cond, format, ...) \ + (void)::igl::_IGLSoftError(cond, \ + IGL_ERROR_CATEGORY, \ + "Soft assert failed", \ + IGL_FUNCTION, \ + __FILE__, \ + __LINE__, \ + (format), \ + ##__VA_ARGS__) + +#define _IGL_SOFT_VERIFY(cond, format, ...) \ + ::igl::_IGLSoftError((cond), \ + IGL_ERROR_CATEGORY, \ + "Soft verify failed", \ + IGL_FUNCTION, \ + __FILE__, \ + __LINE__, \ + (format), \ + ##__VA_ARGS__) #define _IGL_SOFT_VERIFY_NOT(cond, format, ...) \ (!::igl::_IGLSoftError(0 == !!(cond), \ + IGL_ERROR_CATEGORY, \ "Soft verify failed", \ IGL_FUNCTION, \ __FILE__, \ diff --git a/src/igl/tests/util/TestErrorGuard.cpp b/src/igl/tests/util/TestErrorGuard.cpp index 685c8dfdba..94b0c3588a 100644 --- a/src/igl/tests/util/TestErrorGuard.cpp +++ b/src/igl/tests/util/TestErrorGuard.cpp @@ -26,10 +26,11 @@ igl::tests::util::TestErrorGuard::~TestErrorGuard() { #endif } -void igl::tests::util::TestErrorGuard::ReportErrorHandler(const char* file, +void igl::tests::util::TestErrorGuard::ReportErrorHandler(const char* category, + const char* /*reason*/, + const char* file, const char* /*func*/, int line, - const char* category, const char* format, ...) { #if IGL_SOFT_ERROR_ENABLED diff --git a/src/igl/tests/util/TestErrorGuard.h b/src/igl/tests/util/TestErrorGuard.h index f848f80567..019e8f90f1 100644 --- a/src/igl/tests/util/TestErrorGuard.h +++ b/src/igl/tests/util/TestErrorGuard.h @@ -17,10 +17,11 @@ class TestErrorGuard final { virtual ~TestErrorGuard(); - static void ReportErrorHandler(const char* file, + static void ReportErrorHandler(const char* category, + const char* reason, + const char* file, const char* func, int line, - const char* category, const char* format, ...); From 66afde998a5d3cc308ef99541dd2344ea4d39b60 Mon Sep 17 00:00:00 2001 From: Eric Griffith Date: Mon, 2 Dec 2024 15:50:24 -0800 Subject: [PATCH 8/9] IGL: Add unit tests for asserts and soft errors Reviewed By: ChristianK275 Differential Revision: D66545833 fbshipit-source-id: 3e8460ccc92b88f8252620044d87eb5f7b7fba57 --- src/igl/Assert.cpp | 41 +++--- src/igl/Assert.h | 116 +++++++++------ src/igl/tests/Assert.cpp | 195 ++++++++++++++++++++++++++ src/igl/tests/util/TestErrorGuard.cpp | 6 +- src/igl/tests/util/TestErrorGuard.h | 4 +- 5 files changed, 291 insertions(+), 71 deletions(-) create mode 100644 src/igl/tests/Assert.cpp diff --git a/src/igl/Assert.cpp b/src/igl/Assert.cpp index 1bfcddf5da..a9e36b06cd 100644 --- a/src/igl/Assert.cpp +++ b/src/igl/Assert.cpp @@ -10,6 +10,21 @@ // ---------------------------------------------------------------------------- +namespace { +IGLErrorHandlerFunc& GetDebugAbortListener() { + static IGLErrorHandlerFunc sListener = nullptr; + return sListener; +} +} // namespace + +IGL_API void IGLSetDebugAbortListener(IGLErrorHandlerFunc listener) { + GetDebugAbortListener() = listener; +} + +IGL_API IGLErrorHandlerFunc IGLGetDebugAbortListener(void) { + return GetDebugAbortListener(); +} + namespace igl { // Toggle debug break on/off at runtime @@ -58,30 +73,16 @@ void _IGLDebugBreak() { // ---------------------------------------------------------------------------- namespace { -// Default handler is no-op. -// If there's an error, IGL_DEBUG_VERIFY will trap in dev builds -void IGLReportErrorDefault(const char* /* category */, - const char* /* reason */, - const char* /* file */, - const char* /* func */, - int /* line */, - const char* /* format */, - ...) {} - -IGLSoftErrorFunc& GetErrorHandler() { - static IGLSoftErrorFunc sHandler = IGLReportErrorDefault; +IGLErrorHandlerFunc& GetSoftErrorHandler() { + static IGLErrorHandlerFunc sHandler = nullptr; return sHandler; } - } // namespace -IGL_API void IGLSetSoftErrorHandler(IGLSoftErrorFunc handler) { - if (!handler) { - handler = IGLReportErrorDefault; // prevent null handler - } - GetErrorHandler() = handler; +IGL_API void IGLSetSoftErrorHandler(IGLErrorHandlerFunc handler) { + GetSoftErrorHandler() = handler; } -IGL_API IGLSoftErrorFunc IGLGetSoftErrorHandler(void) { - return GetErrorHandler(); +IGL_API IGLErrorHandlerFunc IGLGetSoftErrorHandler(void) { + return GetSoftErrorHandler(); } diff --git a/src/igl/Assert.h b/src/igl/Assert.h index 0e5c4b6430..a5ab6fbcfb 100644 --- a/src/igl/Assert.h +++ b/src/igl/Assert.h @@ -70,32 +70,61 @@ #define IGL_DEBUG_BREAK_ENABLED 0 #endif +using IGLErrorHandlerFunc = void (*)(const char* category, + const char* reason, + const char* file, + const char* func, + int line, + const char* format, + va_list ap); + IGL_API void _IGLDebugBreak(); +IGL_API void IGLSetDebugAbortListener(IGLErrorHandlerFunc listener); +IGL_API IGLErrorHandlerFunc IGLGetDebugAbortListener(void); + namespace igl { bool isDebugBreakEnabled(); void setDebugBreakEnabled(bool enabled); -template -[[nodiscard]] static inline const T& _IGLVerify(const T& cond, - [[maybe_unused]] const char* category, - [[maybe_unused]] const char* reason, - [[maybe_unused]] const char* func, - [[maybe_unused]] const char* file, - [[maybe_unused]] int line, - [[maybe_unused]] const char* format, - ...) { +inline void _IGLVerifyV(bool cond, + [[maybe_unused]] const char* category, + [[maybe_unused]] const char* reason, + [[maybe_unused]] const char* func, + [[maybe_unused]] const char* file, + [[maybe_unused]] int line, + [[maybe_unused]] const char* format, + [[maybe_unused]] va_list ap) { #if IGL_VERIFY_ENABLED if (!cond) { + va_list apCopy; + va_copy(apCopy, ap); + auto listener = IGLGetDebugAbortListener(); + if (listener) { + listener(category, reason, file, func, line, format, apCopy); + } + va_end(apCopy); + IGLLog(IGLLogError, "[%s] %s in '%s' (%s:%d): ", category, reason, func, file, line); - va_list ap; - va_start(ap, format); IGLLogV(IGLLogError, format, ap); - va_end(ap); IGLLog(IGLLogError, IGL_NEWLINE); _IGLDebugBreak(); } #endif // IGL_VERIFY_ENABLED +} + +[[nodiscard]] inline bool _IGLVerify(bool cond, + [[maybe_unused]] const char* category, + [[maybe_unused]] const char* reason, + [[maybe_unused]] const char* func, + [[maybe_unused]] const char* file, + [[maybe_unused]] int line, + [[maybe_unused]] const char* format, + ...) { + va_list ap; + va_start(ap, format); + _IGLVerifyV(cond, category, reason, func, file, line, format, ap); + va_end(ap); return cond; } } // namespace igl @@ -103,7 +132,7 @@ template #if IGL_VERIFY_ENABLED #define _IGL_DEBUG_ABORT(cond, format, ...) \ - (void)::igl::_IGLVerify(cond, \ + (void)::igl::_IGLVerify(!!(cond), \ IGL_ERROR_CATEGORY, \ "Abort requested", \ IGL_FUNCTION, \ @@ -112,7 +141,7 @@ template (format), \ ##__VA_ARGS__) #define _IGL_DEBUG_ASSERT(cond, format, ...) \ - (void)::igl::_IGLVerify(cond, \ + (void)::igl::_IGLVerify(!!(cond), \ IGL_ERROR_CATEGORY, \ "Assert failed", \ IGL_FUNCTION, \ @@ -122,7 +151,7 @@ template ##__VA_ARGS__) #define _IGL_DEBUG_VERIFY(cond, format, ...) \ - ::igl::_IGLVerify((cond), \ + ::igl::_IGLVerify(!!(cond), \ IGL_ERROR_CATEGORY, \ "Verify failed", \ IGL_FUNCTION, \ @@ -131,7 +160,7 @@ template (format), \ ##__VA_ARGS__) #define _IGL_DEBUG_VERIFY_NOT(cond, format, ...) \ - (!::igl::_IGLVerify(0 == !!(cond), \ + (!::igl::_IGLVerify(!(cond), \ IGL_ERROR_CATEGORY, \ "Verify failed", \ IGL_FUNCTION, \ @@ -183,15 +212,8 @@ template ///-------------------------------------- /// MARK: - Custom -using IGLSoftErrorFunc = void (*)(const char* category, - const char* reason, - const char* file, - const char* func, - int line, - const char* format, - ...); -IGL_API void IGLSetSoftErrorHandler(IGLSoftErrorFunc handler); -IGL_API IGLSoftErrorFunc IGLGetSoftErrorHandler(void); +IGL_API void IGLSetSoftErrorHandler(IGLErrorHandlerFunc handler); +IGL_API IGLErrorHandlerFunc IGLGetSoftErrorHandler(void); IGL_API void IGLSoftError(const char* category, const char* reason, const char* file, @@ -200,35 +222,41 @@ IGL_API void IGLSoftError(const char* category, const char* format, ...); namespace igl { -template -[[nodiscard]] static inline const T& _IGLSoftError(const T& cond, - [[maybe_unused]] const char* category, - [[maybe_unused]] const char* reason, - [[maybe_unused]] const char* func, - [[maybe_unused]] const char* file, - [[maybe_unused]] int line, - [[maybe_unused]] const char* format, - [[maybe_unused]] const Args&... args) { +[[nodiscard]] inline bool _IGLSoftError(bool cond, + [[maybe_unused]] const char* category, + [[maybe_unused]] const char* reason, + [[maybe_unused]] const char* func, + [[maybe_unused]] const char* file, + [[maybe_unused]] int line, + [[maybe_unused]] const char* format, + ...) { + va_list ap, apCopy; + va_start(ap, format); + va_copy(apCopy, ap); #if IGL_VERIFY_ENABLED - const auto& verifiedCond = _IGLVerify(cond, category, reason, func, file, line, format, args...); -#else - const auto& verifiedCond = cond; + _IGLVerifyV(cond, category, reason, func, file, line, format, ap); #endif // IGL_VERIFY_ENABLED #if IGL_SOFT_ERROR_ENABLED - if (!verifiedCond) { - IGLGetSoftErrorHandler()(category, reason, file, func, line, format, args...); + if (!cond) { + auto handler = IGLGetSoftErrorHandler(); + if (handler) { + handler(category, reason, file, func, line, format, apCopy); + } } #endif // IGL_SOFT_ERROR_ENABLED - return verifiedCond; + va_end(apCopy); + va_end(ap); + + return cond; } } // namespace igl #if IGL_SOFT_ERROR_ENABLED #define _IGL_SOFT_ERROR(cond, format, ...) \ - (void)::igl::_IGLSoftError(cond, \ + (void)::igl::_IGLSoftError(!!(cond), \ IGL_ERROR_CATEGORY, \ "Soft error", \ IGL_FUNCTION, \ @@ -237,7 +265,7 @@ template (format), \ ##__VA_ARGS__) #define _IGL_SOFT_ASSERT(cond, format, ...) \ - (void)::igl::_IGLSoftError(cond, \ + (void)::igl::_IGLSoftError(!!(cond), \ IGL_ERROR_CATEGORY, \ "Soft assert failed", \ IGL_FUNCTION, \ @@ -247,7 +275,7 @@ template ##__VA_ARGS__) #define _IGL_SOFT_VERIFY(cond, format, ...) \ - ::igl::_IGLSoftError((cond), \ + ::igl::_IGLSoftError(!!(cond), \ IGL_ERROR_CATEGORY, \ "Soft verify failed", \ IGL_FUNCTION, \ @@ -256,7 +284,7 @@ template (format), \ ##__VA_ARGS__) #define _IGL_SOFT_VERIFY_NOT(cond, format, ...) \ - (!::igl::_IGLSoftError(0 == !!(cond), \ + (!::igl::_IGLSoftError(!(cond), \ IGL_ERROR_CATEGORY, \ "Soft verify failed", \ IGL_FUNCTION, \ diff --git a/src/igl/tests/Assert.cpp b/src/igl/tests/Assert.cpp new file mode 100644 index 0000000000..2b6bb3b0ec --- /dev/null +++ b/src/igl/tests/Assert.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +// Only include Assert.h and ensure it is configured to enable both soft errors and debug aborts +#define IGL_DEBUG 1 +#define IGL_SOFT_ERROR_ENABLED 1 +#define IGL_COMMON_SKIP_CHECK 1 +#include + +namespace igl::tests { +namespace { +bool sAbort = false; +bool sSoftError = false; +} // namespace + +class AssertTest : public ::testing::Test { + public: + void SetUp() override { + igl::setDebugBreakEnabled(false); + IGLSetDebugAbortListener([](const char* /*category*/, + const char* /*reason*/, + const char* /*file*/, + const char* /*func*/, + int /*line*/, + const char* /*format*/, + va_list /*ap*/) { sAbort = true; }); + IGLSetSoftErrorHandler([](const char* /*category*/, + const char* /*reason*/, + const char* /*file*/, + const char* /*func*/, + int /*line*/, + const char* /*format*/, + va_list /*ap*/) { sSoftError = true; }); + } + + void TearDown() override { + IGLSetDebugAbortListener(nullptr); + IGLSetSoftErrorHandler(nullptr); + } +}; + +TEST_F(AssertTest, DebugAbort) { + sAbort = false; + EXPECT_FALSE(sAbort); + IGL_DEBUG_ABORT("Aborting"); + EXPECT_TRUE(sAbort); + + sAbort = false; + EXPECT_FALSE(sAbort); + IGL_DEBUG_ABORT("Aborting with arg %d", 1); + EXPECT_TRUE(sAbort); + + sAbort = false; + EXPECT_FALSE(sAbort); + IGL_DEBUG_ASSERT(false); + EXPECT_TRUE(sAbort); + + sAbort = false; + EXPECT_FALSE(sAbort); + IGL_DEBUG_ASSERT(false, "Aborting"); + EXPECT_TRUE(sAbort); + + sAbort = false; + EXPECT_FALSE(sAbort); + IGL_DEBUG_ASSERT(false, "Aborting with arg %d", 1); + EXPECT_TRUE(sAbort); + + sAbort = false; + EXPECT_FALSE(sAbort); + std::ignore = IGL_DEBUG_VERIFY(false); + EXPECT_TRUE(sAbort); + + sAbort = false; + EXPECT_FALSE(sAbort); + std::ignore = IGL_DEBUG_VERIFY(false, "Aborting"); + EXPECT_TRUE(sAbort); + + sAbort = false; + EXPECT_FALSE(sAbort); + std::ignore = IGL_DEBUG_VERIFY(false, "Aborting with arg %d", 1); + EXPECT_TRUE(sAbort); + + sAbort = false; + EXPECT_FALSE(sAbort); + std::ignore = IGL_DEBUG_VERIFY_NOT(true); + EXPECT_TRUE(sAbort); + + sAbort = false; + EXPECT_FALSE(sAbort); + std::ignore = IGL_DEBUG_VERIFY_NOT(true, "Aborting"); + EXPECT_TRUE(sAbort); + + sAbort = false; + EXPECT_FALSE(sAbort); + std::ignore = IGL_DEBUG_VERIFY_NOT(true, "Aborting with arg %d", 1); + EXPECT_TRUE(sAbort); +} + +TEST_F(AssertTest, SoftError) { + sAbort = false; + sSoftError = false; + EXPECT_FALSE(sAbort); + EXPECT_FALSE(sSoftError); + IGL_SOFT_ERROR("Aborting"); + EXPECT_TRUE(sAbort); + EXPECT_TRUE(sSoftError); + + sAbort = false; + sSoftError = false; + EXPECT_FALSE(sAbort); + EXPECT_FALSE(sSoftError); + IGL_SOFT_ERROR("Aborting with arg %d", 1); + EXPECT_TRUE(sAbort); + EXPECT_TRUE(sSoftError); + + sAbort = false; + sSoftError = false; + EXPECT_FALSE(sAbort); + EXPECT_FALSE(sSoftError); + IGL_SOFT_ASSERT(false); + EXPECT_TRUE(sAbort); + EXPECT_TRUE(sSoftError); + + sAbort = false; + sSoftError = false; + EXPECT_FALSE(sAbort); + EXPECT_FALSE(sSoftError); + IGL_SOFT_ASSERT(false, "Aborting"); + EXPECT_TRUE(sAbort); + EXPECT_TRUE(sSoftError); + + sAbort = false; + sSoftError = false; + EXPECT_FALSE(sAbort); + EXPECT_FALSE(sSoftError); + IGL_SOFT_ASSERT(false, "Aborting with arg %d", 1); + EXPECT_TRUE(sAbort); + EXPECT_TRUE(sSoftError); + + sAbort = false; + sSoftError = false; + EXPECT_FALSE(sAbort); + EXPECT_FALSE(sSoftError); + std::ignore = IGL_SOFT_VERIFY(false); + EXPECT_TRUE(sAbort); + EXPECT_TRUE(sSoftError); + + sAbort = false; + sSoftError = false; + EXPECT_FALSE(sAbort); + EXPECT_FALSE(sSoftError); + std::ignore = IGL_SOFT_VERIFY(false, "Aborting"); + EXPECT_TRUE(sAbort); + EXPECT_TRUE(sSoftError); + + sAbort = false; + sSoftError = false; + EXPECT_FALSE(sAbort); + EXPECT_FALSE(sSoftError); + std::ignore = IGL_SOFT_VERIFY(false, "Aborting with arg %d", 1); + EXPECT_TRUE(sAbort); + EXPECT_TRUE(sSoftError); + + sAbort = false; + sSoftError = false; + EXPECT_FALSE(sAbort); + EXPECT_FALSE(sSoftError); + std::ignore = IGL_SOFT_VERIFY_NOT(true); + EXPECT_TRUE(sAbort); + EXPECT_TRUE(sSoftError); + + sAbort = false; + sSoftError = false; + EXPECT_FALSE(sAbort); + EXPECT_FALSE(sSoftError); + std::ignore = IGL_SOFT_VERIFY_NOT(true, "Aborting"); + EXPECT_TRUE(sAbort); + EXPECT_TRUE(sSoftError); + + sAbort = false; + sSoftError = false; + EXPECT_FALSE(sAbort); + EXPECT_FALSE(sSoftError); + std::ignore = IGL_SOFT_VERIFY_NOT(true, "Aborting with arg %d", 1); + EXPECT_TRUE(sAbort); + EXPECT_TRUE(sSoftError); +} + +} // namespace igl::tests diff --git a/src/igl/tests/util/TestErrorGuard.cpp b/src/igl/tests/util/TestErrorGuard.cpp index 94b0c3588a..eb60b7fb7c 100644 --- a/src/igl/tests/util/TestErrorGuard.cpp +++ b/src/igl/tests/util/TestErrorGuard.cpp @@ -32,11 +32,8 @@ void igl::tests::util::TestErrorGuard::ReportErrorHandler(const char* category, const char* /*func*/, int line, const char* format, - ...) { + va_list ap) { #if IGL_SOFT_ERROR_ENABLED - va_list ap; - va_start(ap, format); - va_list apCopy; va_copy(apCopy, ap); const auto len = std::vsnprintf(nullptr, 0, format, apCopy); @@ -46,7 +43,6 @@ void igl::tests::util::TestErrorGuard::ReportErrorHandler(const char* category, fmtString.resize(len + 1); std::vsnprintf(&fmtString.front(), len + 1, format, ap); fmtString.resize(len); - va_end(ap); ADD_FAILURE() << "IGL error encountered in " << file << ":" << line << " category=" << category << " " << fmtString; diff --git a/src/igl/tests/util/TestErrorGuard.h b/src/igl/tests/util/TestErrorGuard.h index 019e8f90f1..edfc2c0cd8 100644 --- a/src/igl/tests/util/TestErrorGuard.h +++ b/src/igl/tests/util/TestErrorGuard.h @@ -23,11 +23,11 @@ class TestErrorGuard final { const char* func, int line, const char* format, - ...); + va_list ap); private: #if IGL_SOFT_ERROR_ENABLED - IGLSoftErrorFunc savedErrorHandler_; + IGLErrorHandlerFunc savedErrorHandler_; #endif }; } // namespace igl::tests::util From b18d5a490e5956cfd74451a0518eb30de418294e Mon Sep 17 00:00:00 2001 From: Eric Griffith Date: Mon, 2 Dec 2024 15:50:24 -0800 Subject: [PATCH 9/9] IGL: Only evaluate verify args if condition fails Reviewed By: ChristianK275 Differential Revision: D66550662 fbshipit-source-id: c645698d9dd540a23725386c0d7e63d79f7dc1d1 --- src/igl/Assert.h | 197 ++++++++++++++++++----------------------------- 1 file changed, 75 insertions(+), 122 deletions(-) diff --git a/src/igl/Assert.h b/src/igl/Assert.h index a5ab6fbcfb..ad11f68598 100644 --- a/src/igl/Assert.h +++ b/src/igl/Assert.h @@ -87,98 +87,77 @@ namespace igl { bool isDebugBreakEnabled(); void setDebugBreakEnabled(bool enabled); -inline void _IGLVerifyV(bool cond, - [[maybe_unused]] const char* category, - [[maybe_unused]] const char* reason, - [[maybe_unused]] const char* func, - [[maybe_unused]] const char* file, - [[maybe_unused]] int line, - [[maybe_unused]] const char* format, - [[maybe_unused]] va_list ap) { +[[nodiscard]] inline bool _IGLAlwaysTrue() { + return true; +} + +inline void _IGLDebugAbortV([[maybe_unused]] const char* category, + [[maybe_unused]] const char* reason, + [[maybe_unused]] const char* func, + [[maybe_unused]] const char* file, + [[maybe_unused]] int line, + [[maybe_unused]] const char* format, + [[maybe_unused]] va_list ap) { #if IGL_VERIFY_ENABLED - if (!cond) { - va_list apCopy; - va_copy(apCopy, ap); - auto listener = IGLGetDebugAbortListener(); - if (listener) { - listener(category, reason, file, func, line, format, apCopy); - } - va_end(apCopy); - - IGLLog(IGLLogError, "[%s] %s in '%s' (%s:%d): ", category, reason, func, file, line); - IGLLogV(IGLLogError, format, ap); - IGLLog(IGLLogError, IGL_NEWLINE); - _IGLDebugBreak(); + va_list apCopy; + va_copy(apCopy, ap); + auto listener = IGLGetDebugAbortListener(); + if (listener) { + listener(category, reason, file, func, line, format, apCopy); } + va_end(apCopy); + + IGLLog(IGLLogError, "[%s] %s in '%s' (%s:%d): ", category, reason, func, file, line); + IGLLogV(IGLLogError, format, ap); + IGLLog(IGLLogError, IGL_NEWLINE); + _IGLDebugBreak(); #endif // IGL_VERIFY_ENABLED } -[[nodiscard]] inline bool _IGLVerify(bool cond, - [[maybe_unused]] const char* category, - [[maybe_unused]] const char* reason, - [[maybe_unused]] const char* func, - [[maybe_unused]] const char* file, - [[maybe_unused]] int line, - [[maybe_unused]] const char* format, - ...) { +[[nodiscard]] inline bool _IGLDebugAbort(const char* category, + const char* reason, + const char* func, + const char* file, + int line, + const char* format, + ...) { va_list ap; va_start(ap, format); - _IGLVerifyV(cond, category, reason, func, file, line, format, ap); + _IGLDebugAbortV(category, reason, func, file, line, format, ap); va_end(ap); - return cond; + + return false; } } // namespace igl #if IGL_VERIFY_ENABLED -#define _IGL_DEBUG_ABORT(cond, format, ...) \ - (void)::igl::_IGLVerify(!!(cond), \ - IGL_ERROR_CATEGORY, \ - "Abort requested", \ - IGL_FUNCTION, \ - __FILE__, \ - __LINE__, \ - (format), \ - ##__VA_ARGS__) -#define _IGL_DEBUG_ASSERT(cond, format, ...) \ - (void)::igl::_IGLVerify(!!(cond), \ - IGL_ERROR_CATEGORY, \ - "Assert failed", \ - IGL_FUNCTION, \ - __FILE__, \ - __LINE__, \ - (format), \ - ##__VA_ARGS__) +#define _IGL_DEBUG_ABORT_IMPL(cond, reason, format, ...) \ + (cond \ + ? ::igl::_IGLAlwaysTrue() \ + : ::igl::_IGLDebugAbort( \ + IGL_ERROR_CATEGORY, reason, IGL_FUNCTION, __FILE__, __LINE__, format, ##__VA_ARGS__)) + +#define _IGL_DEBUG_ABORT(format, ...) \ + (void)_IGL_DEBUG_ABORT_IMPL(false, "Abort requested", (format), ##__VA_ARGS__) +#define _IGL_DEBUG_ASSERT(cond, format, ...) \ + (void)_IGL_DEBUG_ABORT_IMPL(!!(cond), "Assert failed", (format), ##__VA_ARGS__) #define _IGL_DEBUG_VERIFY(cond, format, ...) \ - ::igl::_IGLVerify(!!(cond), \ - IGL_ERROR_CATEGORY, \ - "Verify failed", \ - IGL_FUNCTION, \ - __FILE__, \ - __LINE__, \ - (format), \ - ##__VA_ARGS__) + _IGL_DEBUG_ABORT_IMPL(!!(cond), "Verify failed", (format), ##__VA_ARGS__) #define _IGL_DEBUG_VERIFY_NOT(cond, format, ...) \ - (!::igl::_IGLVerify(!(cond), \ - IGL_ERROR_CATEGORY, \ - "Verify failed", \ - IGL_FUNCTION, \ - __FILE__, \ - __LINE__, \ - (format), \ - ##__VA_ARGS__)) + !_IGL_DEBUG_ABORT_IMPL(!(cond), "Verify failed", (format), ##__VA_ARGS__) #else -#define _IGL_DEBUG_ABORT(cond, format, ...) static_cast(0) +#define _IGL_DEBUG_ABORT(format, ...) static_cast(0) #define _IGL_DEBUG_ASSERT(cond, format, ...) static_cast(0) #define _IGL_DEBUG_VERIFY(cond, format, ...) (cond) #define _IGL_DEBUG_VERIFY_NOT(cond, format, ...) (cond) #endif // IGL_VERIFY_ENABLED -#define IGL_DEBUG_ABORT(format, ...) _IGL_DEBUG_ABORT(false, (format), ##__VA_ARGS__) +#define IGL_DEBUG_ABORT(format, ...) _IGL_DEBUG_ABORT((format), ##__VA_ARGS__) #define _IGL_DEBUG_ASSERT_0(cond) _IGL_DEBUG_ASSERT(cond, #cond) #define _IGL_DEBUG_ASSERT_1(cond, format, ...) _IGL_DEBUG_ASSERT(cond, (format), ##__VA_ARGS__) @@ -222,87 +201,61 @@ IGL_API void IGLSoftError(const char* category, const char* format, ...); namespace igl { -[[nodiscard]] inline bool _IGLSoftError(bool cond, - [[maybe_unused]] const char* category, - [[maybe_unused]] const char* reason, - [[maybe_unused]] const char* func, - [[maybe_unused]] const char* file, - [[maybe_unused]] int line, - [[maybe_unused]] const char* format, +[[nodiscard]] inline bool _IGLSoftError(const char* category, + const char* reason, + const char* func, + const char* file, + int line, + const char* format, ...) { va_list ap, apCopy; va_start(ap, format); va_copy(apCopy, ap); -#if IGL_VERIFY_ENABLED - _IGLVerifyV(cond, category, reason, func, file, line, format, ap); -#endif // IGL_VERIFY_ENABLED + + _IGLDebugAbortV(category, reason, func, file, line, format, apCopy); + va_end(apCopy); #if IGL_SOFT_ERROR_ENABLED - if (!cond) { - auto handler = IGLGetSoftErrorHandler(); - if (handler) { - handler(category, reason, file, func, line, format, apCopy); - } + auto handler = IGLGetSoftErrorHandler(); + if (handler) { + handler(category, reason, file, func, line, format, ap); } #endif // IGL_SOFT_ERROR_ENABLED - va_end(apCopy); va_end(ap); - return cond; + return false; // Always return false } } // namespace igl #if IGL_SOFT_ERROR_ENABLED -#define _IGL_SOFT_ERROR(cond, format, ...) \ - (void)::igl::_IGLSoftError(!!(cond), \ - IGL_ERROR_CATEGORY, \ - "Soft error", \ - IGL_FUNCTION, \ - __FILE__, \ - __LINE__, \ - (format), \ - ##__VA_ARGS__) -#define _IGL_SOFT_ASSERT(cond, format, ...) \ - (void)::igl::_IGLSoftError(!!(cond), \ - IGL_ERROR_CATEGORY, \ - "Soft assert failed", \ - IGL_FUNCTION, \ - __FILE__, \ - __LINE__, \ - (format), \ - ##__VA_ARGS__) - -#define _IGL_SOFT_VERIFY(cond, format, ...) \ - ::igl::_IGLSoftError(!!(cond), \ - IGL_ERROR_CATEGORY, \ - "Soft verify failed", \ - IGL_FUNCTION, \ - __FILE__, \ - __LINE__, \ - (format), \ - ##__VA_ARGS__) +#define _IGL_SOFT_ERROR_IMPL(cond, reason, format, ...) \ + (cond \ + ? ::igl::_IGLAlwaysTrue() \ + : ::igl::_IGLSoftError( \ + IGL_ERROR_CATEGORY, reason, IGL_FUNCTION, __FILE__, __LINE__, format, ##__VA_ARGS__)) + +#define _IGL_SOFT_ERROR(format, ...) \ + (void)_IGL_SOFT_ERROR_IMPL(false, "Soft error", (format), ##__VA_ARGS__) +#define _IGL_SOFT_ASSERT(cond, format, ...) \ + (void)_IGL_SOFT_ERROR_IMPL(!!(cond), "Soft assert failed", (format), ##__VA_ARGS__) + +#define _IGL_SOFT_VERIFY(cond, format, ...) \ + _IGL_SOFT_ERROR_IMPL(!!(cond), "Soft verify failed", (format), ##__VA_ARGS__) #define _IGL_SOFT_VERIFY_NOT(cond, format, ...) \ - (!::igl::_IGLSoftError(!(cond), \ - IGL_ERROR_CATEGORY, \ - "Soft verify failed", \ - IGL_FUNCTION, \ - __FILE__, \ - __LINE__, \ - (format), \ - ##__VA_ARGS__)) + !_IGL_SOFT_ERROR_IMPL(!(cond), "Soft verify failed", (format), ##__VA_ARGS__) #else -#define _IGL_SOFT_ERROR(cond, format, ...) static_cast(0) +#define _IGL_SOFT_ERROR(format, ...) static_cast(0) #define _IGL_SOFT_ASSERT(cond, format, ...) static_cast(0) #define _IGL_SOFT_VERIFY(cond, format, ...) (cond) #define _IGL_SOFT_VERIFY_NOT(cond, format, ...) (cond) #endif // IGL_SOFT_ERROR_ENABLED -#define IGL_SOFT_ERROR(format, ...) _IGL_SOFT_ERROR(false, (format), ##__VA_ARGS__) +#define IGL_SOFT_ERROR(format, ...) _IGL_SOFT_ERROR((format), ##__VA_ARGS__) #define _IGL_SOFT_ASSERT_0(cond) _IGL_SOFT_ASSERT(cond, #cond) #define _IGL_SOFT_ASSERT_1(cond, format, ...) _IGL_SOFT_ASSERT(cond, (format), ##__VA_ARGS__)