diff --git a/traits.hpp b/traits.hpp index 8665470..858b6dc 100644 --- a/traits.hpp +++ b/traits.hpp @@ -138,67 +138,69 @@ namespace cruft::vk { /// XXX: if such a function does not exist anywhere then we currently use /// tuple::ignore to simplify implementation elsewhere. we should probably /// investigate std::is_detected for these cases though. + /// + /// clang#18781: we make use of references types extensively here to + /// workaround a potential ODR bug in clang which results in undefined + /// references. + /// or potentially i'm being too clever for my own good, but it works fine + /// in gcc... template struct life_traits { }; //------------------------------------------------------------------------- template <> struct life_traits { - static constexpr auto create = vkCreateInstance; - static constexpr auto destroy = vkDestroyInstance; + static constexpr auto& create = vkCreateInstance; + static constexpr auto& destroy = vkDestroyInstance; }; template <> struct life_traits { - static constexpr auto create = vkCreateDevice; - static constexpr auto destroy = vkDestroyDevice; + static constexpr auto& create = vkCreateDevice; + static constexpr auto& destroy = vkDestroyDevice; }; template <> struct life_traits { - static constexpr auto create = vkCreateCommandPool; - static constexpr auto destroy = vkDestroyCommandPool; + static constexpr auto& create = vkCreateCommandPool; + static constexpr auto& destroy = vkDestroyCommandPool; }; template <> struct life_traits { - static constexpr auto create = vkCreateFence; - static constexpr auto destroy = vkDestroyFence; + static constexpr auto& create = vkCreateFence; + static constexpr auto& destroy = vkDestroyFence; }; template <> struct life_traits { - static constexpr auto create = vkCreateSemaphore; - static constexpr auto destroy = vkDestroySemaphore; + static constexpr auto& create = vkCreateSemaphore; + static constexpr auto& destroy = vkDestroySemaphore; }; template <> struct life_traits { - static constexpr auto create = vkCreateEvent; - static constexpr auto destroy = vkDestroyEvent; + static constexpr auto& create = vkCreateEvent; + static constexpr auto& destroy = vkDestroyEvent; }; template <> struct life_traits { - static constexpr auto create = vkCreateRenderPass; - static constexpr auto destroy = vkDestroyRenderPass; + static constexpr auto& create = vkCreateRenderPass; + static constexpr auto& destroy = vkDestroyRenderPass; }; template <> struct life_traits { - static constexpr auto create = vkCreateFramebuffer; - static constexpr auto destroy = vkDestroyFramebuffer; + static constexpr auto& create = vkCreateFramebuffer; + static constexpr auto& destroy = vkDestroyFramebuffer; }; template <> struct life_traits { - static constexpr auto create = vkCreateShaderModule; - static constexpr auto destroy = vkDestroyShaderModule; + static constexpr auto& create = vkCreateShaderModule; + static constexpr auto& destroy = vkDestroyShaderModule; }; template <> struct life_traits { - static constexpr auto destroy = vkDestroySurfaceKHR; + static constexpr auto& destroy = vkDestroySurfaceKHR; }; template <> struct life_traits { - // clang#18781: we work around an ODR bug in clang which causes - // undefined references by explicitly using a temporary here. ideally - // this causes minimal difference in the generated output. - using create_t = decltype(vkGetDeviceQueue); - static constexpr create_t& create = vkGetDeviceQueue; + static constexpr auto& create = vkGetDeviceQueue; static constexpr auto destroy = ::util::tuple::ignore< id_t>, @@ -225,22 +227,22 @@ namespace cruft::vk { //}; template <> struct life_traits { - static constexpr auto create = vkCreatePipelineCache; - static constexpr auto destroy = vkDestroyPipelineCache; + static constexpr auto& create = vkCreatePipelineCache; + static constexpr auto& destroy = vkDestroyPipelineCache; }; template <> struct life_traits { - static constexpr auto create = vkAllocateMemory; - static constexpr auto destroy = vkFreeMemory; + static constexpr auto& create = vkAllocateMemory; + static constexpr auto& destroy = vkFreeMemory; }; template <> struct life_traits { - static constexpr auto create = vkCreateBuffer; - static constexpr auto destroy = vkDestroyBuffer; + static constexpr auto& create = vkCreateBuffer; + static constexpr auto& destroy = vkDestroyBuffer; }; template <> struct life_traits { - static constexpr auto create = vkCreateBufferView; + static constexpr auto& create = vkCreateBufferView; };