From 2b05b959747a4610ca31153cbd0d5a5577e0d7c1 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Sat, 11 Jun 2022 20:10:06 -0400 Subject: [PATCH] Add support for VK_EXT_metal_objects extension. Update Vulkan-Headers version to include new VK_EXT_metal_objects extension. Update MoltenVK version to 1.1.11. Update What's New document. --- Docs/MoltenVK_Runtime_UserGuide.md | 1 + Docs/Whats_New.md | 11 +++ .../Vulkan-Headers_repo_revision | 2 +- MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h | 2 +- MoltenVK/MoltenVK/GPUObjects/MVKDevice.h | 3 + MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 94 ++++++++++++++++++- .../MoltenVK/GPUObjects/MVKDeviceMemory.mm | 22 ++++- MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 36 +++++++ MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm | 1 + MoltenVK/MoltenVK/GPUObjects/MVKSync.h | 47 ++++++++-- MoltenVK/MoltenVK/GPUObjects/MVKSync.mm | 57 ++++++++--- MoltenVK/MoltenVK/Layers/MVKExtensions.def | 1 + MoltenVK/MoltenVK/Vulkan/vulkan.mm | 15 +++ 13 files changed, 265 insertions(+), 27 deletions(-) diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md index 23c4bf69..b7f572d7 100644 --- a/Docs/MoltenVK_Runtime_UserGuide.md +++ b/Docs/MoltenVK_Runtime_UserGuide.md @@ -306,6 +306,7 @@ In addition to core *Vulkan* functionality, **MoltenVK** also supports the foll - `VK_EXT_image_robustness` - `VK_EXT_inline_uniform_block` - `VK_EXT_memory_budget` *(requires Metal 2.0)* +- `VK_EXT_metal_objects` - `VK_EXT_metal_surface` - `VK_EXT_post_depth_coverage` *(iOS and macOS, requires family 4 (A11) or better Apple GPU)* - `VK_EXT_private_data ` diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 97669041..dfdbc271 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -13,6 +13,17 @@ Copyright (c) 2015-2022 [The Brenwill Workshop Ltd.](http://www.brenwill.com) +MoltenVK 1.1.11 +-------------- + +Released TBD + +- Add support for extensions: + - `VK_EXT_metal_objects` +- Reducing redundant state changes to improve commend encoding performance. + + + MoltenVK 1.1.10 -------------- diff --git a/ExternalRevisions/Vulkan-Headers_repo_revision b/ExternalRevisions/Vulkan-Headers_repo_revision index b907983a..1245433c 100644 --- a/ExternalRevisions/Vulkan-Headers_repo_revision +++ b/ExternalRevisions/Vulkan-Headers_repo_revision @@ -1 +1 @@ -3ef4c97fd6ea001d75a8e9da408ee473c180e456 +ec9b96aae53e152f6812e66fa43757c1256369a0 diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h index 858f0607..4a99c3dd 100644 --- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h +++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h @@ -50,7 +50,7 @@ typedef unsigned long MTLLanguageVersion; */ #define MVK_VERSION_MAJOR 1 #define MVK_VERSION_MINOR 1 -#define MVK_VERSION_PATCH 10 +#define MVK_VERSION_PATCH 11 #define MVK_MAKE_VERSION(major, minor, patch) (((major) * 10000) + ((minor) * 100) + (patch)) #define MVK_VERSION MVK_MAKE_VERSION(MVK_VERSION_MAJOR, MVK_VERSION_MINOR, MVK_VERSION_PATCH) diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index 63b6e189..9989a698 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -765,6 +765,9 @@ public: /** Returns whether this instance is currently automatically capturing a GPU trace. */ inline bool isCurrentlyAutoGPUCapturing() { return _isCurrentlyAutoGPUCapturing; } + /** Returns the Metal objects underpinning the Vulkan objects indicated in the pNext chain of pMetalObjectsInfo. */ + void getMetalObjects(VkExportMetalObjectsInfoEXT* pMetalObjectsInfo); + #pragma mark Properties directly accessible diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index f724e7a0..370807ed 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -3333,20 +3333,31 @@ void MVKDevice::destroyFence(MVKFence* mvkFence, MVKSemaphore* MVKDevice::createSemaphore(const VkSemaphoreCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator) { const VkSemaphoreTypeCreateInfo* pTypeCreateInfo = nullptr; + const VkExportMetalObjectCreateInfoEXT* pExportInfo = nullptr; + const VkImportMetalSharedEventInfoEXT* pImportInfo = nullptr; for (auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) { switch (next->sType) { case VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO: pTypeCreateInfo = (VkSemaphoreTypeCreateInfo*)next; break; + case VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT: + pExportInfo = (VkExportMetalObjectCreateInfoEXT*)next; + break; + case VK_STRUCTURE_TYPE_IMPORT_METAL_SHARED_EVENT_INFO_EXT: + pImportInfo = (VkImportMetalSharedEventInfoEXT*)next; + break; default: break; } } - if (pTypeCreateInfo && pTypeCreateInfo->semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE) { + + if ((pTypeCreateInfo && pTypeCreateInfo->semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE) || + (pExportInfo && pExportInfo->exportObjectType == VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT) || + pImportInfo) { if (_pMetalFeatures->events) { - return new MVKTimelineSemaphoreMTLEvent(this, pCreateInfo, pTypeCreateInfo); + return new MVKTimelineSemaphoreMTLEvent(this, pCreateInfo, pTypeCreateInfo, pExportInfo, pImportInfo); } else { - return new MVKTimelineSemaphoreEmulated(this, pCreateInfo, pTypeCreateInfo); + return new MVKTimelineSemaphoreEmulated(this, pCreateInfo, pTypeCreateInfo, pExportInfo, pImportInfo); } } else { switch (_vkSemaphoreStyle) { @@ -3364,10 +3375,25 @@ void MVKDevice::destroySemaphore(MVKSemaphore* mvkSem4, MVKEvent* MVKDevice::createEvent(const VkEventCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator) { + const VkExportMetalObjectCreateInfoEXT* pExportInfo = nullptr; + const VkImportMetalSharedEventInfoEXT* pImportInfo = nullptr; + for (auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) { + switch (next->sType) { + case VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT: + pExportInfo = (VkExportMetalObjectCreateInfoEXT*)next; + break; + case VK_STRUCTURE_TYPE_IMPORT_METAL_SHARED_EVENT_INFO_EXT: + pImportInfo = (VkImportMetalSharedEventInfoEXT*)next; + break; + default: + break; + } + } + if (_pMetalFeatures->events) { - return new MVKEventNative(this, pCreateInfo); + return new MVKEventNative(this, pCreateInfo, pExportInfo, pImportInfo); } else { - return new MVKEventEmulated(this, pCreateInfo); + return new MVKEventEmulated(this, pCreateInfo, pExportInfo, pImportInfo); } } @@ -3982,6 +4008,64 @@ void MVKDevice::stopAutoGPUCapture(MVKConfigAutoGPUCaptureScope autoGPUCaptureSc } } +void MVKDevice::getMetalObjects(VkExportMetalObjectsInfoEXT* pMetalObjectsInfo) { + for (auto* next = (VkBaseOutStructure*)pMetalObjectsInfo->pNext; next; next = next->pNext) { + switch (next->sType) { + case VK_STRUCTURE_TYPE_EXPORT_METAL_DEVICE_INFO_EXT: { + auto* pDvcInfo = (VkExportMetalDeviceInfoEXT*)next; + pDvcInfo->mtlDevice = getMTLDevice(); + break; + } + case VK_STRUCTURE_TYPE_EXPORT_METAL_COMMAND_QUEUE_INFO_EXT: { + auto* pQInfo = (VkExportMetalCommandQueueInfoEXT*)next; + MVKQueue* mvkQ = MVKQueue::getMVKQueue(pQInfo->queue); + pQInfo->mtlCommandQueue = mvkQ->getMTLCommandQueue(); + break; + } + case VK_STRUCTURE_TYPE_EXPORT_METAL_BUFFER_INFO_EXT: { + auto* pBuffInfo = (VkExportMetalBufferInfoEXT*)next; + auto* mvkDevMem = (MVKDeviceMemory*)pBuffInfo->memory; + pBuffInfo->mtlBuffer = mvkDevMem->getMTLBuffer(); + break; + } + case VK_STRUCTURE_TYPE_EXPORT_METAL_TEXTURE_INFO_EXT: { + auto* pImgInfo = (VkExportMetalTextureInfoEXT*)next; + uint8_t planeIndex = MVKImage::getPlaneFromVkImageAspectFlags(pImgInfo->plane); + auto* mvkImg = (MVKImage*)pImgInfo->image; + auto* mvkImgView = (MVKImageView*)pImgInfo->imageView; + auto* mvkBuffView = (MVKBufferView*)pImgInfo->bufferView; + if (mvkImg) { + pImgInfo->mtlTexture = mvkImg->getMTLTexture(planeIndex); + } else if (mvkImgView) { + pImgInfo->mtlTexture = mvkImgView->getMTLTexture(planeIndex); + } else { + pImgInfo->mtlTexture = mvkBuffView->getMTLTexture(); + } + break; + } + case VK_STRUCTURE_TYPE_EXPORT_METAL_IO_SURFACE_INFO_EXT: { + auto* pIOSurfInfo = (VkExportMetalIOSurfaceInfoEXT*)next; + auto* mvkImg = (MVKImage*)pIOSurfInfo->image; + pIOSurfInfo->ioSurface = mvkImg->getIOSurface(); + break; + } + case VK_STRUCTURE_TYPE_EXPORT_METAL_SHARED_EVENT_INFO_EXT: { + auto* pShEvtInfo = (VkExportMetalSharedEventInfoEXT*)next; + auto* mvkSem4 = (MVKSemaphore*)pShEvtInfo->semaphore; + auto* mvkEvt = (MVKEvent*)pShEvtInfo->event; + if (mvkSem4) { + pShEvtInfo->mtlSharedEvent = mvkSem4->getMTLSharedEvent(); + } else if (mvkEvt) { + pShEvtInfo->mtlSharedEvent = mvkEvt->getMTLSharedEvent(); + } + break; + } + default: + break; + } + } +} + #pragma mark Construction diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm index 229b0ab7..a397e3ce 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm @@ -283,6 +283,7 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device, _allocationSize = pAllocateInfo->allocationSize; + bool willExportMTLBuffer = false; VkImage dedicatedImage = VK_NULL_HANDLE; VkBuffer dedicatedBuffer = VK_NULL_HANDLE; VkExternalMemoryHandleTypeFlags handleTypes = 0; @@ -300,6 +301,22 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device, handleTypes = pExpMemInfo->handleTypes; break; } + case VK_STRUCTURE_TYPE_IMPORT_METAL_BUFFER_INFO_EXT: { + // Setting Metal objects directly will override Vulkan settings. + // It is responsibility of app to ensure these are consistent. Not doing so results in undefined behavior. + const auto* pMTLBuffInfo = (VkImportMetalBufferInfoEXT*)next; + [_mtlBuffer release]; // guard against dups + _mtlBuffer = [pMTLBuffInfo->mtlBuffer retain]; // retained + _mtlStorageMode = _mtlBuffer.storageMode; + _mtlCPUCacheMode = _mtlBuffer.cpuCacheMode; + _allocationSize = _mtlBuffer.length; + break; + } + case VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT: { + const auto* pExportInfo = (VkExportMetalObjectCreateInfoEXT*)next; + willExportMTLBuffer = pExportInfo->exportObjectType == VK_EXPORT_METAL_OBJECT_TYPE_METAL_BUFFER_BIT_EXT; + break; + } default: break; } @@ -344,8 +361,9 @@ MVKDeviceMemory::MVKDeviceMemory(MVKDevice* device, } // If memory needs to be coherent it must reside in an MTLBuffer, since an open-ended map() must work. - 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)); + // Or if a MTLBuffer will be exported, ensure it exists. + if ((isMemoryHostCoherent() || willExportMTLBuffer) && !ensureMTLBuffer() ) { + setConfigurationResult(reportError(VK_ERROR_OUT_OF_DEVICE_MEMORY, "Could not allocate a host-coherent or exportable VkDeviceMemory of size %llu bytes. The maximum memory-aligned size of a host-coherent VkDeviceMemory is %llu bytes.", _allocationSize, _device->_pMetalFeatures->maxMTLBufferSize)); } } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 379ed9d2..8340095d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -712,6 +712,10 @@ id MVKImage::getMTLTexture(uint8_t planeIndex, MTLPixelFormat mtlPix VkResult MVKImage::setMTLTexture(uint8_t planeIndex, id mtlTexture) { lock_guard lock(_lock); + if (planeIndex >= _planes.size()) { return reportError(VK_ERROR_INITIALIZATION_FAILED, "Plane index is out of bounds. Attempted to set MTLTexture at plane index %d in VkImage that has %zu planes.", planeIndex, _planes.size()); } + + if (_planes[planeIndex]->_mtlTexture == mtlTexture) { return VK_SUCCESS; } + releaseIOSurface(); _planes[planeIndex]->releaseMTLTexture(); _planes[planeIndex]->_mtlTexture = [mtlTexture retain]; // retained @@ -747,6 +751,9 @@ IOSurfaceRef MVKImage::getIOSurface() { return _ioSurface; } VkResult MVKImage::useIOSurface(IOSurfaceRef ioSurface) { lock_guard lock(_lock); + // Don't recreate existing. But special case of incoming nil if already nil means create a new IOSurface. + if (ioSurface && _ioSurface == ioSurface) { return VK_SUCCESS; } + if (!_device->_pMetalFeatures->ioSurfaces) { return reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkUseIOSurfaceMVK() : IOSurfaces are not supported on this platform."); } #if MVK_SUPPORT_IOSURFACE_BOOL @@ -986,6 +993,35 @@ MVKImage::MVKImage(MVKDevice* device, const VkImageCreateInfo* pCreateInfo) : MV if (pExtMemInfo) { initExternalMemory(pExtMemInfo->handleTypes); } + // Setting Metal objects directly will override Vulkan settings. + // It is responsibility of app to ensure these are consistent. Not doing so results in undefined behavior. + const VkExportMetalObjectCreateInfoEXT* pExportInfo = nullptr; + for (const auto* next = (const VkBaseInStructure*)pCreateInfo->pNext; next; next = next->pNext) { + switch (next->sType) { + case VK_STRUCTURE_TYPE_IMPORT_METAL_TEXTURE_INFO_EXT: { + const auto* pMTLTexInfo = (VkImportMetalTextureInfoEXT*)next; + uint8_t planeIndex = MVKImage::getPlaneFromVkImageAspectFlags(pMTLTexInfo->plane); + setConfigurationResult(setMTLTexture(planeIndex, pMTLTexInfo->mtlTexture)); + break; + } + case VK_STRUCTURE_TYPE_IMPORT_METAL_IO_SURFACE_INFO_EXT: { + const auto* pIOSurfInfo = (VkImportMetalIOSurfaceInfoEXT*)next; + setConfigurationResult(useIOSurface(pIOSurfInfo->ioSurface)); + break; + } + case VK_STRUCTURE_TYPE_EXPORT_METAL_OBJECT_CREATE_INFO_EXT: + pExportInfo = (VkExportMetalObjectCreateInfoEXT*)next; + break; + default: + break; + } + } + + // If we're expecting to export an IOSurface, and weren't give one, + // base this image on a new IOSurface that matches its configuration. + if (pExportInfo && pExportInfo->exportObjectType == VK_EXPORT_METAL_OBJECT_TYPE_METAL_IOSURFACE_BIT_EXT && !_ioSurface) { + setConfigurationResult(useIOSurface(nil)); + } } VkSampleCountFlagBits MVKImage::validateSamples(const VkImageCreateInfo* pCreateInfo, bool isAttachment) { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm index 29aeeeaa..9c9f1970 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm @@ -653,6 +653,7 @@ void MVKInstance::initProcAddrs() { ADD_DVC_EXT_ENTRY_POINT(vkCmdDebugMarkerInsertEXT, EXT_DEBUG_MARKER); ADD_DVC_EXT_ENTRY_POINT(vkSetHdrMetadataEXT, EXT_HDR_METADATA); ADD_DVC_EXT_ENTRY_POINT(vkResetQueryPoolEXT, EXT_HOST_QUERY_RESET); + ADD_DVC_EXT_ENTRY_POINT(vkExportMetalObjectsEXT, EXT_METAL_OBJECTS); ADD_DVC_EXT_ENTRY_POINT(vkCreatePrivateDataSlotEXT, EXT_PRIVATE_DATA); ADD_DVC_EXT_ENTRY_POINT(vkDestroyPrivateDataSlotEXT, EXT_PRIVATE_DATA); ADD_DVC_EXT_ENTRY_POINT(vkGetPrivateDataEXT, EXT_PRIVATE_DATA); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSync.h b/MoltenVK/MoltenVK/GPUObjects/MVKSync.h index 60091a4b..fdbaf4ae 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSync.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSync.h @@ -183,6 +183,12 @@ public: /** Returns whether this semaphore uses command encoding. */ virtual bool isUsingCommandEncoding() = 0; + /** + * Returns the MTLSharedEvent underlying this Vulkan semaphore, + * or nil if this semaphore is not underpinned by a MTLSharedEvent. + */ + virtual id getMTLSharedEvent() { return nil; }; + #pragma mark Construction @@ -290,7 +296,11 @@ public: #pragma mark Construction - MVKTimelineSemaphore(MVKDevice* device, const VkSemaphoreCreateInfo* pCreateInfo, const VkSemaphoreTypeCreateInfo* pTypeCreateInfo) + MVKTimelineSemaphore(MVKDevice* device, + const VkSemaphoreCreateInfo* pCreateInfo, + const VkSemaphoreTypeCreateInfo* pTypeCreateInfo, + const VkExportMetalObjectCreateInfoEXT* pExportInfo, + const VkImportMetalSharedEventInfoEXT* pImportInfo) : MVKSemaphore(device, pCreateInfo) {} }; @@ -306,18 +316,23 @@ public: void encodeWait(id mtlCmdBuff, uint64_t value) override; void encodeSignal(id mtlCmdBuff, uint64_t value) override; bool isUsingCommandEncoding() override { return true; } + id getMTLSharedEvent() override { return _mtlEvent; }; uint64_t getCounterValue() override { return _mtlEvent.signaledValue; } void signal(const VkSemaphoreSignalInfo* pSignalInfo) override; bool registerWait(MVKFenceSitter* sitter, const VkSemaphoreWaitInfo* pWaitInfo, uint32_t index) override; void unregisterWait(MVKFenceSitter* sitter) override; - MVKTimelineSemaphoreMTLEvent(MVKDevice* device, const VkSemaphoreCreateInfo* pCreateInfo, const VkSemaphoreTypeCreateInfo* pTypeCreateInfo); + MVKTimelineSemaphoreMTLEvent(MVKDevice* device, + const VkSemaphoreCreateInfo* pCreateInfo, + const VkSemaphoreTypeCreateInfo* pTypeCreateInfo, + const VkExportMetalObjectCreateInfoEXT* pExportInfo, + const VkImportMetalSharedEventInfoEXT* pImportInfo); ~MVKTimelineSemaphoreMTLEvent() override; protected: - id _mtlEvent; + id _mtlEvent = nil; std::mutex _lock; std::unordered_set _sitters; }; @@ -339,7 +354,11 @@ public: bool registerWait(MVKFenceSitter* sitter, const VkSemaphoreWaitInfo* pWaitInfo, uint32_t index) override; void unregisterWait(MVKFenceSitter* sitter) override; - MVKTimelineSemaphoreEmulated(MVKDevice* device, const VkSemaphoreCreateInfo* pCreateInfo, const VkSemaphoreTypeCreateInfo* pTypeCreateInfo); + MVKTimelineSemaphoreEmulated(MVKDevice* device, + const VkSemaphoreCreateInfo* pCreateInfo, + const VkSemaphoreTypeCreateInfo* pTypeCreateInfo, + const VkExportMetalObjectCreateInfoEXT* pExportInfo, + const VkImportMetalSharedEventInfoEXT* pImportInfo); protected: void signalImpl(uint64_t value); @@ -475,10 +494,16 @@ public: /** Encodes an operation to block command buffer operation until this event is signaled. */ virtual void encodeWait(id mtlCmdBuff) = 0; + /** Returns the MTLSharedEvent underlying this Vulkan event. */ + virtual id getMTLSharedEvent() = 0; + #pragma mark Construction - MVKEvent(MVKDevice* device, const VkEventCreateInfo* pCreateInfo) : MVKVulkanAPIDeviceObject(device) {} + MVKEvent(MVKDevice* device, + const VkEventCreateInfo* pCreateInfo, + const VkExportMetalObjectCreateInfoEXT* pExportInfo, + const VkImportMetalSharedEventInfoEXT* pImportInfo) : MVKVulkanAPIDeviceObject(device) {} protected: void propagateDebugName() override {} @@ -497,8 +522,12 @@ public: void signal(bool status) override; void encodeSignal(id mtlCmdBuff, bool status) override; void encodeWait(id mtlCmdBuff) override; + id getMTLSharedEvent() override { return _mtlEvent; }; - MVKEventNative(MVKDevice* device, const VkEventCreateInfo* pCreateInfo); + MVKEventNative(MVKDevice* device, + const VkEventCreateInfo* pCreateInfo, + const VkExportMetalObjectCreateInfoEXT* pExportInfo, + const VkImportMetalSharedEventInfoEXT* pImportInfo); ~MVKEventNative() override; @@ -518,8 +547,12 @@ public: void signal(bool status) override; void encodeSignal(id mtlCmdBuff, bool status) override; void encodeWait(id mtlCmdBuff) override; + id getMTLSharedEvent() override { return nil; }; - MVKEventEmulated(MVKDevice* device, const VkEventCreateInfo* pCreateInfo); + MVKEventEmulated(MVKDevice* device, + const VkEventCreateInfo* pCreateInfo, + const VkExportMetalObjectCreateInfoEXT* pExportInfo, + const VkImportMetalSharedEventInfoEXT* pImportInfo); protected: MVKSemaphoreImpl _blocker; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm index d711342e..60af66ba 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm @@ -211,11 +211,21 @@ void MVKTimelineSemaphoreMTLEvent::unregisterWait(MVKFenceSitter* sitter) { _sitters.erase(sitter); } -MVKTimelineSemaphoreMTLEvent::MVKTimelineSemaphoreMTLEvent(MVKDevice* device, const VkSemaphoreCreateInfo* pCreateInfo, const VkSemaphoreTypeCreateInfo* pTypeCreateInfo) : - MVKTimelineSemaphore(device, pCreateInfo, pTypeCreateInfo), - _mtlEvent([device->getMTLDevice() newSharedEvent]) { //retained +MVKTimelineSemaphoreMTLEvent::MVKTimelineSemaphoreMTLEvent(MVKDevice* device, + const VkSemaphoreCreateInfo* pCreateInfo, + const VkSemaphoreTypeCreateInfo* pTypeCreateInfo, + const VkExportMetalObjectCreateInfoEXT* pExportInfo, + const VkImportMetalSharedEventInfoEXT* pImportInfo) : + MVKTimelineSemaphore(device, pCreateInfo, pTypeCreateInfo, pExportInfo, pImportInfo) { - _mtlEvent.signaledValue = pTypeCreateInfo->initialValue; + // Import or create a Metal event + _mtlEvent = (pImportInfo + ? [pImportInfo->mtlSharedEvent retain] + : [device->getMTLDevice() newSharedEvent]); //retained + + if (pTypeCreateInfo) { + _mtlEvent.signaledValue = pTypeCreateInfo->initialValue; + } } MVKTimelineSemaphoreMTLEvent::~MVKTimelineSemaphoreMTLEvent() { @@ -284,9 +294,18 @@ void MVKTimelineSemaphoreEmulated::unregisterWait(MVKFenceSitter* sitter) { for (auto value : emptySets) { _sitters.erase(value); } } -MVKTimelineSemaphoreEmulated::MVKTimelineSemaphoreEmulated(MVKDevice* device, const VkSemaphoreCreateInfo* pCreateInfo, const VkSemaphoreTypeCreateInfo* pTypeCreateInfo) : - MVKTimelineSemaphore(device, pCreateInfo, pTypeCreateInfo), - _value(pTypeCreateInfo->initialValue) {} +MVKTimelineSemaphoreEmulated::MVKTimelineSemaphoreEmulated(MVKDevice* device, + const VkSemaphoreCreateInfo* pCreateInfo, + const VkSemaphoreTypeCreateInfo* pTypeCreateInfo, + const VkExportMetalObjectCreateInfoEXT* pExportInfo, + const VkImportMetalSharedEventInfoEXT* pImportInfo) : + MVKTimelineSemaphore(device, pCreateInfo, pTypeCreateInfo, pExportInfo, pImportInfo), + _value(pTypeCreateInfo ? pTypeCreateInfo->initialValue : 0) { + + if (pExportInfo && pExportInfo->exportObjectType == VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT) { + setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "vkCreateEvent(): MTLSharedEvent is not available on this platform.")); + } +} #pragma mark - @@ -375,8 +394,16 @@ void MVKEventNative::encodeWait(id mtlCmdBuff) { } } -MVKEventNative::MVKEventNative(MVKDevice* device, const VkEventCreateInfo* pCreateInfo) : MVKEvent(device, pCreateInfo) { - _mtlEvent = [_device->getMTLDevice() newSharedEvent]; // retained +MVKEventNative::MVKEventNative(MVKDevice* device, + const VkEventCreateInfo* pCreateInfo, + const VkExportMetalObjectCreateInfoEXT* pExportInfo, + const VkImportMetalSharedEventInfoEXT* pImportInfo) : + MVKEvent(device, pCreateInfo, pExportInfo, pImportInfo) { + + // Import or create a Metal event + _mtlEvent = (pImportInfo + ? [pImportInfo->mtlSharedEvent retain] + : [device->getMTLDevice() newSharedEvent]); //retained } MVKEventNative::~MVKEventNative() { @@ -421,8 +448,16 @@ void MVKEventEmulated::encodeWait(id mtlCmdBuff) { } } -MVKEventEmulated::MVKEventEmulated(MVKDevice* device, const VkEventCreateInfo* pCreateInfo) : - MVKEvent(device, pCreateInfo), _blocker(false, 1), _inlineSignalStatus(false) {} +MVKEventEmulated::MVKEventEmulated(MVKDevice* device, + const VkEventCreateInfo* pCreateInfo, + const VkExportMetalObjectCreateInfoEXT* pExportInfo, + const VkImportMetalSharedEventInfoEXT* pImportInfo) : + MVKEvent(device, pCreateInfo, pExportInfo, pImportInfo), _blocker(false, 1), _inlineSignalStatus(false) { + + if (pExportInfo && pExportInfo->exportObjectType == VK_EXPORT_METAL_OBJECT_TYPE_METAL_SHARED_EVENT_BIT_EXT) { + setConfigurationResult(reportError(VK_ERROR_INITIALIZATION_FAILED, "vkCreateEvent(): MTLSharedEvent is not available on this platform.")); + } +} #pragma mark - diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def index 927e2338..9fa6915a 100644 --- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def +++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def @@ -94,6 +94,7 @@ MVK_EXTENSION(EXT_host_query_reset, EXT_HOST_QUERY_RESET, MVK_EXTENSION(EXT_image_robustness, EXT_IMAGE_ROBUSTNESS, DEVICE, 10.11, 8.0) MVK_EXTENSION(EXT_inline_uniform_block, EXT_INLINE_UNIFORM_BLOCK, DEVICE, 10.11, 8.0) MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET, DEVICE, 10.13, 11.0) +MVK_EXTENSION(EXT_metal_objects, EXT_METAL_OBJECTS, DEVICE, 10.11, 8.0) MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE, INSTANCE, 10.11, 8.0) MVK_EXTENSION(EXT_post_depth_coverage, EXT_POST_DEPTH_COVERAGE, DEVICE, 11.0, 11.0) MVK_EXTENSION(EXT_private_data, EXT_PRIVATE_DATA, DEVICE, 10.11, 8.0) diff --git a/MoltenVK/MoltenVK/Vulkan/vulkan.mm b/MoltenVK/MoltenVK/Vulkan/vulkan.mm index c291e892..10cb8740 100644 --- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm +++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm @@ -3038,6 +3038,21 @@ MVK_PUBLIC_VULKAN_SYMBOL VkResult vkCreateMetalSurfaceEXT( return rslt; } + +#pragma mark - +#pragma mark VK_EXT_metal_objects extension + +MVK_PUBLIC_VULKAN_SYMBOL void vkExportMetalObjectsEXT( + VkDevice device, + VkExportMetalObjectsInfoEXT* pMetalObjectsInfo) { + + MVKTraceVulkanCallStart(); + MVKDevice* mvkDvc = MVKDevice::getMVKDevice(device); + mvkDvc->getMetalObjects(pMetalObjectsInfo); + MVKTraceVulkanCallEnd(); +} + + #pragma mark - #pragma mark VK_EXT_private_data extension