From 44d88e25df14b7e191a15bfbe002a875d7c67056 Mon Sep 17 00:00:00 2001 From: Nicolas James Date: Thu, 12 Mar 2026 18:20:36 +1100 Subject: Add graceful exception handling in hooks --- src/layer.cc | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/layer.cc b/src/layer.cc index 014ab37..d547888 100644 --- a/src/layer.cc +++ b/src/layer.cc @@ -619,9 +619,43 @@ AntiLagUpdateAMD(VkDevice device, const VkAntiLagDataAMD* pData) { } // namespace low_latency -using func_map_t = std::unordered_map; +// This is a bit of template hackery which generates a wrapper function for each +// of our hooks that keeps exceptions from getting sucked back into the caller. +// This is useful because it allows us to use exceptions and not violate the +// vulkan contract. If we can return something, VK_ERROR_UNKNOWN is used - +// otherwise we call terminate. +template struct HookExceptionWrapper; +template +struct HookExceptionWrapper { + static R call(Args... args) noexcept { + + // If the function is void, we don't need to think about anything and + // can just call it. + if constexpr (std::is_void_v) { + Func(args...); + return; + } + + // If the function isn't void, we need to wrap it in a try block. Any + // exceptions we get (which came from our layer) should handled here + // by returning VK_ERROR_UNKNOWN when we can. Otherwise just terminate. + try { + return Func(args...); + } catch (...) { + if constexpr (std::is_same_v) { + return VK_ERROR_UNKNOWN; + } + } + + std::terminate(); + } +}; + #define HOOK_ENTRY(vk_name_literal, fn_sym) \ - {vk_name_literal, reinterpret_cast(fn_sym)} + {vk_name_literal, reinterpret_cast( \ + &HookExceptionWrapper::call)} + +using func_map_t = std::unordered_map; static const auto instance_functions = func_map_t{ HOOK_ENTRY("vkCreateDevice", low_latency::CreateDevice), -- cgit v1.2.3