diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 2ddaa6fb..2b7845ca 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -20,7 +20,10 @@ MoltenVK 1.0.42 Released TBD - Add support for extensions: - - `VK_KHR_external_memory_capabilities` + - `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. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h index d3cbb054..60a2ac7b 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.h @@ -92,6 +92,7 @@ protected: 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 ed74605c..4ce1465f 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKBuffer.mm @@ -66,8 +66,8 @@ VkResult MVKBuffer::getMemoryRequirements(const void*, VkMemoryRequirements2* pM 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: @@ -192,6 +192,28 @@ id MVKBuffer::getMTLBuffer() { 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/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index 4bcc63b5..f5e1f4dd 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -283,6 +283,12 @@ public: /** 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 @@ -337,6 +343,7 @@ protected: uint64_t getVRAMSize(); uint64_t getRecommendedMaxWorkingSetSize(); uint64_t getCurrentAllocatedSize(); + void initExternalMemoryProperties(); void initExtensions(); MVKVector& getQueueFamilies(); void initPipelineCacheUUID(); @@ -344,9 +351,6 @@ protected: uint64_t getSpirvCrossRevision(); bool getImageViewIsSupported(const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo); void populate(VkPhysicalDeviceIDProperties* pDevIdProps); - void populate(VkExternalMemoryProperties& xmProps, - VkExternalMemoryHandleTypeFlagBits handleType, - VkExternalMemoryHandleTypeFlagBits supportedHandleType); void logGPUInfo(); id _mtlDevice; @@ -364,6 +368,8 @@ protected: 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 79a3db4e..00b8b424 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -419,10 +419,7 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(const VkPhysicalDeviceImage for (auto* nextProps = (VkBaseOutStructure*)pImageFormatProperties->pNext; nextProps; nextProps = nextProps->pNext) { if (nextProps->sType == VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES) { auto* pExtImgFmtProps = (VkExternalImageFormatProperties*)nextProps; - - // TODO: This is an inoperable placeholder until VK_KHR_external_memory_metal is ratified and implemented - const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM; - populate(pExtImgFmtProps->externalMemoryProperties, pExtImgFmtInfo->handleType, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLTEXTURE_BIT_KHR); + pExtImgFmtProps->externalMemoryProperties = getExternalImageProperties(pExtImgFmtInfo->handleType); } } break; @@ -482,24 +479,22 @@ bool MVKPhysicalDevice::getImageViewIsSupported(const VkPhysicalDeviceImageForma void MVKPhysicalDevice::getExternalBufferProperties(const VkPhysicalDeviceExternalBufferInfo* pExternalBufferInfo, VkExternalBufferProperties* pExternalBufferProperties) { - - // TODO: This is an inoperable placeholder until VK_KHR_external_memory_metal is ratified and implemented - const VkExternalMemoryHandleTypeFlagBits VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR = VK_EXTERNAL_MEMORY_HANDLE_TYPE_FLAG_BITS_MAX_ENUM; - populate(pExternalBufferProperties->externalMemoryProperties, pExternalBufferInfo->handleType, VK_EXTERNAL_MEMORY_HANDLE_TYPE_MTLBUFFER_BIT_KHR); + pExternalBufferProperties->externalMemoryProperties = getExternalBufferProperties(pExternalBufferInfo->handleType); } -// If the handleType is the supported handle type, populates xmProps accordingly, otherwise xmProps is cleared. -void MVKPhysicalDevice::populate(VkExternalMemoryProperties& xmProps, - VkExternalMemoryHandleTypeFlagBits handleType, - VkExternalMemoryHandleTypeFlagBits supportedHandleType) { - if (handleType == supportedHandleType) { - xmProps.externalMemoryFeatures = (VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT | - VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT | - VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT); - xmProps.exportFromImportedHandleTypes = supportedHandleType; - xmProps.compatibleHandleTypes = supportedHandleType; - } else { - mvkClear(&xmProps); +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; } } @@ -847,8 +842,9 @@ MVKPhysicalDevice::MVKPhysicalDevice(MVKInstance* mvkInstance, id mtl initMetalFeatures(); // Call first. initFeatures(); // Call second. initProperties(); // Call third. - initMemoryProperties(); initExtensions(); + initMemoryProperties(); + initExternalMemoryProperties(); logGPUInfo(); } @@ -1973,6 +1969,23 @@ uint64_t MVKPhysicalDevice::getCurrentAllocatedSize() { #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(); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.h index 5fc2cb2a..0a51525a 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 @@ protected: bool ensureHostMemory(); void freeHostMemory(); MVKResource* getDedicatedResource(); + void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes); MVKVectorInline _buffers; MVKVectorInline _images; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm index 714a8f95..efcce8db 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm @@ -266,10 +266,7 @@ void MVKDeviceMemory::freeHostMemory() { 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 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device, 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 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device, } } #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 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device, 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 89e5af02..6772d56b 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h @@ -235,6 +235,7 @@ protected: bool validateUseTexelBuffer(); void initSubresources(const VkImageCreateInfo* pCreateInfo); void initSubresourceLayout(MVKImageSubresource& imgSubRez); + void initExternalMemory(VkExternalMemoryHandleTypeFlags handleTypes); id newMTLTexture(); void releaseMTLTexture(); void releaseIOSurface(); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 0fdd9417..0b378d71 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -182,8 +182,9 @@ VkResult MVKImage::getMemoryRequirements(const void*, VkMemoryRequirements2* pMe 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: @@ -615,6 +616,18 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV } 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 +797,16 @@ void MVKImage::initSubresourceLayout(MVKImageSubresource& imgSubRez) { 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(); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKResource.h b/MoltenVK/MoltenVK/GPUObjects/MVKResource.h index 3f5c235f..766b7691 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKResource.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKResource.h @@ -88,4 +88,6 @@ protected: VkDeviceSize _deviceMemoryOffset = 0; VkDeviceSize _byteCount = 0; VkDeviceSize _byteAlignment = 0; + VkExternalMemoryHandleTypeFlags _externalMemoryHandleTypes = 0; + bool _requiresDedicatedMemoryAllocation = false; }; diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def index 337b802c..f1b4580a 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def @@ -46,6 +46,7 @@ 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)