Merge pull request #872 from billhollings/master
Add support for VK_KHR_external_memory extension.
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index ca421d0..2b7845c 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -19,6 +19,12 @@
Released TBD
+- Add support for extensions:
+ - `VK_KHR_external_memory` (non-functional groundwork for future
+ Metal-resource Vulkan extension).
+ - `VK_KHR_external_memory_capabilities` (non-functional groundwork
+ for future Metal-resource Vulkan extension).
+- Memory consumption improvements when handling Vulkan commands.
- Reinstate `VulkanSamples API-Samples` demo apps and add
`input_attachment` and `push_descriptors` demos.
- `vkQueuePresentKHR()` returns a `VkResult` for each swapchain.
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm
index 01b8daf..af83890 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdPipeline.mm
@@ -261,18 +261,17 @@
}
if (mvkDvc->_enabledExtensions.vk_EXT_inline_uniform_block.enabled) {
const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr;
- for (auto* next = (VkWriteDescriptorSetInlineUniformBlockEXT*)descWrite.pNext; next; next = (VkWriteDescriptorSetInlineUniformBlockEXT*)next->pNext)
- {
+ for (const auto* next = (VkBaseInStructure*)descWrite.pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: {
- pInlineUniformBlock = next;
+ pInlineUniformBlock = (VkWriteDescriptorSetInlineUniformBlockEXT*)next;
break;
}
default:
break;
}
}
- if (pInlineUniformBlock != nullptr) {
+ if (pInlineUniformBlock) {
auto *pNewInlineUniformBlock = new VkWriteDescriptorSetInlineUniformBlockEXT(*pInlineUniformBlock);
pNewInlineUniformBlock->pNext = nullptr; // clear pNext just in case, no other extensions are supported at this time
descWrite.pNext = pNewInlineUniformBlock;
@@ -300,11 +299,10 @@
if (descWrite.pTexelBufferView) { delete[] descWrite.pTexelBufferView; }
const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr;
- for (auto* next = (VkWriteDescriptorSetInlineUniformBlockEXT*)descWrite.pNext; next; next = (VkWriteDescriptorSetInlineUniformBlockEXT*)next->pNext)
- {
+ for (const auto* next = (VkBaseInStructure*)descWrite.pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: {
- pInlineUniformBlock = next;
+ pInlineUniformBlock = (VkWriteDescriptorSetInlineUniformBlockEXT*)next;
break;
}
default:
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h
index d3cbb05..3f88415 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h
@@ -48,6 +48,9 @@
/** Binds this resource to the specified offset within the specified memory allocation. */
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override;
+ /** Binds this resource to the specified offset within the specified memory allocation. */
+ VkResult bindDeviceMemory2(const VkBindBufferMemoryInfo* pBindInfo);
+
/** Applies the specified global memory barrier. */
void applyMemoryBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
@@ -92,6 +95,7 @@
bool shouldFlushHostMemory();
VkResult flushToDevice(VkDeviceSize offset, VkDeviceSize size);
VkResult pullFromDevice(VkDeviceSize offset, VkDeviceSize size);
+ void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
VkBufferUsageFlags _usage;
bool _isHostCoherentTexelBuffer = false;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
index ed74605..8c55b3b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm
@@ -66,8 +66,8 @@
switch (next->sType) {
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
auto* dedicatedReqs = (VkMemoryDedicatedRequirements*)next;
- dedicatedReqs->prefersDedicatedAllocation = VK_FALSE;
- dedicatedReqs->requiresDedicatedAllocation = VK_FALSE;
+ dedicatedReqs->requiresDedicatedAllocation = _requiresDedicatedMemoryAllocation;
+ dedicatedReqs->prefersDedicatedAllocation = dedicatedReqs->requiresDedicatedAllocation;
break;
}
default:
@@ -93,6 +93,10 @@
return _deviceMemory ? _deviceMemory->addBuffer(this) : VK_SUCCESS;
}
+VkResult MVKBuffer::bindDeviceMemory2(const VkBindBufferMemoryInfo* pBindInfo) {
+ return bindDeviceMemory((MVKDeviceMemory*)pBindInfo->memory, pBindInfo->memoryOffset);
+}
+
void MVKBuffer::applyMemoryBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
VkMemoryBarrier* pMemoryBarrier,
@@ -192,6 +196,28 @@
MVKBuffer::MVKBuffer(MVKDevice* device, const VkBufferCreateInfo* pCreateInfo) : MVKResource(device), _usage(pCreateInfo->usage) {
_byteAlignment = _device->_pMetalFeatures->mtlBufferAlignment;
_byteCount = pCreateInfo->size;
+
+ for (const auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
+ switch (next->sType) {
+ case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO: {
+ auto* pExtMemInfo = (const VkExternalMemoryBufferCreateInfo*)next;
+ initExternalMemory(pExtMemInfo->handleTypes);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+void MVKBuffer::initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes) {
+ if (mvkIsOnlyAnyFlagEnabled(handleTypes, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR)) {
+ _externalMemoryHandleTypes = handleTypes;
+ auto& xmProps = _device->getPhysicalDevice()->getExternalBufferProperties(VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR);
+ _requiresDedicatedMemoryAllocation = _requiresDedicatedMemoryAllocation || mvkIsAnyFlagEnabled(xmProps.externalMemoryFeatures, VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT);
+ } else {
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateBuffer(): Only external memory handle type VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR is supported."));
+ }
}
MVKBuffer::~MVKBuffer() {
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
index a433703..45d5ba5 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDescriptorSet.mm
@@ -109,11 +109,10 @@
const VkBufferView* pTexelBufferView = descWrite.pTexelBufferView;
const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr;
if (_device->_enabledExtensions.vk_EXT_inline_uniform_block.enabled) {
- for (auto* next = (VkWriteDescriptorSetInlineUniformBlockEXT*)descWrite.pNext; next; next = (VkWriteDescriptorSetInlineUniformBlockEXT*)next->pNext)
- {
+ for (const auto* next = (VkBaseInStructure*)descWrite.pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: {
- pInlineUniformBlock = next;
+ pInlineUniformBlock = (VkWriteDescriptorSetInlineUniformBlockEXT*)next;
break;
}
default:
@@ -689,11 +688,10 @@
const VkWriteDescriptorSetInlineUniformBlockEXT* pInlineUniformBlock = nullptr;
if (dstSet->getDevice()->_enabledExtensions.vk_EXT_inline_uniform_block.enabled) {
- for (auto* next = (VkWriteDescriptorSetInlineUniformBlockEXT*)pDescWrite->pNext; next; next = (VkWriteDescriptorSetInlineUniformBlockEXT*)next->pNext)
- {
+ for (const auto* next = (VkBaseInStructure*)pDescWrite->pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT: {
- pInlineUniformBlock = next;
+ pInlineUniformBlock = (VkWriteDescriptorSetInlineUniformBlockEXT*)next;
break;
}
default:
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
index c9527f0..f5e1f4d 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
@@ -117,12 +117,9 @@
void getFormatProperties(VkFormat format, VkFormatProperties* pFormatProperties);
/** Populates the specified structure with the format properties of this device. */
- void getFormatProperties(VkFormat format, VkFormatProperties2KHR* pFormatProperties);
+ void getFormatProperties(VkFormat format, VkFormatProperties2* pFormatProperties);
- /**
- * Populates the specified structure with the image format properties
- * supported for the specified image characteristics on this device.
- */
+ /** Populates the image format properties supported on this device. */
VkResult getImageFormatProperties(VkFormat format,
VkImageType type,
VkImageTiling tiling,
@@ -130,12 +127,13 @@
VkImageCreateFlags flags,
VkImageFormatProperties* pImageFormatProperties);
- /**
- * Populates the specified structure with the image format properties
- * supported for the specified image characteristics on this device.
- */
- VkResult getImageFormatProperties(const VkPhysicalDeviceImageFormatInfo2KHR* pImageFormatInfo,
- VkImageFormatProperties2KHR* pImageFormatProperties);
+ /** Populates the image format properties supported on this device. */
+ VkResult getImageFormatProperties(const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
+ VkImageFormatProperties2* pImageFormatProperties);
+
+ /** Populates the external buffer properties supported on this device. */
+ void getExternalBufferProperties(const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+ VkExternalBufferProperties* pExternalBufferProperties);
#pragma mark Surfaces
@@ -244,13 +242,13 @@
#pragma mark Memory models
/** Returns a pointer to the memory characteristics of this device. */
- inline const VkPhysicalDeviceMemoryProperties* getPhysicalDeviceMemoryProperties() { return &_memoryProperties; }
+ inline const VkPhysicalDeviceMemoryProperties* getMemoryProperties() { return &_memoryProperties; }
/** Populates the specified memory properties with the memory characteristics of this device. */
- VkResult getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties* pMemoryProperties);
+ VkResult getMemoryProperties(VkPhysicalDeviceMemoryProperties* pMemoryProperties);
/** Populates the specified memory properties with the memory characteristics of this device. */
- VkResult getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
+ VkResult getMemoryProperties(VkPhysicalDeviceMemoryProperties2* pMemoryProperties);
/**
* Returns a bit mask of all memory type indices.
@@ -285,6 +283,12 @@
/** Returns whether this is a unified memory device. */
bool getHasUnifiedMemory();
+ /** Returns the external memory properties supported for buffers for the handle type. */
+ VkExternalMemoryProperties& getExternalBufferProperties(VkExternalMemoryHandleTypeFlagBits handleType);
+
+ /** Returns the external memory properties supported for images for the handle type. */
+ VkExternalMemoryProperties& getExternalImageProperties(VkExternalMemoryHandleTypeFlagBits handleType);
+
#pragma mark Metal
@@ -339,12 +343,14 @@
uint64_t getVRAMSize();
uint64_t getRecommendedMaxWorkingSetSize();
uint64_t getCurrentAllocatedSize();
+ void initExternalMemoryProperties();
void initExtensions();
MVKVector<MVKQueueFamily*>& getQueueFamilies();
void initPipelineCacheUUID();
uint32_t getHighestMTLFeatureSet();
uint64_t getSpirvCrossRevision();
- bool getImageViewIsSupported(const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo);
+ bool getImageViewIsSupported(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo);
+ void populate(VkPhysicalDeviceIDProperties* pDevIdProps);
void logGPUInfo();
id<MTLDevice> _mtlDevice;
@@ -362,6 +368,8 @@
uint32_t _hostCoherentMemoryTypes;
uint32_t _privateMemoryTypes;
uint32_t _lazilyAllocatedMemoryTypes;
+ VkExternalMemoryProperties _mtlBufferExternalMemoryProperties;
+ VkExternalMemoryProperties _mtlTextureExternalMemoryProperties;
};
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index 442f23c..00b8b42 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -62,166 +62,216 @@
}
void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures* features) {
- if (features) { *features = _features; }
+ *features = _features;
}
void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
- if (features) {
- features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
- features->features = _features;
- for (auto* next = (VkBaseOutStructure*)features->pNext; next; next = next->pNext) {
- switch ((uint32_t)next->sType) {
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
- auto* storageFeatures = (VkPhysicalDevice16BitStorageFeatures*)next;
- storageFeatures->storageBuffer16BitAccess = true;
- storageFeatures->uniformAndStorageBuffer16BitAccess = true;
- storageFeatures->storagePushConstant16 = true;
- storageFeatures->storageInputOutput16 = true;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR: {
- auto* storageFeatures = (VkPhysicalDevice8BitStorageFeaturesKHR*)next;
- storageFeatures->storageBuffer8BitAccess = true;
- storageFeatures->uniformAndStorageBuffer8BitAccess = true;
- storageFeatures->storagePushConstant8 = true;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR: {
- auto* f16Features = (VkPhysicalDeviceFloat16Int8FeaturesKHR*)next;
- f16Features->shaderFloat16 = true;
- f16Features->shaderInt8 = true;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR: {
- auto* uboLayoutFeatures = (VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR*)next;
- uboLayoutFeatures->uniformBufferStandardLayout = true;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES: {
- auto* varPtrFeatures = (VkPhysicalDeviceVariablePointerFeatures*)next;
- varPtrFeatures->variablePointersStorageBuffer = true;
- varPtrFeatures->variablePointers = true;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: {
- auto* interlockFeatures = (VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*)next;
- interlockFeatures->fragmentShaderSampleInterlock = _metalFeatures.rasterOrderGroups;
- interlockFeatures->fragmentShaderPixelInterlock = _metalFeatures.rasterOrderGroups;
- interlockFeatures->fragmentShaderShadingRateInterlock = false; // Requires variable rate shading; not supported yet in Metal
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT: {
- auto* hostQueryResetFeatures = (VkPhysicalDeviceHostQueryResetFeaturesEXT*)next;
- hostQueryResetFeatures->hostQueryReset = true;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT: {
- auto* scalarLayoutFeatures = (VkPhysicalDeviceScalarBlockLayoutFeaturesEXT*)next;
- scalarLayoutFeatures->scalarBlockLayout = true;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT: {
- auto* texelBuffAlignFeatures = (VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT*)next;
- texelBuffAlignFeatures->texelBufferAlignment = _metalFeatures.texelBuffers && [_mtlDevice respondsToSelector: @selector(minimumLinearTextureAlignmentForPixelFormat:)];
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
- auto* divisorFeatures = (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT*)next;
- divisorFeatures->vertexAttributeInstanceRateDivisor = true;
- divisorFeatures->vertexAttributeInstanceRateZeroDivisor = true;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_EXTX: {
- auto* portabilityFeatures = (VkPhysicalDevicePortabilitySubsetFeaturesEXTX*)next;
- portabilityFeatures->triangleFans = false;
- portabilityFeatures->separateStencilMaskRef = true;
- portabilityFeatures->events = true;
- portabilityFeatures->standardImageViews = _mvkInstance->getMoltenVKConfiguration()->fullImageViewSwizzle || _metalFeatures.nativeTextureSwizzle;
- portabilityFeatures->samplerMipLodBias = false;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL: {
- auto* shaderIntFuncsFeatures = (VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL*)next;
- shaderIntFuncsFeatures->shaderIntegerFunctions2 = true;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT: {
- auto* inlineUniformBlockFeatures = (VkPhysicalDeviceInlineUniformBlockFeaturesEXT*)next;
- inlineUniformBlockFeatures->inlineUniformBlock = true;
- inlineUniformBlockFeatures->descriptorBindingInlineUniformBlockUpdateAfterBind = true;
- break;
- }
- default:
- break;
- }
- }
- }
+ features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+ features->features = _features;
+ for (auto* next = (VkBaseOutStructure*)features->pNext; next; next = next->pNext) {
+ switch ((uint32_t)next->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
+ auto* storageFeatures = (VkPhysicalDevice16BitStorageFeatures*)next;
+ storageFeatures->storageBuffer16BitAccess = true;
+ storageFeatures->uniformAndStorageBuffer16BitAccess = true;
+ storageFeatures->storagePushConstant16 = true;
+ storageFeatures->storageInputOutput16 = true;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES_KHR: {
+ auto* storageFeatures = (VkPhysicalDevice8BitStorageFeaturesKHR*)next;
+ storageFeatures->storageBuffer8BitAccess = true;
+ storageFeatures->uniformAndStorageBuffer8BitAccess = true;
+ storageFeatures->storagePushConstant8 = true;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT16_INT8_FEATURES_KHR: {
+ auto* f16Features = (VkPhysicalDeviceFloat16Int8FeaturesKHR*)next;
+ f16Features->shaderFloat16 = true;
+ f16Features->shaderInt8 = true;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_UNIFORM_BUFFER_STANDARD_LAYOUT_FEATURES_KHR: {
+ auto* uboLayoutFeatures = (VkPhysicalDeviceUniformBufferStandardLayoutFeaturesKHR*)next;
+ uboLayoutFeatures->uniformBufferStandardLayout = true;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES: {
+ auto* varPtrFeatures = (VkPhysicalDeviceVariablePointerFeatures*)next;
+ varPtrFeatures->variablePointersStorageBuffer = true;
+ varPtrFeatures->variablePointers = true;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_INTERLOCK_FEATURES_EXT: {
+ auto* interlockFeatures = (VkPhysicalDeviceFragmentShaderInterlockFeaturesEXT*)next;
+ interlockFeatures->fragmentShaderSampleInterlock = _metalFeatures.rasterOrderGroups;
+ interlockFeatures->fragmentShaderPixelInterlock = _metalFeatures.rasterOrderGroups;
+ interlockFeatures->fragmentShaderShadingRateInterlock = false; // Requires variable rate shading; not supported yet in Metal
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT: {
+ auto* hostQueryResetFeatures = (VkPhysicalDeviceHostQueryResetFeaturesEXT*)next;
+ hostQueryResetFeatures->hostQueryReset = true;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT: {
+ auto* scalarLayoutFeatures = (VkPhysicalDeviceScalarBlockLayoutFeaturesEXT*)next;
+ scalarLayoutFeatures->scalarBlockLayout = true;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT: {
+ auto* texelBuffAlignFeatures = (VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT*)next;
+ texelBuffAlignFeatures->texelBufferAlignment = _metalFeatures.texelBuffers && [_mtlDevice respondsToSelector: @selector(minimumLinearTextureAlignmentForPixelFormat:)];
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
+ auto* divisorFeatures = (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT*)next;
+ divisorFeatures->vertexAttributeInstanceRateDivisor = true;
+ divisorFeatures->vertexAttributeInstanceRateZeroDivisor = true;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_EXTX: {
+ auto* portabilityFeatures = (VkPhysicalDevicePortabilitySubsetFeaturesEXTX*)next;
+ portabilityFeatures->triangleFans = false;
+ portabilityFeatures->separateStencilMaskRef = true;
+ portabilityFeatures->events = true;
+ portabilityFeatures->standardImageViews = _mvkInstance->getMoltenVKConfiguration()->fullImageViewSwizzle || _metalFeatures.nativeTextureSwizzle;
+ portabilityFeatures->samplerMipLodBias = false;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_FUNCTIONS_2_FEATURES_INTEL: {
+ auto* shaderIntFuncsFeatures = (VkPhysicalDeviceShaderIntegerFunctions2FeaturesINTEL*)next;
+ shaderIntFuncsFeatures->shaderIntegerFunctions2 = true;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_FEATURES_EXT: {
+ auto* inlineUniformBlockFeatures = (VkPhysicalDeviceInlineUniformBlockFeaturesEXT*)next;
+ inlineUniformBlockFeatures->inlineUniformBlock = true;
+ inlineUniformBlockFeatures->descriptorBindingInlineUniformBlockUpdateAfterBind = true;
+ break;
+ }
+ default:
+ break;
+ }
+ }
}
void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties* properties) {
- if (properties) { *properties = _properties; }
+ *properties = _properties;
}
void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) {
- if (properties) {
- properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
- properties->properties = _properties;
- for (auto* next = (VkBaseOutStructure*)properties->pNext; next; next = next->pNext) {
- switch ((uint32_t)next->sType) {
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
- auto* pointClipProps = (VkPhysicalDevicePointClippingProperties*)next;
- pointClipProps->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
- auto* maint3Props = (VkPhysicalDeviceMaintenance3Properties*)next;
- maint3Props->maxPerSetDescriptors = (_metalFeatures.maxPerStageBufferCount + _metalFeatures.maxPerStageTextureCount + _metalFeatures.maxPerStageSamplerCount) * 4;
- maint3Props->maxMemoryAllocationSize = _metalFeatures.maxMTLBufferSize;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
- auto* pushDescProps = (VkPhysicalDevicePushDescriptorPropertiesKHR*)next;
- pushDescProps->maxPushDescriptors = _properties.limits.maxPerStageResources;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT: {
- auto* texelBuffAlignProps = (VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT*)next;
- // Save the 'next' pointer; we'll unintentionally overwrite it
- // on the next line. Put it back when we're done.
- void* savedNext = texelBuffAlignProps->pNext;
- *texelBuffAlignProps = _texelBuffAlignProperties;
- texelBuffAlignProps->pNext = savedNext;
- break;
- }
- case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
- auto* divisorProps = (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT*)next;
- divisorProps->maxVertexAttribDivisor = kMVKUndefinedLargeUInt32;
- break;
- }
+ properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ properties->properties = _properties;
+ for (auto* next = (VkBaseOutStructure*)properties->pNext; next; next = next->pNext) {
+ switch ((uint32_t)next->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
+ auto* pointClipProps = (VkPhysicalDevicePointClippingProperties*)next;
+ pointClipProps->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
+ auto* maint3Props = (VkPhysicalDeviceMaintenance3Properties*)next;
+ maint3Props->maxPerSetDescriptors = (_metalFeatures.maxPerStageBufferCount + _metalFeatures.maxPerStageTextureCount + _metalFeatures.maxPerStageSamplerCount) * 4;
+ maint3Props->maxMemoryAllocationSize = _metalFeatures.maxMTLBufferSize;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
+ auto* pushDescProps = (VkPhysicalDevicePushDescriptorPropertiesKHR*)next;
+ pushDescProps->maxPushDescriptors = _properties.limits.maxPerStageResources;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT: {
+ auto* texelBuffAlignProps = (VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT*)next;
+ // Save the 'next' pointer; we'll unintentionally overwrite it
+ // on the next line. Put it back when we're done.
+ void* savedNext = texelBuffAlignProps->pNext;
+ *texelBuffAlignProps = _texelBuffAlignProperties;
+ texelBuffAlignProps->pNext = savedNext;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
+ auto* divisorProps = (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT*)next;
+ divisorProps->maxVertexAttribDivisor = kMVKUndefinedLargeUInt32;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
+ populate((VkPhysicalDeviceIDProperties*)next);
+ break;
+ }
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_EXTX: {
auto* portabilityProps = (VkPhysicalDevicePortabilitySubsetPropertiesEXTX*)next;
portabilityProps->minVertexInputBindingStrideAlignment = 4;
break;
}
- default:
- break;
- }
- }
- }
+ default:
+ break;
+ }
+ }
+}
+
+// Populates the device ID properties structure
+void MVKPhysicalDevice::populate(VkPhysicalDeviceIDProperties* pDevIdProps) {
+
+ uint8_t* uuid;
+ size_t uuidComponentOffset;
+
+ // ---- Device ID ----------------------------------------------
+ uuid = pDevIdProps->deviceUUID;
+ uuidComponentOffset = 0;
+ mvkClear(uuid, VK_UUID_SIZE);
+
+ // First 4 bytes contains GPU vendor ID
+ uint32_t vendorID = _properties.vendorID;
+ *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(vendorID);
+ uuidComponentOffset += sizeof(vendorID);
+
+ // Next 4 bytes contains GPU device ID
+ uint32_t deviceID = _properties.deviceID;
+ *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(deviceID);
+ uuidComponentOffset += sizeof(deviceID);
+
+ // Last 8 bytes contain the GPU registry ID
+ uint64_t regID = mvkGetRegistryID(_mtlDevice);
+ *(uint64_t*)&uuid[uuidComponentOffset] = NSSwapHostLongLongToBig(regID);
+ uuidComponentOffset += sizeof(regID);
+
+
+ // ---- Driver ID ----------------------------------------------
+ uuid = pDevIdProps->driverUUID;
+ uuidComponentOffset = 0;
+ mvkClear(uuid, VK_UUID_SIZE);
+
+ // First 4 bytes contains MoltenVK prefix
+ const char* mvkPfx = "MVK";
+ size_t mvkPfxLen = strlen(mvkPfx);
+ mvkCopy(&uuid[uuidComponentOffset], (uint8_t*)mvkPfx, mvkPfxLen);
+ uuidComponentOffset += mvkPfxLen + 1;
+
+ // Next 4 bytes contains MoltenVK version
+ uint32_t mvkVersion = MVK_VERSION;
+ *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(mvkVersion);
+ uuidComponentOffset += sizeof(mvkVersion);
+
+ // Next 4 bytes contains highest Metal feature set supported by this device
+ uint32_t mtlFeatSet = getHighestMTLFeatureSet();
+ *(uint32_t*)&uuid[uuidComponentOffset] = NSSwapHostIntToBig(mtlFeatSet);
+ uuidComponentOffset += sizeof(mtlFeatSet);
+
+
+ // ---- LUID ignored for Metal devices ------------------------
+ mvkClear(pDevIdProps->deviceLUID, VK_LUID_SIZE);
+ pDevIdProps->deviceNodeMask = 0;
+ pDevIdProps->deviceLUIDValid = VK_FALSE;
}
void MVKPhysicalDevice::getFormatProperties(VkFormat format, VkFormatProperties* pFormatProperties) {
- if (pFormatProperties) {
- *pFormatProperties = _pixelFormats.getVkFormatProperties(format);
- }
+ *pFormatProperties = _pixelFormats.getVkFormatProperties(format);
}
-void MVKPhysicalDevice::getFormatProperties(VkFormat format,
- VkFormatProperties2KHR* pFormatProperties) {
- if (pFormatProperties) {
- pFormatProperties->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR;
- pFormatProperties->formatProperties = _pixelFormats.getVkFormatProperties(format);
- }
+void MVKPhysicalDevice::getFormatProperties(VkFormat format, VkFormatProperties2KHR* pFormatProperties) {
+ pFormatProperties->sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR;
+ pFormatProperties->formatProperties = _pixelFormats.getVkFormatProperties(format);
}
VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format,
@@ -357,32 +407,41 @@
return VK_SUCCESS;
}
-VkResult MVKPhysicalDevice::getImageFormatProperties(const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
- VkImageFormatProperties2KHR* pImageFormatProperties) {
+VkResult MVKPhysicalDevice::getImageFormatProperties(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
+ VkImageFormatProperties2* pImageFormatProperties) {
- if ( !pImageFormatInfo || pImageFormatInfo->sType != VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR ) {
- return VK_ERROR_FORMAT_NOT_SUPPORTED;
- }
+ for (const auto* nextInfo = (VkBaseInStructure*)pImageFormatInfo->pNext; nextInfo; nextInfo = nextInfo->pNext) {
+ switch (nextInfo->sType) {
+ case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO: {
+ // Return information about external memory support for MTLTexture.
+ // Search VkImageFormatProperties2 for the corresponding VkExternalImageFormatProperties and populate it.
+ auto* pExtImgFmtInfo = (VkPhysicalDeviceExternalImageFormatInfo*)nextInfo;
+ for (auto* nextProps = (VkBaseOutStructure*)pImageFormatProperties->pNext; nextProps; nextProps = nextProps->pNext) {
+ if (nextProps->sType == VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES) {
+ auto* pExtImgFmtProps = (VkExternalImageFormatProperties*)nextProps;
+ pExtImgFmtProps->externalMemoryProperties = getExternalImageProperties(pExtImgFmtInfo->handleType);
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
- if ( !_pixelFormats.isSupported(pImageFormatInfo->format) ) { return VK_ERROR_FORMAT_NOT_SUPPORTED; }
+ if ( !_pixelFormats.isSupported(pImageFormatInfo->format) ) { return VK_ERROR_FORMAT_NOT_SUPPORTED; }
if ( !getImageViewIsSupported(pImageFormatInfo) ) { return VK_ERROR_FORMAT_NOT_SUPPORTED; }
- if (pImageFormatProperties) {
- pImageFormatProperties->sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR;
- return getImageFormatProperties(pImageFormatInfo->format, pImageFormatInfo->type,
- pImageFormatInfo->tiling, pImageFormatInfo->usage,
- pImageFormatInfo->flags,
- &pImageFormatProperties->imageFormatProperties);
- }
-
- return VK_SUCCESS;
+ return getImageFormatProperties(pImageFormatInfo->format, pImageFormatInfo->type,
+ pImageFormatInfo->tiling, pImageFormatInfo->usage,
+ pImageFormatInfo->flags,
+ &pImageFormatProperties->imageFormatProperties);
}
// If the image format info links portability image view info, test if an image view of that configuration is supported
-bool MVKPhysicalDevice::getImageViewIsSupported(const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo) {
- auto* next = (MVKVkAPIStructHeader*)pImageFormatInfo->pNext;
- while (next) {
+bool MVKPhysicalDevice::getImageViewIsSupported(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo) {
+ for (const auto* next = (VkBaseInStructure*)pImageFormatInfo->pNext; next; next = next->pNext) {
switch ((uint32_t)next->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_SUPPORT_EXTX: {
auto* portImgViewInfo = (VkPhysicalDeviceImageViewSupportEXTX*)next;
@@ -390,7 +449,7 @@
// Create an image view and test whether it could be configured
VkImageViewCreateInfo viewInfo = {
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .pNext = (VkStructureType*)portImgViewInfo->pNext,
+ .pNext = portImgViewInfo->pNext,
.flags = portImgViewInfo->flags,
.image = nullptr,
.viewType = portImgViewInfo->viewType,
@@ -411,7 +470,6 @@
mtlPixFmt, useSwizzle) == VK_SUCCESS);
}
default:
- next = (MVKVkAPIStructHeader*)next->pNext;
break;
}
}
@@ -419,6 +477,27 @@
return true;
}
+void MVKPhysicalDevice::getExternalBufferProperties(const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+ VkExternalBufferProperties* pExternalBufferProperties) {
+ pExternalBufferProperties->externalMemoryProperties = getExternalBufferProperties(pExternalBufferInfo->handleType);
+}
+
+static VkExternalMemoryProperties _emptyExtMemProps = {};
+
+VkExternalMemoryProperties& MVKPhysicalDevice::getExternalBufferProperties(VkExternalMemoryHandleTypeFlagBits handleType) {
+ switch (handleType) {
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR: return _mtlBufferExternalMemoryProperties;
+ default: return _emptyExtMemProps;
+ }
+}
+
+VkExternalMemoryProperties& MVKPhysicalDevice::getExternalImageProperties(VkExternalMemoryHandleTypeFlagBits handleType) {
+ switch (handleType) {
+ case VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR: return _mtlTextureExternalMemoryProperties;
+ default: return _emptyExtMemProps;
+ }
+}
+
#pragma mark Surfaces
@@ -722,17 +801,16 @@
#pragma mark Memory models
/** Populates the specified memory properties with the memory characteristics of this device. */
-VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
+VkResult MVKPhysicalDevice::getMemoryProperties(VkPhysicalDeviceMemoryProperties* pMemoryProperties) {
*pMemoryProperties = _memoryProperties;
return VK_SUCCESS;
}
-VkResult MVKPhysicalDevice::getPhysicalDeviceMemoryProperties(VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
- if (pMemoryProperties) {
- pMemoryProperties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
- pMemoryProperties->memoryProperties = _memoryProperties;
- for (auto* next = (VkBaseOutStructure*)pMemoryProperties->pNext; next; next = next->pNext) {
- switch (next->sType) {
+VkResult MVKPhysicalDevice::getMemoryProperties(VkPhysicalDeviceMemoryProperties2* pMemoryProperties) {
+ pMemoryProperties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2;
+ pMemoryProperties->memoryProperties = _memoryProperties;
+ for (auto* next = (VkBaseOutStructure*)pMemoryProperties->pNext; next; next = next->pNext) {
+ switch (next->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: {
auto* budgetProps = (VkPhysicalDeviceMemoryBudgetPropertiesEXT*)next;
mvkClear(budgetProps->heapBudget, VK_MAX_MEMORY_HEAPS);
@@ -747,7 +825,6 @@
}
default:
break;
- }
}
}
return VK_SUCCESS;
@@ -765,8 +842,9 @@
initMetalFeatures(); // Call first.
initFeatures(); // Call second.
initProperties(); // Call third.
- initMemoryProperties();
initExtensions();
+ initMemoryProperties();
+ initExternalMemoryProperties();
logGPUInfo();
}
@@ -1470,8 +1548,7 @@
if (regID) {
entry = IOServiceGetMatchingService(kIOMasterPortDefault, IORegistryEntryIDMatching(regID));
if (entry) {
- // That returned the IOGraphicsAccelerator nub. Its parent, then, is the actual
- // PCI device.
+ // That returned the IOGraphicsAccelerator nub. Its parent, then, is the actual PCI device.
io_registry_entry_t parent;
if (IORegistryEntryGetParentEntry(entry, kIOServicePlane, &parent) == kIOReturnSuccess) {
isFound = true;
@@ -1665,7 +1742,7 @@
*(uint32_t*)&_properties.pipelineCacheUUID[uuidComponentOffset] = NSSwapHostIntToBig(mvkVersion);
uuidComponentOffset += sizeof(mvkVersion);
- // Next 4 bytes contains hightest Metal feature set supported by this device
+ // Next 4 bytes contains highest Metal feature set supported by this device
uint32_t mtlFeatSet = getHighestMTLFeatureSet();
*(uint32_t*)&_properties.pipelineCacheUUID[uuidComponentOffset] = NSSwapHostIntToBig(mtlFeatSet);
uuidComponentOffset += sizeof(mtlFeatSet);
@@ -1892,6 +1969,23 @@
#endif
}
+void MVKPhysicalDevice::initExternalMemoryProperties() {
+
+ // Buffers
+ _mtlBufferExternalMemoryProperties.externalMemoryFeatures = (VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
+ VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
+ VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT);
+ _mtlBufferExternalMemoryProperties.exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR;
+ _mtlBufferExternalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR;
+
+ // Images
+ _mtlTextureExternalMemoryProperties.externalMemoryFeatures = (VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT |
+ VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT |
+ VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT);
+ _mtlTextureExternalMemoryProperties.exportFromImportedHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR;
+ _mtlTextureExternalMemoryProperties.compatibleHandleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR;
+}
+
void MVKPhysicalDevice::initExtensions() {
MVKExtensionList* pWritableExtns = (MVKExtensionList*)&_supportedExtensions;
pWritableExtns->disableAllButEnabledDeviceExtensions();
@@ -2815,8 +2909,7 @@
&pdFeats2.features.robustBufferAccess, 55);
}
- auto* next = (MVKVkAPIStructHeader*)pCreateInfo->pNext;
- while (next) {
+ for (const auto* next = (VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
switch ((uint32_t)next->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2: {
auto* requestedFeatures = (VkPhysicalDeviceFeatures2*)next;
@@ -2905,7 +2998,6 @@
default:
break;
}
- next = (MVKVkAPIStructHeader*)next->pNext;
}
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h
index 5fc2cb2..0a51525 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h
@@ -27,6 +27,10 @@
class MVKBuffer;
class MVKImage;
+// TODO: These are inoperable placeholders until VK_KHR_external_memory_metal defines them properly
+static const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
+static const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM;
+
#pragma mark MVKDeviceMemory
@@ -141,6 +145,7 @@
bool ensureHostMemory();
void freeHostMemory();
MVKResource* getDedicatedResource();
+ void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
MVKVectorInline<MVKBuffer*, 4> _buffers;
MVKVectorInline<MVKImage*, 4> _images;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
index 714a8f9..efcce8d 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
@@ -266,10 +266,7 @@
MVKResource* MVKDeviceMemory::getDedicatedResource() {
MVKAssert(_isDedicated, "This method should only be called on dedicated allocations!");
- if (_buffers.empty())
- return _images[0];
- else
- return _buffers[0];
+ return _buffers.empty() ? (MVKResource*)_images[0] : (MVKResource*)_buffers[0];
}
MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device,
@@ -284,22 +281,28 @@
VkImage dedicatedImage = VK_NULL_HANDLE;
VkBuffer dedicatedBuffer = VK_NULL_HANDLE;
- auto* next = (VkStructureType*)pAllocateInfo->pNext;
- while (next) {
- switch (*next) {
- case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO: {
- auto* pDedicatedInfo = (VkMemoryDedicatedAllocateInfo*)next;
- dedicatedImage = pDedicatedInfo->image;
- dedicatedBuffer = pDedicatedInfo->buffer;
- next = (VkStructureType*)pDedicatedInfo->pNext;
- break;
- }
- default:
- next = (VkStructureType*)((VkMemoryAllocateInfo*)next)->pNext;
- break;
+ VkExternalMemoryHandleTypeFlags handleTypes = 0;
+ for (const auto* next = (const VkBaseInStructure*)pAllocateInfo->pNext; next; next = next->pNext) {
+ switch (next->sType) {
+ case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO: {
+ auto* pDedicatedInfo = (VkMemoryDedicatedAllocateInfo*)next;
+ dedicatedImage = pDedicatedInfo->image;
+ dedicatedBuffer = pDedicatedInfo->buffer;
+ _isDedicated = dedicatedImage || dedicatedBuffer;
+ break;
+ }
+ case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO: {
+ auto* pExpMemInfo = (VkExportMemoryAllocateInfo*)next;
+ handleTypes = pExpMemInfo->handleTypes;
+ break;
+ }
+ default:
+ break;
}
}
+ initExternalMemory(handleTypes); // After setting _isDedicated
+
// "Dedicated" means this memory can only be used for this image or buffer.
if (dedicatedImage) {
#if MVK_MACOS
@@ -316,14 +319,16 @@
}
}
#endif
- _isDedicated = true;
_images.push_back((MVKImage*)dedicatedImage);
return;
}
- // If we can, create a MTLHeap. This should happen before creating the buffer
- // allowing us to map its contents.
- if (!dedicatedImage && !dedicatedBuffer) {
+ if (dedicatedBuffer) {
+ _buffers.push_back((MVKBuffer*)dedicatedBuffer);
+ }
+
+ // If we can, create a MTLHeap. This should happen before creating the buffer, allowing us to map its contents.
+ if ( !_isDedicated ) {
if (!ensureMTLHeap()) {
setConfigurationResult(reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not allocate VkDeviceMemory of size %llu bytes.", _allocationSize));
return;
@@ -334,10 +339,26 @@
if (isMemoryHostCoherent() && !ensureMTLBuffer() ) {
setConfigurationResult(reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not allocate a host-coherent VkDeviceMemory of size %llu bytes. The maximum memory-aligned size of a host-coherent VkDeviceMemory is %llu bytes.", _allocationSize, _device->_pMetalFeatures->maxMTLBufferSize));
}
+}
- if (dedicatedBuffer) {
- _isDedicated = true;
- _buffers.push_back((MVKBuffer*)dedicatedBuffer);
+void MVKDeviceMemory::initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes) {
+ if ( !handleTypes ) { return; }
+
+ if ( !mvkIsOnlyAnyFlagEnabled(handleTypes, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR | VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR) ) {
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "vkAllocateMemory(): Only external memory handle types VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR or VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR are supported."));
+ }
+
+ bool requiresDedicated = false;
+ if (mvkIsAnyFlagEnabled(handleTypes, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR)) {
+ auto& xmProps = _device->getPhysicalDevice()->getExternalBufferProperties(VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR);
+ requiresDedicated = requiresDedicated || mvkIsAnyFlagEnabled(xmProps.externalMemoryFeatures, VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT);
+ }
+ if (mvkIsAnyFlagEnabled(handleTypes, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR)) {
+ auto& xmProps = _device->getPhysicalDevice()->getExternalImageProperties(VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR);
+ requiresDedicated = requiresDedicated || mvkIsAnyFlagEnabled(xmProps.externalMemoryFeatures, VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT);
+ }
+ if (requiresDedicated && !_isDedicated) {
+ setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "vkAllocateMemory(): External memory requires a dedicated VkBuffer or VkImage."));
}
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
index 89e5af0..8bbfa05 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
@@ -130,6 +130,9 @@
/** Binds this resource to the specified offset within the specified memory allocation. */
VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override;
+ /** Binds this resource to the specified offset within the specified memory allocation. */
+ virtual VkResult bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo);
+
/** Applies the specified global memory barrier. */
void applyMemoryBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
@@ -235,6 +238,7 @@
bool validateUseTexelBuffer();
void initSubresources(const VkImageCreateInfo* pCreateInfo);
void initSubresourceLayout(MVKImageSubresource& imgSubRez);
+ void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes);
id<MTLTexture> newMTLTexture();
void releaseMTLTexture();
void releaseIOSurface();
@@ -380,7 +384,7 @@
public:
/** Binds this resource according to the specified bind information. */
- VkResult bindDeviceMemory2(const void* pBindInfo) override;
+ VkResult bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo) override;
#pragma mark Construction
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index 89fb6dd..a90913b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -182,8 +182,9 @@
case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
auto* dedicatedReqs = (VkMemoryDedicatedRequirements*)next;
bool writable = mvkIsAnyFlagEnabled(_usage, VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
- dedicatedReqs->prefersDedicatedAllocation = !_usesTexelBuffer && (writable || !_device->_pMetalFeatures->placementHeaps);
- dedicatedReqs->requiresDedicatedAllocation = VK_FALSE;
+ dedicatedReqs->requiresDedicatedAllocation = _requiresDedicatedMemoryAllocation;
+ dedicatedReqs->prefersDedicatedAllocation = (dedicatedReqs->requiresDedicatedAllocation ||
+ (!_usesTexelBuffer && (writable || !_device->_pMetalFeatures->placementHeaps)));
break;
}
default:
@@ -206,6 +207,10 @@
return _deviceMemory ? _deviceMemory->addImage(this) : VK_SUCCESS;
}
+VkResult MVKImage::bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo) {
+ return bindDeviceMemory((MVKDeviceMemory*)pBindInfo->memory, pBindInfo->memoryOffset);
+}
+
bool MVKImage::validateUseTexelBuffer() {
VkExtent2D blockExt = getPixelFormats()->getBlockTexelSize(_mtlPixelFormat);
bool isUncompressed = blockExt.width == 1 && blockExt.height == 1;
@@ -615,6 +620,18 @@
}
initSubresources(pCreateInfo);
+
+ for (const auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
+ switch (next->sType) {
+ case VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO: {
+ auto* pExtMemInfo = (const VkExternalMemoryImageCreateInfo*)next;
+ initExternalMemory(pExtMemInfo->handleTypes);
+ break;
+ }
+ default:
+ break;
+ }
+ }
}
VkSampleCountFlagBits MVKImage::validateSamples(const VkImageCreateInfo* pCreateInfo, bool isAttachment) {
@@ -784,6 +801,16 @@
layout.depthPitch = bytesPerLayerCurrLevel;
}
+void MVKImage::initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes) {
+ if (mvkIsOnlyAnyFlagEnabled(handleTypes, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR)) {
+ _externalMemoryHandleTypes = handleTypes;
+ auto& xmProps = _device->getPhysicalDevice()->getExternalImageProperties(VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR);
+ _requiresDedicatedMemoryAllocation = _requiresDedicatedMemoryAllocation || mvkIsAnyFlagEnabled(xmProps.externalMemoryFeatures, VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT);
+ } else {
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage(): Only external memory handle type VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR is supported."));
+ }
+}
+
MVKImage::~MVKImage() {
if (_deviceMemory) { _deviceMemory->removeImage(this); }
releaseMTLTexture();
@@ -991,10 +1018,9 @@
#pragma mark -
#pragma mark MVKPeerSwapchainImage
-VkResult MVKPeerSwapchainImage::bindDeviceMemory2(const void* pBindInfo) {
- const auto* imageInfo = (const VkBindImageMemoryInfo*)pBindInfo;
+VkResult MVKPeerSwapchainImage::bindDeviceMemory2(const VkBindImageMemoryInfo* pBindInfo) {
const VkBindImageMemorySwapchainInfoKHR* swapchainInfo = nullptr;
- for (const auto* next = (const VkBaseInStructure*)imageInfo->pNext; next; next = next->pNext) {
+ for (const auto* next = (const VkBaseInStructure*)pBindInfo->pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR:
swapchainInfo = (const VkBindImageMemorySwapchainInfoKHR*)next;
@@ -1002,11 +1028,9 @@
default:
break;
}
- if (swapchainInfo) { break; }
}
- if (!swapchainInfo) {
- return VK_ERROR_OUT_OF_DEVICE_MEMORY;
- }
+ if (!swapchainInfo) { return VK_ERROR_OUT_OF_DEVICE_MEMORY; }
+
_swapchainIndex = swapchainInfo->imageIndex;
return VK_SUCCESS;
}
@@ -1114,17 +1138,14 @@
_image = (MVKImage*)pCreateInfo->image;
_usage = _image->_usage;
- auto* next = (MVKVkAPIStructHeader*)pCreateInfo->pNext;
- while (next) {
- switch ((uint32_t)next->sType) {
+ for (const auto* next = (VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
+ switch (next->sType) {
case VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO: {
auto* pViewUsageInfo = (VkImageViewUsageCreateInfo*)next;
if (!(pViewUsageInfo->usage & ~_usage)) { _usage = pViewUsageInfo->usage; }
- next = (MVKVkAPIStructHeader*)next->pNext;
break;
}
default:
- next = (MVKVkAPIStructHeader*)next->pNext;
break;
}
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
index aa08efa..66d7a6b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
@@ -383,8 +383,7 @@
_hasDebugUtilsMessengers = false;
_debugReportCallbackLayerPrefix = getDriverLayer()->getName();
- MVKVkAPIStructHeader* next = (MVKVkAPIStructHeader*)pCreateInfo->pNext;
- while (next) {
+ for (const auto* next = (VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT:
createDebugReportCallback((VkDebugReportCallbackCreateInfoEXT*)next, nullptr);
@@ -395,7 +394,6 @@
default:
break;
}
- next = (MVKVkAPIStructHeader*)next->pNext;
}
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
index 727f02b..c67ab8c 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKPipeline.mm
@@ -944,15 +944,12 @@
const SPIRVToMSLConversionConfiguration& shaderContext) {
// Collect extension structures
VkPipelineVertexInputDivisorStateCreateInfoEXT* pVertexInputDivisorState = nullptr;
- auto* next = (MVKVkAPIStructHeader*)pVI->pNext;
- while (next) {
+ for (const auto* next = (VkBaseInStructure*)pVI->pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT:
pVertexInputDivisorState = (VkPipelineVertexInputDivisorStateCreateInfoEXT*)next;
- next = (MVKVkAPIStructHeader*)pVertexInputDivisorState->pNext;
break;
default:
- next = (MVKVkAPIStructHeader*)next->pNext;
break;
}
}
@@ -1032,15 +1029,12 @@
VkPipelineTessellationDomainOriginStateCreateInfo* pTessDomainOriginState = nullptr;
if (reflectData.patchKind == spv::ExecutionModeTriangles) {
- auto* next = (MVKVkAPIStructHeader*)pTS->pNext;
- while (next) {
+ for (const auto* next = (VkBaseInStructure*)pTS->pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO:
pTessDomainOriginState = (VkPipelineTessellationDomainOriginStateCreateInfo*)next;
- next = (MVKVkAPIStructHeader*)pTessDomainOriginState->pNext;
break;
default:
- next = (MVKVkAPIStructHeader*)next->pNext;
break;
}
}
@@ -1131,15 +1125,12 @@
VkPipelineTessellationDomainOriginStateCreateInfo* pTessDomainOriginState = nullptr;
if (pCreateInfo->pTessellationState) {
- auto* next = (MVKVkAPIStructHeader*)pCreateInfo->pTessellationState->pNext;
- while (next) {
+ for (const auto* next = (VkBaseInStructure*)pCreateInfo->pTessellationState->pNext; next; next = next->pNext) {
switch (next->sType) {
case VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO:
pTessDomainOriginState = (VkPipelineTessellationDomainOriginStateCreateInfo*)next;
- next = (MVKVkAPIStructHeader*)pTessDomainOriginState->pNext;
break;
default:
- next = (MVKVkAPIStructHeader*)next->pNext;
break;
}
}
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKResource.h b/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
index 3f5c235..fb6f7ee 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKResource.h
@@ -47,9 +47,6 @@
/** Binds this resource to the specified offset within the specified memory allocation. */
virtual VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset);
- /** Binds this resource according to the specified bind information. */
- virtual VkResult bindDeviceMemory2(const void* pBindInfo);
-
/** Returns the device memory underlying this resource. */
inline MVKDeviceMemory* getDeviceMemory() { return _deviceMemory; }
@@ -88,4 +85,6 @@
VkDeviceSize _deviceMemoryOffset = 0;
VkDeviceSize _byteCount = 0;
VkDeviceSize _byteAlignment = 0;
+ VkExternalMemoryHandleTypeFlags _externalMemoryHandleTypes = 0;
+ bool _requiresDedicatedMemoryAllocation = false;
};
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm b/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm
index ab50512..bf106f1 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKResource.mm
@@ -21,18 +21,6 @@
#include "MVKEnvironment.h"
-struct MVKBindDeviceMemoryInfo {
- VkStructureType sType;
- void* pNext;
- union {
- VkBuffer buffer;
- VkImage image;
- };
- VkDeviceMemory memory;
- VkDeviceSize memoryOffset;
-};
-
-
#pragma mark MVKResource
VkResult MVKResource::bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) {
@@ -46,11 +34,6 @@
return VK_SUCCESS;
}
-VkResult MVKResource::bindDeviceMemory2(const void* pBindInfo) {
- auto* mvkBindInfo = (const MVKBindDeviceMemoryInfo*)pBindInfo;
- return bindDeviceMemory((MVKDeviceMemory*)mvkBindInfo->memory, mvkBindInfo->memoryOffset);
-}
-
// Returns whether the specified global memory barrier requires a sync between this
// texture and host memory for the purpose of the host reading texture memory.
bool MVKResource::needsHostReadSync(VkPipelineStageFlags srcStageMask,
diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
index 196860b..f1b4580 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
@@ -39,58 +39,60 @@
#define MVK_EXTENSION_LAST(var, EXT, type) MVK_EXTENSION(var, EXT, type)
#endif
-MVK_EXTENSION(KHR_16bit_storage, KHR_16BIT_STORAGE, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_8bit_storage, KHR_8BIT_STORAGE, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_bind_memory2, KHR_BIND_MEMORY_2, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_dedicated_allocation, KHR_DEDICATED_ALLOCATION, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_device_group, KHR_DEVICE_GROUP, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_device_group_creation, KHR_DEVICE_GROUP_CREATION, MVK_EXTENSION_INSTANCE)
-MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, MVK_EXTENSION_INSTANCE)
-MVK_EXTENSION(KHR_get_surface_capabilities2, KHR_GET_SURFACE_CAPABILITIES_2, MVK_EXTENSION_INSTANCE)
-MVK_EXTENSION(KHR_image_format_list, KHR_IMAGE_FORMAT_LIST, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_maintenance1, KHR_MAINTENANCE1, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_maintenance2, KHR_MAINTENANCE2, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_maintenance3, KHR_MAINTENANCE3, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_push_descriptor, KHR_PUSH_DESCRIPTOR, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_relaxed_block_layout, KHR_RELAXED_BLOCK_LAYOUT, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_sampler_mirror_clamp_to_edge, KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_shader_float16_int8, KHR_SHADER_FLOAT16_INT8, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_storage_buffer_storage_class, KHR_STORAGE_BUFFER_STORAGE_CLASS, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_surface, KHR_SURFACE, MVK_EXTENSION_INSTANCE)
-MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_swapchain_mutable_format, KHR_SWAPCHAIN_MUTABLE_FORMAT, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_uniform_buffer_standard_layout, KHR_UNIFORM_BUFFER_STANDARD_LAYOUT, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_debug_marker, EXT_DEBUG_MARKER, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT, MVK_EXTENSION_INSTANCE)
-MVK_EXTENSION(EXT_debug_utils, EXT_DEBUG_UTILS, MVK_EXTENSION_INSTANCE)
-MVK_EXTENSION(EXT_fragment_shader_interlock, EXT_FRAGMENT_SHADER_INTERLOCK, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_hdr_metadata, EXT_HDR_METADATA, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_inline_uniform_block, EXT_INLINE_UNIFORM_BLOCK, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE, MVK_EXTENSION_INSTANCE)
-MVK_EXTENSION(EXT_post_depth_coverage, EXT_POST_DEPTH_COVERAGE, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_scalar_block_layout, EXT_SCALAR_BLOCK_LAYOUT, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_swapchain_colorspace, EXT_SWAPCHAIN_COLOR_SPACE, MVK_EXTENSION_INSTANCE)
-MVK_EXTENSION(EXT_texel_buffer_alignment, EXT_TEXEL_BUFFER_ALIGNMENT, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(MVK_ios_surface, MVK_IOS_SURFACE, MVK_EXTENSION_INSTANCE)
-MVK_EXTENSION(MVK_macos_surface, MVK_MACOS_SURFACE, MVK_EXTENSION_INSTANCE)
-MVK_EXTENSION(MVK_moltenvk, MVK_MOLTENVK, MVK_EXTENSION_INSTANCE)
-MVK_EXTENSION(AMD_gpu_shader_half_float, AMD_GPU_SHADER_HALF_FLOAT, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(AMD_negative_viewport_height, AMD_NEGATIVE_VIEWPORT_HEIGHT, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(AMD_shader_image_load_store_lod, AMD_SHADER_IMAGE_LOAD_STORE_LOD, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(AMD_shader_trinary_minmax, AMD_SHADER_TRINARY_MINMAX, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(IMG_format_pvrtc, IMG_FORMAT_PVRTC, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION(INTEL_shader_integer_functions2, INTEL_SHADER_INTEGER_FUNCTIONS_2, MVK_EXTENSION_DEVICE)
-MVK_EXTENSION_LAST(NV_glsl_shader, NV_GLSL_SHADER, MVK_EXTENSION_DEVICE)
+MVK_EXTENSION(KHR_16bit_storage, KHR_16BIT_STORAGE, DEVICE)
+MVK_EXTENSION(KHR_8bit_storage, KHR_8BIT_STORAGE, DEVICE)
+MVK_EXTENSION(KHR_bind_memory2, KHR_BIND_MEMORY_2, DEVICE)
+MVK_EXTENSION(KHR_dedicated_allocation, KHR_DEDICATED_ALLOCATION, DEVICE)
+MVK_EXTENSION(KHR_descriptor_update_template, KHR_DESCRIPTOR_UPDATE_TEMPLATE, DEVICE)
+MVK_EXTENSION(KHR_device_group, KHR_DEVICE_GROUP, DEVICE)
+MVK_EXTENSION(KHR_device_group_creation, KHR_DEVICE_GROUP_CREATION, INSTANCE)
+MVK_EXTENSION(KHR_external_memory, KHR_EXTERNAL_MEMORY, DEVICE)
+MVK_EXTENSION(KHR_external_memory_capabilities, KHR_EXTERNAL_MEMORY_CAPABILITIES, INSTANCE)
+MVK_EXTENSION(KHR_get_memory_requirements2, KHR_GET_MEMORY_REQUIREMENTS_2, DEVICE)
+MVK_EXTENSION(KHR_get_physical_device_properties2, KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2, INSTANCE)
+MVK_EXTENSION(KHR_get_surface_capabilities2, KHR_GET_SURFACE_CAPABILITIES_2, INSTANCE)
+MVK_EXTENSION(KHR_image_format_list, KHR_IMAGE_FORMAT_LIST, DEVICE)
+MVK_EXTENSION(KHR_maintenance1, KHR_MAINTENANCE1, DEVICE)
+MVK_EXTENSION(KHR_maintenance2, KHR_MAINTENANCE2, DEVICE)
+MVK_EXTENSION(KHR_maintenance3, KHR_MAINTENANCE3, DEVICE)
+MVK_EXTENSION(KHR_push_descriptor, KHR_PUSH_DESCRIPTOR, DEVICE)
+MVK_EXTENSION(KHR_relaxed_block_layout, KHR_RELAXED_BLOCK_LAYOUT, DEVICE)
+MVK_EXTENSION(KHR_sampler_mirror_clamp_to_edge, KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE, DEVICE)
+MVK_EXTENSION(KHR_shader_draw_parameters, KHR_SHADER_DRAW_PARAMETERS, DEVICE)
+MVK_EXTENSION(KHR_shader_float16_int8, KHR_SHADER_FLOAT16_INT8, DEVICE)
+MVK_EXTENSION(KHR_storage_buffer_storage_class, KHR_STORAGE_BUFFER_STORAGE_CLASS, DEVICE)
+MVK_EXTENSION(KHR_surface, KHR_SURFACE, INSTANCE)
+MVK_EXTENSION(KHR_swapchain, KHR_SWAPCHAIN, DEVICE)
+MVK_EXTENSION(KHR_swapchain_mutable_format, KHR_SWAPCHAIN_MUTABLE_FORMAT, DEVICE)
+MVK_EXTENSION(KHR_uniform_buffer_standard_layout, KHR_UNIFORM_BUFFER_STANDARD_LAYOUT, DEVICE)
+MVK_EXTENSION(KHR_variable_pointers, KHR_VARIABLE_POINTERS, DEVICE)
+MVK_EXTENSION(EXT_debug_marker, EXT_DEBUG_MARKER, DEVICE)
+MVK_EXTENSION(EXT_debug_report, EXT_DEBUG_REPORT, INSTANCE)
+MVK_EXTENSION(EXT_debug_utils, EXT_DEBUG_UTILS, INSTANCE)
+MVK_EXTENSION(EXT_fragment_shader_interlock, EXT_FRAGMENT_SHADER_INTERLOCK, DEVICE)
+MVK_EXTENSION(EXT_hdr_metadata, EXT_HDR_METADATA, DEVICE)
+MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET, DEVICE)
+MVK_EXTENSION(EXT_inline_uniform_block, EXT_INLINE_UNIFORM_BLOCK, DEVICE)
+MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET, DEVICE)
+MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE, INSTANCE)
+MVK_EXTENSION(EXT_post_depth_coverage, EXT_POST_DEPTH_COVERAGE, DEVICE)
+MVK_EXTENSION(EXT_scalar_block_layout, EXT_SCALAR_BLOCK_LAYOUT, DEVICE)
+MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT, DEVICE)
+MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER, DEVICE)
+MVK_EXTENSION(EXT_swapchain_colorspace, EXT_SWAPCHAIN_COLOR_SPACE, INSTANCE)
+MVK_EXTENSION(EXT_texel_buffer_alignment, EXT_TEXEL_BUFFER_ALIGNMENT, DEVICE)
+MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR, DEVICE)
+MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET, DEVICE)
+MVK_EXTENSION(MVK_ios_surface, MVK_IOS_SURFACE, INSTANCE)
+MVK_EXTENSION(MVK_macos_surface, MVK_MACOS_SURFACE, INSTANCE)
+MVK_EXTENSION(MVK_moltenvk, MVK_MOLTENVK, INSTANCE)
+MVK_EXTENSION(AMD_gpu_shader_half_float, AMD_GPU_SHADER_HALF_FLOAT, DEVICE)
+MVK_EXTENSION(AMD_negative_viewport_height, AMD_NEGATIVE_VIEWPORT_HEIGHT, DEVICE)
+MVK_EXTENSION(AMD_shader_image_load_store_lod, AMD_SHADER_IMAGE_LOAD_STORE_LOD, DEVICE)
+MVK_EXTENSION(AMD_shader_trinary_minmax, AMD_SHADER_TRINARY_MINMAX, DEVICE)
+MVK_EXTENSION(IMG_format_pvrtc, IMG_FORMAT_PVRTC, DEVICE)
+MVK_EXTENSION(INTEL_shader_integer_functions2, INTEL_SHADER_INTEGER_FUNCTIONS_2, DEVICE)
+MVK_EXTENSION_LAST(NV_glsl_shader, NV_GLSL_SHADER, DEVICE)
#undef MVK_EXTENSION
#undef MVK_EXTENSION_LAST
diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.mm b/MoltenVK/MoltenVK/Layers/MVKExtensions.mm
index 4d15962..80c221a 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.mm
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.mm
@@ -47,54 +47,30 @@
// Returns whether the specified properties are valid for this platform
static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) {
#if MVK_MACOS
- if (pProperties == &kVkExtProps_EXT_HDR_METADATA) {
- return mvkOSVersionIsAtLeast(10.15);
- }
- if (pProperties == &kVkExtProps_EXT_FRAGMENT_SHADER_INTERLOCK) {
- return mvkOSVersionIsAtLeast(10.13);
- }
- if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
- return mvkOSVersionIsAtLeast(10.13);
- }
- if (pProperties == &kVkExtProps_EXT_POST_DEPTH_COVERAGE) { return false; }
- if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) {
- return mvkOSVersionIsAtLeast(10.14);
- }
- if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) {
- return mvkOSVersionIsAtLeast(10.13);
- }
if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; }
- if (pProperties == &kVkExtProps_AMD_SHADER_IMAGE_LOAD_STORE_LOD) { return false; }
- if (pProperties == &kVkExtProps_AMD_SHADER_TRINARY_MINMAX) {
- return mvkOSVersionIsAtLeast(10.14);
- }
if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; }
+ if (pProperties == &kVkExtProps_EXT_POST_DEPTH_COVERAGE) { return false; }
+ if (pProperties == &kVkExtProps_AMD_SHADER_IMAGE_LOAD_STORE_LOD) { return false; }
+
+ if (pProperties == &kVkExtProps_EXT_HDR_METADATA) { return mvkOSVersionIsAtLeast(10.15); }
+ if (pProperties == &kVkExtProps_EXT_FRAGMENT_SHADER_INTERLOCK) { return mvkOSVersionIsAtLeast(10.13); }
+ if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) { return mvkOSVersionIsAtLeast(10.13); }
+ if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) { return mvkOSVersionIsAtLeast(10.14); }
+ if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) { return mvkOSVersionIsAtLeast(10.13); }
+ if (pProperties == &kVkExtProps_AMD_SHADER_TRINARY_MINMAX) { return mvkOSVersionIsAtLeast(10.14); }
#endif
#if MVK_IOS
+ if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; }
if (pProperties == &kVkExtProps_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE) { return false; }
if (pProperties == &kVkExtProps_EXT_HDR_METADATA) { return false; }
- if (pProperties == &kVkExtProps_EXT_FRAGMENT_SHADER_INTERLOCK) {
- return mvkOSVersionIsAtLeast(11.0);
- }
- if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
- return mvkOSVersionIsAtLeast(11.0);
- }
- if (pProperties == &kVkExtProps_EXT_POST_DEPTH_COVERAGE) {
- return mvkOSVersionIsAtLeast(11.0);
- }
- if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) {
- return mvkOSVersionIsAtLeast(12.0);
- }
- if (pProperties == &kVkExtProps_EXT_SWAPCHAIN_COLOR_SPACE) {
- return mvkOSVersionIsAtLeast(9.0);
- }
- if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) {
- return mvkOSVersionIsAtLeast(11.0);
- }
- if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; }
- if (pProperties == &kVkExtProps_AMD_SHADER_TRINARY_MINMAX) {
- return mvkOSVersionIsAtLeast(12.0);
- }
+
+ if (pProperties == &kVkExtProps_EXT_FRAGMENT_SHADER_INTERLOCK) { return mvkOSVersionIsAtLeast(11.0); }
+ if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) { return mvkOSVersionIsAtLeast(11.0); }
+ if (pProperties == &kVkExtProps_EXT_POST_DEPTH_COVERAGE) { return mvkOSVersionIsAtLeast(11.0); }
+ if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) { return mvkOSVersionIsAtLeast(12.0); }
+ if (pProperties == &kVkExtProps_EXT_SWAPCHAIN_COLOR_SPACE) { return mvkOSVersionIsAtLeast(9.0); }
+ if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) { return mvkOSVersionIsAtLeast(11.0); }
+ if (pProperties == &kVkExtProps_AMD_SHADER_TRINARY_MINMAX) { return mvkOSVersionIsAtLeast(12.0); }
#endif
return true;
@@ -127,17 +103,19 @@
#include "MVKExtensions.def"
}
+#define MVK_ENSURE_EXTENSION_TYPE(var, EXT, type) vk_ ##var.enabled = vk_ ##var.enabled && MVK_EXTENSION_ ##type;
+
void MVKExtensionList::disableAllButEnabledInstanceExtensions() {
-#define MVK_EXTENSION_INSTANCE true
-#define MVK_EXTENSION_DEVICE false
-#define MVK_EXTENSION(var, EXT, type) vk_ ##var.enabled = type && vk_ ##var.enabled;
+#define MVK_EXTENSION_INSTANCE true
+#define MVK_EXTENSION_DEVICE false
+#define MVK_EXTENSION(var, EXT, type) MVK_ENSURE_EXTENSION_TYPE(var, EXT, type)
#include "MVKExtensions.def"
}
void MVKExtensionList::disableAllButEnabledDeviceExtensions() {
-#define MVK_EXTENSION_INSTANCE false
-#define MVK_EXTENSION_DEVICE true
-#define MVK_EXTENSION(var, EXT, type) vk_ ##var.enabled = type && vk_ ##var.enabled;
+#define MVK_EXTENSION_INSTANCE false
+#define MVK_EXTENSION_DEVICE true
+#define MVK_EXTENSION(var, EXT, type) MVK_ENSURE_EXTENSION_TYPE(var, EXT, type)
#include "MVKExtensions.def"
}
diff --git a/MoltenVK/MoltenVK/Utility/MVKFoundation.h b/MoltenVK/MoltenVK/Utility/MVKFoundation.h
index c256bf0..c2c17f3 100644
--- a/MoltenVK/MoltenVK/Utility/MVKFoundation.h
+++ b/MoltenVK/MoltenVK/Utility/MVKFoundation.h
@@ -55,12 +55,6 @@
/** A representation of the value of 1.0 as a 16-bit half-float. */
#define kHalfFloat1 0x3C00
-/** Common header for many standard Vulkan API structures. */
-typedef struct {
- VkStructureType sType;
- const void* pNext;
-} MVKVkAPIStructHeader;
-
#pragma mark -
#pragma mark Vertex content structures
diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
index 5b28ae3..51990e8 100644
--- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm
+++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
@@ -230,7 +230,7 @@
MVKTraceVulkanCallStart();
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
- mvkPD->getPhysicalDeviceMemoryProperties(pMemoryProperties);
+ mvkPD->getMemoryProperties(pMemoryProperties);
MVKTraceVulkanCallEnd();
}
@@ -2113,7 +2113,7 @@
MVKTraceVulkanCallStart();
MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
- mvkPD->getPhysicalDeviceMemoryProperties(pMemoryProperties);
+ mvkPD->getMemoryProperties(pMemoryProperties);
MVKTraceVulkanCallEnd();
}
@@ -2665,6 +2665,21 @@
#pragma mark -
+#pragma mark VK_KHR_external_memory_capabilities extension
+
+MVK_PUBLIC_SYMBOL void vkGetPhysicalDeviceExternalBufferPropertiesKHR(
+ VkPhysicalDevice physicalDevice,
+ const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo,
+ VkExternalBufferProperties* pExternalBufferProperties) {
+
+ MVKTraceVulkanCallStart();
+ MVKPhysicalDevice* mvkPD = MVKPhysicalDevice::getMVKPhysicalDevice(physicalDevice);
+ mvkPD->getExternalBufferProperties(pExternalBufferInfo, pExternalBufferProperties);
+ MVKTraceVulkanCallEnd();
+}
+
+
+#pragma mark -
#pragma mark VK_EXT_metal_surface extension
MVK_PUBLIC_SYMBOL VkResult vkCreateMetalSurfaceEXT(