diff options
| author | Nicolas James <nj3ahxac@gmail.com> | 2026-03-12 18:20:36 +1100 |
|---|---|---|
| committer | Nicolas James <nj3ahxac@gmail.com> | 2026-03-12 18:20:36 +1100 |
| commit | 44d88e25df14b7e191a15bfbe002a875d7c67056 (patch) | |
| tree | 7ea556fc885fc937c5db5800bc2112f9e57b6280 | |
| parent | a19308a35e88cd53c0d5ac2f26c705f902804658 (diff) | |
Add graceful exception handling in hooks
| -rw-r--r-- | src/layer.cc | 38 |
1 files 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<std::string_view, PFN_vkVoidFunction>; +// 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 <auto Func> struct HookExceptionWrapper; +template <typename R, typename... Args, R (*Func)(Args...)> +struct HookExceptionWrapper<Func> { + 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<R>) { + 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<R, VkResult>) { + return VK_ERROR_UNKNOWN; + } + } + + std::terminate(); + } +}; + #define HOOK_ENTRY(vk_name_literal, fn_sym) \ - {vk_name_literal, reinterpret_cast<PFN_vkVoidFunction>(fn_sym)} + {vk_name_literal, reinterpret_cast<PFN_vkVoidFunction>( \ + &HookExceptionWrapper<fn_sym>::call)} + +using func_map_t = std::unordered_map<std::string_view, PFN_vkVoidFunction>; static const auto instance_functions = func_map_t{ HOOK_ENTRY("vkCreateDevice", low_latency::CreateDevice), |
