Fix alignment of VkWrapper

The alignment of VkWrapper is currently set to match the alignment of
uint64_t which isn't always correct. On some platforms (e.g. Linux x86)
the alignment of uint64_t inside and outside of a struct differ (8 vs
4). Using an alignment of 8 will cause swiftshader to miscalculate the
size of structs containing VkWrappers and the offset of different
fields into the struct. This is why the alignment of VkWrapper should
match that of uint64_t inside a struct, not outside of it.

Bug: chromium:967831
Change-Id: Ibf8240d13406413481cf87e9d45df4478c35be2f
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/32108
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Saman Sami <samans@chromium.org>
diff --git a/src/Vulkan/VulkanPlatform.h b/src/Vulkan/VulkanPlatform.h
index 958c22d..9825197 100644
--- a/src/Vulkan/VulkanPlatform.h
+++ b/src/Vulkan/VulkanPlatform.h
@@ -18,7 +18,17 @@
 #include <cstddef>
 #include <cstdint>
 
-template<typename HandleType> class alignas(sizeof(uint64_t)) VkWrapperBase
+// We can't directly use alignas(uint64_t) because on some platforms a uint64_t
+// has an alignment of 8 outside of a struct but inside it has an alignment of
+// 4. We use this dummy struct to figure out the alignment of uint64_t inside a
+// struct.
+struct DummyUInt64Wrapper {
+	uint64_t dummy;
+};
+
+static constexpr size_t kNativeVkHandleAlignment = alignof(DummyUInt64Wrapper);
+
+template<typename HandleType> class alignas(kNativeVkHandleAlignment) VkWrapperBase
 {
 public:
 	VkWrapperBase(HandleType handle)
@@ -52,7 +62,7 @@
 	PointerHandleUnion u;
 };
 
-template<typename T> class alignas(sizeof(uint64_t)) VkWrapper : public VkWrapperBase<T>
+template<typename T> class alignas(kNativeVkHandleAlignment) VkWrapper : public VkWrapperBase<T>
 {
 public:
 	using HandleType = T;
@@ -75,7 +85,7 @@
 // VkDescriptorSet objects are really just memory in the VkDescriptorPool
 // object, so define different/more convenient operators for this object.
 struct VkDescriptorSet_T;
-template<> class alignas(sizeof(uint64_t)) VkWrapper<VkDescriptorSet_T*> : public VkWrapperBase<uint8_t*>
+template<> class alignas(kNativeVkHandleAlignment) VkWrapper<VkDescriptorSet_T*> : public VkWrapperBase<uint8_t*>
 {
 public:
 	using HandleType = uint8_t*;