diff --git a/src/backend/vulkan/vulkan_platform.h b/src/backend/vulkan/vulkan_platform.h index 3354a38ba5..5c1a19dd65 100644 --- a/src/backend/vulkan/vulkan_platform.h +++ b/src/backend/vulkan/vulkan_platform.h @@ -15,6 +15,61 @@ #ifndef BACKEND_VULKAN_VULKANPLATFORM_H_ #define BACKEND_VULKAN_VULKANPLATFORM_H_ -#include +#include +#include + +// vulkan.h defines non-dispatchable handles to opaque pointers on 64bit architectures and uint64_t +// on 32bit architectures. This causes a problem in 32bit where the handles cannot be used to +// distinguish between overloads of the same function. +// Change the definition of non-dispatchable handles to be opaque structures containing a uint64_t +// and overload the comparison operators between themselves and VK_NULL_HANDLE (which will be +// redefined to be nullptr). This keeps the type-safety of having the handles be different types +// (like vulkan.h on 64 bit) but makes sure the types are different on 32 bit architectures. + +// Simple handle types that supports "nullptr_t" as a 0 value. +template +class VkNonDispatchableHandle { + public: + // Default constructor and assigning of VK_NULL_HANDLE + VkNonDispatchableHandle() = default; + VkNonDispatchableHandle(std::nullptr_t) : mHandle(0) { + } + + // Use default copy constructor/assignment + VkNonDispatchableHandle(const VkNonDispatchableHandle& other) = default; + VkNonDispatchableHandle& operator=(const VkNonDispatchableHandle&) = default; + + // Comparisons between handles + bool operator==(VkNonDispatchableHandle other) { + return mHandle == other.mHandle; + } + bool operator!=(VkNonDispatchableHandle other) { + return mHandle != other.mHandle; + } + + // Comparisons between handles and VK_NULL_HANDLE + bool operator==(std::nullptr_t) { + return mHandle == 0; + } + bool operator!=(std::nullptr_t) { + return mHandle != 0; + } + + private: + uint64_t mHandle = 0; +}; + +# define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) \ + struct VkTag##object; \ + using object = VkNonDispatchableHandle; \ + static_assert(sizeof(object) == sizeof(uint64_t), ""); \ + static_assert(alignof(object) == alignof(uint64_t), ""); + +# include + + // VK_NULL_HANDLE is defined to 0 but we don't want our handle type to compare to arbitrary + // integers. Redefine VK_NULL_HANDLE to nullptr that has its own type. +# undef VK_NULL_HANDLE +# define VK_NULL_HANDLE nullptr #endif // BACKEND_VULKAN_VULKANPLATFORM_H_