Merge pull request #1621 from billhollings/vk-ext-metal-objects-squash
Add support for VK_EXT_metal_objects extension.
diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md
index 23c4bf6..b7f572d 100644
--- a/Docs/MoltenVK_Runtime_UserGuide.md
+++ b/Docs/MoltenVK_Runtime_UserGuide.md
@@ -306,6 +306,7 @@
- `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 9766904..dfdbc27 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -13,6 +13,17 @@
+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 b907983..1245433 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 858f060..4a99c3d 100644
--- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
+++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h
@@ -50,7 +50,7 @@
*/
#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 63b6e18..9989a69 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h
@@ -765,6 +765,9 @@
/** 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 f724e7a..370807e 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -3333,20 +3333,31 @@
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 @@
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::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 229b0ab..a397e3c 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDeviceMemory.mm
@@ -283,6 +283,7 @@
_allocationSize = pAllocateInfo->allocationSize;
+ bool willExportMTLBuffer = false;
VkImage dedicatedImage = VK_NULL_HANDLE;
VkBuffer dedicatedBuffer = VK_NULL_HANDLE;
VkExternalMemoryHandleTypeFlags handleTypes = 0;
@@ -300,6 +301,22 @@
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 @@
}
// 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 379ed9d..8340095 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -712,6 +712,10 @@
VkResult MVKImage::setMTLTexture(uint8_t planeIndex, id<MTLTexture> mtlTexture) {
lock_guard<mutex> 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 @@
VkResult MVKImage::useIOSurface(IOSurfaceRef ioSurface) {
lock_guard<mutex> 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 @@
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 29aeeea..9c9f197 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm
@@ -653,6 +653,7 @@
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 60091a4..fdbaf4a 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSync.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSync.h
@@ -183,6 +183,12 @@
/** 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<MTLSharedEvent> getMTLSharedEvent() { return nil; };
+
#pragma mark Construction
@@ -290,7 +296,11 @@
#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 @@
void encodeWait(id<MTLCommandBuffer> mtlCmdBuff, uint64_t value) override;
void encodeSignal(id<MTLCommandBuffer> mtlCmdBuff, uint64_t value) override;
bool isUsingCommandEncoding() override { return true; }
+ id<MTLSharedEvent> 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<MTLSharedEvent> _mtlEvent;
+ id<MTLSharedEvent> _mtlEvent = nil;
std::mutex _lock;
std::unordered_set<MVKFenceSitter*> _sitters;
};
@@ -339,7 +354,11 @@
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 @@
/** Encodes an operation to block command buffer operation until this event is signaled. */
virtual void encodeWait(id<MTLCommandBuffer> mtlCmdBuff) = 0;
+ /** Returns the MTLSharedEvent underlying this Vulkan event. */
+ virtual id<MTLSharedEvent> 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 @@
void signal(bool status) override;
void encodeSignal(id<MTLCommandBuffer> mtlCmdBuff, bool status) override;
void encodeWait(id<MTLCommandBuffer> mtlCmdBuff) override;
+ id<MTLSharedEvent> 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 @@
void signal(bool status) override;
void encodeSignal(id<MTLCommandBuffer> mtlCmdBuff, bool status) override;
void encodeWait(id<MTLCommandBuffer> mtlCmdBuff) override;
+ id<MTLSharedEvent> 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 d711342..60af66b 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSync.mm
@@ -211,11 +211,21 @@
_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 @@
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 @@
}
}
-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 @@
}
}
-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 927e233..9fa6915 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
@@ -94,6 +94,7 @@
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 c291e89..10cb874 100644
--- a/MoltenVK/MoltenVK/Vulkan/vulkan.mm
+++ b/MoltenVK/MoltenVK/Vulkan/vulkan.mm
@@ -3038,6 +3038,21 @@
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