diff --git a/renderdoc/driver/vulkan/vk_common.cpp b/renderdoc/driver/vulkan/vk_common.cpp index e124541c9..a0acc4cde 100644 --- a/renderdoc/driver/vulkan/vk_common.cpp +++ b/renderdoc/driver/vulkan/vk_common.cpp @@ -1149,6 +1149,8 @@ void DescriptorSetSlot::AccumulateBindRefs(DescriptorBindRefs &refs, VulkanResou RDCCOMPILE_ASSERT(uint64_t(DescriptorSlotType::Count) <= 0xff, "DescriptorSlotType is no longer 8-bit"); RDCCOMPILE_ASSERT(sizeof(DescriptorSetSlot) == 32, "DescriptorSetSlot is no longer 32 bytes"); + RDCCOMPILE_ASSERT(offsetof(DescriptorSetSlot, offset) == 8, + "DescriptorSetSlot first uint64_t bitpacking isn't working as expected"); VkResourceRecord *bufView = NULL, *imgView = NULL, *buffer = NULL; diff --git a/renderdoc/driver/vulkan/vk_common.h b/renderdoc/driver/vulkan/vk_common.h index 78e063b19..098da720f 100644 --- a/renderdoc/driver/vulkan/vk_common.h +++ b/renderdoc/driver/vulkan/vk_common.h @@ -460,8 +460,24 @@ struct MemoryAllocation struct VkResourceRecord; class VulkanResourceManager; +// gcc is buggy garbage, and if these enums are compiled as uint64_t it will warn (until gcc 9) that +// the enum won't fit in an 8-bit bitfield. +// As a workaround we use pragma push to pack an explicit uint8_t into a uint64_t:48 + +#if defined(__GNUC__) && (__GNUC__ < 10) + +#define EnumBaseType uint8_t +#define GCC_WORKAROUND 1 + +#else + +#define EnumBaseType uint64_t +#define GCC_WORKAROUND 0 + +#endif + // we inherit from uint64_t to make this more bitfield-able but we intend for this to fit in uint8_t -enum class DescriptorSlotType : uint64_t +enum class DescriptorSlotType : EnumBaseType { // we want an unwritten type as 0 so that zero-initialised descriptors that haven't been written // don't look like samplers, so these unfortunately don't match VkDescriptorType in value. @@ -526,8 +542,7 @@ constexpr DescriptorSlotType convert(VkDescriptorType type) // clang-format on } -// we inherit from uint64_t to make this more bitfield-able but we intend for this to fit in uint8_t -enum class DescriptorSlotImageLayout : uint64_t +enum class DescriptorSlotImageLayout : EnumBaseType { // these match the core types Undefined = 0, @@ -637,6 +652,10 @@ struct DescriptorSetSlot // 48-bit truncated VK_WHOLE_SIZE static const VkDeviceSize WholeSizeRange = 0xFFFFFFFFFFFF; VkDeviceSize GetRange() const { return range == WholeSizeRange ? VK_WHOLE_SIZE : range; } +#if GCC_WORKAROUND +#pragma pack(push, 1) +#endif + // used for buffers, we assume the max buffer size is less than 1<<48. // this is placed first to allow writes to just mask the top bits on read or write and remain // aligned, then the type/layout below can be accessed directly as bytes. @@ -648,6 +667,10 @@ struct DescriptorSetSlot // used for images, the image layout DescriptorSlotImageLayout imageLayout : 8; +#if GCC_WORKAROUND +#pragma pack(pop) +#endif + // used for buffers and inline blocks. We could steal some bits here if we needed them since 48 // bits would be plenty for a long time. VkDeviceSize offset;