aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/code_generation_hashes/SPIR-V_helpers.json6
-rwxr-xr-xsrc/common/spirv/gen_spirv_builder_and_parser.py8
-rw-r--r--src/common/spirv/spirv_instruction_builder_autogen.cpp6
-rw-r--r--src/common/spirv/spirv_instruction_builder_autogen.h2
-rw-r--r--src/common/spirv/spirv_types.h5
-rw-r--r--src/compiler/translator/spirv/BuildSPIRV.cpp2
-rw-r--r--src/libANGLE/renderer/vulkan/CLContextVk.cpp4
-rw-r--r--src/libANGLE/renderer/vulkan/SemaphoreVk.cpp11
-rw-r--r--src/libANGLE/renderer/vulkan/UtilsVk.cpp2
-rw-r--r--src/libANGLE/renderer/vulkan/vk_helpers.cpp38
-rw-r--r--src/libANGLE/renderer/vulkan/vk_helpers.h16
-rw-r--r--src/libANGLE/renderer/vulkan/vk_renderer.cpp3
-rw-r--r--src/libANGLE/renderer/vulkan/vk_utils.cpp4
-rw-r--r--src/libANGLE/renderer/vulkan/vk_utils.h34
14 files changed, 79 insertions, 62 deletions
diff --git a/scripts/code_generation_hashes/SPIR-V_helpers.json b/scripts/code_generation_hashes/SPIR-V_helpers.json
index c03d3fba98..29897bad21 100644
--- a/scripts/code_generation_hashes/SPIR-V_helpers.json
+++ b/scripts/code_generation_hashes/SPIR-V_helpers.json
@@ -1,10 +1,10 @@
{
"src/common/spirv/gen_spirv_builder_and_parser.py":
- "322136a5984882a83fcf33cfe92c8097",
+ "771d70f2fe4c89f325cd22efd0ba9be7",
"src/common/spirv/spirv_instruction_builder_autogen.cpp":
- "c149de371bcd571bd31cc8eb1e517910",
+ "682111aced9eab0828dcb361d6f27b60",
"src/common/spirv/spirv_instruction_builder_autogen.h":
- "56b1309d8afabb2b64d7e16f0c4a4898",
+ "7451dcdf46772d43a6509e4a15d07d80",
"src/common/spirv/spirv_instruction_parser_autogen.cpp":
"388f17f462daa8e091238b4d1fd42ef5",
"src/common/spirv/spirv_instruction_parser_autogen.h":
diff --git a/src/common/spirv/gen_spirv_builder_and_parser.py b/src/common/spirv/gen_spirv_builder_and_parser.py
index dc41a43177..01335a026f 100755
--- a/src/common/spirv/gen_spirv_builder_and_parser.py
+++ b/src/common/spirv/gen_spirv_builder_and_parser.py
@@ -106,12 +106,12 @@ uint32_t MakeLengthOp(size_t length, spv::Op op)
}
} // anonymous namespace
-void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount)
+void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t version, uint32_t idCount)
{
// Header:
//
// - Magic number
- // - Version (1.0)
+ // - Version (1.X)
// - ANGLE's Generator number:
// * 24 for tool id (higher 16 bits)
// * 1 for tool version (lower 16 bits))
@@ -123,7 +123,7 @@ void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount)
ASSERT(blob->empty());
blob->push_back(spv::MagicNumber);
- blob->push_back(0x00010000);
+ blob->push_back(version);
blob->push_back(kANGLEGeneratorId << 16 | kANGLEGeneratorVersion);
blob->push_back(idCount);
blob->push_back(0x00000000);
@@ -131,7 +131,7 @@ void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount)
"""
BUILDER_HELPER_FUNCTION_PROTOTYPE = """
- void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount);
+ void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t version, uint32_t idCount);
"""
PARSER_FIXED_FUNCTIONS_PROTOTYPES = """void GetInstructionOpAndLength(const uint32_t *_instruction,
diff --git a/src/common/spirv/spirv_instruction_builder_autogen.cpp b/src/common/spirv/spirv_instruction_builder_autogen.cpp
index 6e6ad6f510..c63aed55c3 100644
--- a/src/common/spirv/spirv_instruction_builder_autogen.cpp
+++ b/src/common/spirv/spirv_instruction_builder_autogen.cpp
@@ -38,12 +38,12 @@ uint32_t MakeLengthOp(size_t length, spv::Op op)
}
} // anonymous namespace
-void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount)
+void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t version, uint32_t idCount)
{
// Header:
//
// - Magic number
- // - Version (1.0)
+ // - Version (1.X)
// - ANGLE's Generator number:
// * 24 for tool id (higher 16 bits)
// * 1 for tool version (lower 16 bits))
@@ -55,7 +55,7 @@ void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount)
ASSERT(blob->empty());
blob->push_back(spv::MagicNumber);
- blob->push_back(0x00010000);
+ blob->push_back(version);
blob->push_back(kANGLEGeneratorId << 16 | kANGLEGeneratorVersion);
blob->push_back(idCount);
blob->push_back(0x00000000);
diff --git a/src/common/spirv/spirv_instruction_builder_autogen.h b/src/common/spirv/spirv_instruction_builder_autogen.h
index 1caf5cd204..7ecfd0a1ce 100644
--- a/src/common/spirv/spirv_instruction_builder_autogen.h
+++ b/src/common/spirv/spirv_instruction_builder_autogen.h
@@ -20,7 +20,7 @@ namespace angle
namespace spirv
{
-void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t idCount);
+void WriteSpirvHeader(std::vector<uint32_t> *blob, uint32_t version, uint32_t idCount);
void WriteNop(Blob *blob);
void WriteUndef(Blob *blob, IdResultType idResultType, IdResult idResult);
void WriteSourceContinued(Blob *blob, LiteralString continuedSource);
diff --git a/src/common/spirv/spirv_types.h b/src/common/spirv/spirv_types.h
index c97e4db477..b27befdbaa 100644
--- a/src/common/spirv/spirv_types.h
+++ b/src/common/spirv/spirv_types.h
@@ -125,6 +125,11 @@ enum HeaderIndex
kHeaderIndexInstructions = 5,
};
+// SPIR-V version
+constexpr uint32_t kVersion_1_0 = 0x00010000;
+constexpr uint32_t kVersion_1_3 = 0x00010300;
+constexpr uint32_t kVersion_1_4 = 0x00010400;
+
// Returns whether SPIR-V is valid. Useful for ASSERTs. Automatically generates a warning if
// SPIR-V is not valid.
bool Validate(const Blob &blob);
diff --git a/src/compiler/translator/spirv/BuildSPIRV.cpp b/src/compiler/translator/spirv/BuildSPIRV.cpp
index 8edf4bb11b..b79b99b291 100644
--- a/src/compiler/translator/spirv/BuildSPIRV.cpp
+++ b/src/compiler/translator/spirv/BuildSPIRV.cpp
@@ -2321,7 +2321,7 @@ spirv::Blob SPIRVBuilder::getSpirv()
mSpirvFunctions.size());
// Generate the SPIR-V header.
- spirv::WriteSpirvHeader(&result, mNextAvailableId);
+ spirv::WriteSpirvHeader(&result, spirv::kVersion_1_0, mNextAvailableId);
// Generate metadata in the following order:
//
diff --git a/src/libANGLE/renderer/vulkan/CLContextVk.cpp b/src/libANGLE/renderer/vulkan/CLContextVk.cpp
index 5acd9a1a8a..0aae828100 100644
--- a/src/libANGLE/renderer/vulkan/CLContextVk.cpp
+++ b/src/libANGLE/renderer/vulkan/CLContextVk.cpp
@@ -26,7 +26,9 @@ CLContextVk::CLContextVk(const cl::Context &context, const cl::DevicePtrs device
: CLContextImpl(context),
vk::Context(getPlatform()->getRenderer()),
mAssociatedDevices(devicePtrs)
-{}
+{
+ mDeviceQueueIndex = mRenderer->getDefaultDeviceQueueIndex();
+}
CLContextVk::~CLContextVk() = default;
diff --git a/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp b/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp
index df3b0e3217..6dae003151 100644
--- a/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp
+++ b/src/libANGLE/renderer/vulkan/SemaphoreVk.cpp
@@ -85,7 +85,7 @@ angle::Result SemaphoreVk::wait(gl::Context *context,
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// Queue ownership transfer.
- bufferHelper.acquireFromExternal(VK_QUEUE_FAMILY_EXTERNAL,
+ bufferHelper.acquireFromExternal(vk::kExternalDeviceQueueIndex,
contextVk->getDeviceQueueIndex(), commandBuffer);
}
}
@@ -112,7 +112,7 @@ angle::Result SemaphoreVk::wait(gl::Context *context,
ASSERT(!image.hasStagedUpdatesInAllocatedLevels() || image.hasEmulatedImageChannels());
// Queue ownership transfer and layout transition.
- image.acquireFromExternal(contextVk, VK_QUEUE_FAMILY_EXTERNAL,
+ image.acquireFromExternal(contextVk, vk::kExternalDeviceQueueIndex,
contextVk->getDeviceQueueIndex(), layout, commandBuffer);
}
}
@@ -143,8 +143,7 @@ angle::Result SemaphoreVk::signal(gl::Context *context,
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// Queue ownership transfer.
- bufferHelper.releaseToExternal(contextVk->getDeviceQueueIndex(),
- VK_QUEUE_FAMILY_EXTERNAL, commandBuffer);
+ bufferHelper.releaseToExternal(vk::kExternalDeviceQueueIndex, commandBuffer);
}
}
@@ -176,8 +175,8 @@ angle::Result SemaphoreVk::signal(gl::Context *context,
ANGLE_TRY(contextVk->getOutsideRenderPassCommandBuffer(access, &commandBuffer));
// Queue ownership transfer and layout transition.
- image.releaseToExternal(contextVk, contextVk->getDeviceQueueIndex(),
- VK_QUEUE_FAMILY_EXTERNAL, layout, commandBuffer);
+ image.releaseToExternal(contextVk, vk::kExternalDeviceQueueIndex, layout,
+ commandBuffer);
}
}
diff --git a/src/libANGLE/renderer/vulkan/UtilsVk.cpp b/src/libANGLE/renderer/vulkan/UtilsVk.cpp
index 526b5a0680..05feb1fd66 100644
--- a/src/libANGLE/renderer/vulkan/UtilsVk.cpp
+++ b/src/libANGLE/renderer/vulkan/UtilsVk.cpp
@@ -1064,7 +1064,7 @@ angle::spirv::Blob MakeFragShader(
code.reserve(169);
// Header
- spirv::WriteSpirvHeader(&code, kIdCount);
+ spirv::WriteSpirvHeader(&code, spirv::kVersion_1_0, kIdCount);
// The preamble
InsertPreamble(colorAttachmentCount, unresolveDepth, unresolveStencilWithShaderExport, &code);
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
index 42e4e11050..548bf79110 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
@@ -5526,9 +5526,9 @@ angle::Result BufferHelper::invalidate(Renderer *renderer)
return invalidate(renderer, 0, getSize());
}
-void BufferHelper::changeQueue(uint32_t srcQueueFamilyIndex,
- uint32_t dstQueueFamilyIndex,
- OutsideRenderPassCommandBuffer *commandBuffer)
+void BufferHelper::changeQueueFamily(uint32_t srcQueueFamilyIndex,
+ uint32_t dstQueueFamilyIndex,
+ OutsideRenderPassCommandBuffer *commandBuffer)
{
VkBufferMemoryBarrier bufferMemoryBarrier = {};
bufferMemoryBarrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER;
@@ -5544,23 +5544,26 @@ void BufferHelper::changeQueue(uint32_t srcQueueFamilyIndex,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, &bufferMemoryBarrier);
}
-void BufferHelper::acquireFromExternal(uint32_t externalQueueFamilyIndex,
+void BufferHelper::acquireFromExternal(DeviceQueueIndex externalQueueFamilyIndex,
DeviceQueueIndex newDeviceQueueIndex,
OutsideRenderPassCommandBuffer *commandBuffer)
{
- changeQueue(externalQueueFamilyIndex, newDeviceQueueIndex.familyIndex(), commandBuffer);
+ changeQueueFamily(externalQueueFamilyIndex.familyIndex(), newDeviceQueueIndex.familyIndex(),
+ commandBuffer);
mCurrentDeviceQueueIndex = newDeviceQueueIndex;
mIsReleasedToExternal = false;
}
-void BufferHelper::releaseToExternal(DeviceQueueIndex rendererDeviceQueueIndex,
- uint32_t externalQueueFamilyIndex,
+void BufferHelper::releaseToExternal(DeviceQueueIndex externalQueueIndex,
OutsideRenderPassCommandBuffer *commandBuffer)
{
- ASSERT(mCurrentDeviceQueueIndex == rendererDeviceQueueIndex);
- changeQueue(rendererDeviceQueueIndex.familyIndex(), externalQueueFamilyIndex, commandBuffer);
- mCurrentDeviceQueueIndex = kInvalidDeviceQueueIndex;
- mIsReleasedToExternal = true;
+ if (mCurrentDeviceQueueIndex.familyIndex() != externalQueueIndex.familyIndex())
+ {
+ changeQueueFamily(mCurrentDeviceQueueIndex.familyIndex(), externalQueueIndex.familyIndex(),
+ commandBuffer);
+ mCurrentDeviceQueueIndex = kInvalidDeviceQueueIndex;
+ }
+ mIsReleasedToExternal = true;
}
bool BufferHelper::isReleasedToExternal() const
@@ -7046,7 +7049,7 @@ void ImageHelper::changeLayoutAndQueue(Context *context,
}
void ImageHelper::acquireFromExternal(Context *context,
- uint32_t externalQueueFamilyIndex,
+ DeviceQueueIndex externalQueueIndex,
DeviceQueueIndex newDeviceQueueIndex,
ImageLayout currentLayout,
OutsideRenderPassCommandBuffer *commandBuffer)
@@ -7055,10 +7058,10 @@ void ImageHelper::acquireFromExternal(Context *context,
// queue. If this is not the case, it's an application bug, so ASSERT might
// eventually need to change to a warning.
ASSERT(mCurrentLayout == ImageLayout::ExternalPreInitialized ||
- mCurrentDeviceQueueIndex.familyIndex() == externalQueueFamilyIndex);
+ mCurrentDeviceQueueIndex.familyIndex() == externalQueueIndex.familyIndex());
mCurrentLayout = currentLayout;
- mCurrentDeviceQueueIndex = DeviceQueueIndex(externalQueueFamilyIndex);
+ mCurrentDeviceQueueIndex = externalQueueIndex;
mIsReleasedToExternal = false;
// Only change the layout and queue if the layout is anything by Undefined. If it is undefined,
@@ -7082,8 +7085,7 @@ void ImageHelper::acquireFromExternal(Context *context,
}
void ImageHelper::releaseToExternal(Context *context,
- DeviceQueueIndex rendererDeviceQueueIndex,
- uint32_t externalQueueFamilyIndex,
+ DeviceQueueIndex externalQueueIndex,
ImageLayout desiredLayout,
OutsideRenderPassCommandBuffer *commandBuffer)
{
@@ -7091,10 +7093,10 @@ void ImageHelper::releaseToExternal(Context *context,
// A layout change is unnecessary if the image that was previously acquired was never used by
// GL!
- if (mCurrentDeviceQueueIndex.familyIndex() != externalQueueFamilyIndex ||
+ if (mCurrentDeviceQueueIndex.familyIndex() != externalQueueIndex.familyIndex() ||
mCurrentLayout != desiredLayout)
{
- changeLayoutAndQueue(context, getAspectFlags(), desiredLayout, externalQueueFamilyIndex,
+ changeLayoutAndQueue(context, getAspectFlags(), desiredLayout, externalQueueIndex,
commandBuffer);
}
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.h b/src/libANGLE/renderer/vulkan/vk_helpers.h
index c3c127ce79..1ce7c93821 100644
--- a/src/libANGLE/renderer/vulkan/vk_helpers.h
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.h
@@ -973,18 +973,17 @@ class BufferHelper : public ReadWriteResource
angle::Result invalidate(Renderer *renderer);
angle::Result invalidate(Renderer *renderer, VkDeviceSize offset, VkDeviceSize size);
- void changeQueue(uint32_t srcQueueFamilyIndex,
- uint32_t dstQueueFamilyIndex,
- OutsideRenderPassCommandBuffer *commandBuffer);
+ void changeQueueFamily(uint32_t srcQueueFamilyIndex,
+ uint32_t dstQueueFamilyIndex,
+ OutsideRenderPassCommandBuffer *commandBuffer);
// Performs an ownership transfer from an external instance or API.
- void acquireFromExternal(uint32_t externalQueueFamilyIndex,
+ void acquireFromExternal(DeviceQueueIndex externalQueueIndex,
DeviceQueueIndex newDeviceQueueIndex,
OutsideRenderPassCommandBuffer *commandBuffer);
// Performs an ownership transfer to an external instance or API.
- void releaseToExternal(DeviceQueueIndex rendererDeviceQueueIndex,
- uint32_t externalQueueFamilyIndex,
+ void releaseToExternal(DeviceQueueIndex externalQueueIndex,
OutsideRenderPassCommandBuffer *commandBuffer);
// Returns true if the image is owned by an external API or instance.
@@ -2574,15 +2573,14 @@ class ImageHelper final : public Resource, public angle::Subject
// Performs an ownership transfer from an external instance or API.
void acquireFromExternal(Context *context,
- uint32_t externalQueueFamilyIndex,
+ DeviceQueueIndex externalQueueIndex,
DeviceQueueIndex newDeviceQueueIndex,
ImageLayout currentLayout,
OutsideRenderPassCommandBuffer *commandBuffer);
// Performs an ownership transfer to an external instance or API.
void releaseToExternal(Context *context,
- DeviceQueueIndex rendererDeviceQueueIndex,
- uint32_t externalQueueFamilyIndex,
+ DeviceQueueIndex externalQueueIndex,
ImageLayout desiredLayout,
OutsideRenderPassCommandBuffer *commandBuffer);
diff --git a/src/libANGLE/renderer/vulkan/vk_renderer.cpp b/src/libANGLE/renderer/vulkan/vk_renderer.cpp
index d2210247ef..983c90f433 100644
--- a/src/libANGLE/renderer/vulkan/vk_renderer.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_renderer.cpp
@@ -163,7 +163,8 @@ bool IsXclipse()
bool ShouldUseEventForImageBarrier()
{
- return true;
+ // Disabled for now while performance is under investigation
+ return false;
}
bool StrLess(const char *a, const char *b)
diff --git a/src/libANGLE/renderer/vulkan/vk_utils.cpp b/src/libANGLE/renderer/vulkan/vk_utils.cpp
index 1165bc7203..0699e95e83 100644
--- a/src/libANGLE/renderer/vulkan/vk_utils.cpp
+++ b/src/libANGLE/renderer/vulkan/vk_utils.cpp
@@ -372,9 +372,7 @@ VkImageAspectFlags GetFormatAspectFlags(const angle::Format &format)
// Context implementation.
Context::Context(Renderer *renderer)
: mRenderer(renderer), mShareGroupRefCountedEventsGarbageRecycler(nullptr), mPerfCounters{}
-{
- mDeviceQueueIndex = mRenderer->getDefaultDeviceQueueIndex();
-}
+{}
Context::~Context() {}
diff --git a/src/libANGLE/renderer/vulkan/vk_utils.h b/src/libANGLE/renderer/vulkan/vk_utils.h
index 8e8d331dc7..0df93a457f 100644
--- a/src/libANGLE/renderer/vulkan/vk_utils.h
+++ b/src/libANGLE/renderer/vulkan/vk_utils.h
@@ -141,11 +141,17 @@ class DeviceQueueIndex final
: mFamilyIndex(kInvalidQueueFamilyIndex), mQueueIndex(kInvalidQueueIndex)
{}
constexpr DeviceQueueIndex(uint32_t familyIndex)
- : mFamilyIndex(familyIndex), mQueueIndex(kInvalidQueueIndex)
- {}
+ : mFamilyIndex((int8_t)familyIndex), mQueueIndex(kInvalidQueueIndex)
+ {
+ ASSERT(static_cast<uint32_t>(mFamilyIndex) == familyIndex);
+ }
DeviceQueueIndex(uint32_t familyIndex, uint32_t queueIndex)
- : mFamilyIndex(familyIndex), mQueueIndex(queueIndex)
- {}
+ : mFamilyIndex((int8_t)familyIndex), mQueueIndex((int8_t)queueIndex)
+ {
+ // Ensure the value we actually don't truncate the useful bits.
+ ASSERT(static_cast<uint32_t>(mFamilyIndex) == familyIndex);
+ ASSERT(static_cast<uint32_t>(mQueueIndex) == queueIndex);
+ }
DeviceQueueIndex(const DeviceQueueIndex &other) { *this = other; }
DeviceQueueIndex &operator=(const DeviceQueueIndex &other)
@@ -154,23 +160,26 @@ class DeviceQueueIndex final
return *this;
}
- uint32_t familyIndex() const { return mFamilyIndex; }
- uint32_t queueIndex() const { return mQueueIndex; }
+ constexpr uint32_t familyIndex() const { return mFamilyIndex; }
+ constexpr uint32_t queueIndex() const { return mQueueIndex; }
bool operator==(const DeviceQueueIndex &other) const { return mValue == other.mValue; }
bool operator!=(const DeviceQueueIndex &other) const { return mValue != other.mValue; }
private:
- static constexpr uint32_t kInvalidQueueFamilyIndex = std::numeric_limits<uint32_t>::max();
- static constexpr uint32_t kInvalidQueueIndex = std::numeric_limits<uint32_t>::max();
+ static constexpr int8_t kInvalidQueueFamilyIndex = -1;
+ static constexpr int8_t kInvalidQueueIndex = -1;
+ // The expectation is that these indices are small numbers that could easily fit into int8_t.
+ // int8_t is used instead of uint8_t because we need to handle VK_QUEUE_FAMILY_FOREIGN_EXT and
+ // VK_QUEUE_FAMILY_EXTERNAL properly which are essentially are negative values.
union
{
struct
{
- uint32_t mFamilyIndex;
- uint32_t mQueueIndex;
+ int8_t mFamilyIndex;
+ int8_t mQueueIndex;
};
- uint64_t mValue;
+ uint16_t mValue;
};
};
static constexpr DeviceQueueIndex kInvalidDeviceQueueIndex = DeviceQueueIndex();
@@ -178,6 +187,9 @@ static constexpr DeviceQueueIndex kForeignDeviceQueueIndex =
DeviceQueueIndex(VK_QUEUE_FAMILY_FOREIGN_EXT);
static constexpr DeviceQueueIndex kExternalDeviceQueueIndex =
DeviceQueueIndex(VK_QUEUE_FAMILY_EXTERNAL);
+static_assert(kForeignDeviceQueueIndex.familyIndex() == VK_QUEUE_FAMILY_FOREIGN_EXT);
+static_assert(kExternalDeviceQueueIndex.familyIndex() == VK_QUEUE_FAMILY_EXTERNAL);
+static_assert(kInvalidDeviceQueueIndex.familyIndex() == VK_QUEUE_FAMILY_IGNORED);
// A packed attachment index interface with vulkan API
class PackedAttachmentIndex final