From d46b2f303686a33f9c81a73e81e4abb108224096 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Fri, 3 Apr 2020 16:55:10 -0400 Subject: [PATCH 1/5] Disable use of MTLHeap by default. Add MVK_CONFIG_USE_MTLHEAP environment variable to enable use of MTLHeap if needed. Minor fixes to consistent use of MVK_SET_FROM_ENV_OR_BUILD_BOOL(). --- MoltenVK/MoltenVK.xcodeproj/project.pbxproj | 4 ++-- MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h | 12 +++++++++++ MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 22 +++++++++++++-------- MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm | 2 +- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj index 321eea65a..8302b2e47 100644 --- a/MoltenVK/MoltenVK.xcodeproj/project.pbxproj +++ b/MoltenVK/MoltenVK.xcodeproj/project.pbxproj @@ -503,8 +503,6 @@ A94FB7841C7DFB4800632CA3 /* MVKDevice.mm */, A94FB7851C7DFB4800632CA3 /* MVKDeviceMemory.h */, A94FB7861C7DFB4800632CA3 /* MVKDeviceMemory.mm */, - A9653FB724129C84005999D7 /* MVKPixelFormats.h */, - A9653FB924129C84005999D7 /* MVKPixelFormats.mm */, A94FB7871C7DFB4800632CA3 /* MVKFramebuffer.h */, A94FB7881C7DFB4800632CA3 /* MVKFramebuffer.mm */, A94FB7891C7DFB4800632CA3 /* MVKImage.h */, @@ -513,6 +511,8 @@ A94FB78C1C7DFB4800632CA3 /* MVKInstance.mm */, A94FB78D1C7DFB4800632CA3 /* MVKPipeline.h */, A94FB78E1C7DFB4800632CA3 /* MVKPipeline.mm */, + A9653FB724129C84005999D7 /* MVKPixelFormats.h */, + A9653FB924129C84005999D7 /* MVKPixelFormats.mm */, A94FB78F1C7DFB4800632CA3 /* MVKQueryPool.h */, A94FB7901C7DFB4800632CA3 /* MVKQueryPool.mm */, A94FB7911C7DFB4800632CA3 /* MVKQueue.h */, diff --git a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h index a988a15f6..95056cb1d 100644 --- a/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h +++ b/MoltenVK/MoltenVK/API/vk_mvk_moltenvk.h @@ -163,6 +163,18 @@ typedef unsigned long MTLLanguageVersion; * a command is executed. This is a classic time-space trade off. When command pooling is * active, the memory in the pool can be cleared via a call to the vkTrimCommandPoolKHR() * command. This setting is enabled by default, and MoltenVK will pool command memory. + * + * 9. The MVK_CONFIG_USE_MTLHEAP runtime environment variable or MoltenVK compile-time build + * setting controls whether MoltenVK should use MTLHeaps for allocating textures and buffers + * from device memory. If this environment variable is enabled, and placement MTLHeaps are + * available on the platform, MoltenVK will allocate a placement MTLHeap for each VkDeviceMemory + * instance, and allocate textures and buffers from that placement heap. If this environment + * variable is disabled, MoltenVK will allocate textures and buffers from general device memory. + * Apple recommends that MTLHeaps should only be used for specific requirements such as aliasing + * or hazard tracking, and MoltenVK testing has shown that allocating multiple textures of + * different types or usages from one MTLHeap can occassionally cause corruption issues under + * certain circumstances. Because of this, this setting is disabled by default, and MoltenVK + * will allocate texures and buffers from general device memory. */ typedef struct { diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index b49b4f120..d09363665 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -773,7 +773,15 @@ // Initializes the Metal-specific physical device features of this instance. void MVKPhysicalDevice::initMetalFeatures() { - mvkClear(&_metalFeatures); // Start with everything cleared + +# ifndef MVK_CONFIG_USE_MTLHEAP +# define MVK_CONFIG_USE_MTLHEAP 0 +# endif + bool useMTLHeaps; + MVK_SET_FROM_ENV_OR_BUILD_BOOL(useMTLHeaps, MVK_CONFIG_USE_MTLHEAP); + + // Start with all Metal features cleared + mvkClear(&_metalFeatures); _metalFeatures.maxPerStageBufferCount = 31; _metalFeatures.maxMTLBufferSize = (256 * MEBI); @@ -848,7 +856,7 @@ if ( mvkOSVersionIsAtLeast(13.0) ) { _metalFeatures.mslVersionEnum = MTLLanguageVersion2_2; - _metalFeatures.placementHeaps = true; + _metalFeatures.placementHeaps = useMTLHeaps; if (supportsMTLGPUFamily(Apple4)) { _metalFeatures.nativeTextureSwizzle = true; } @@ -904,7 +912,7 @@ _metalFeatures.native3DCompressedTextures = true; if (supportsMTLGPUFamily(Mac2)) { _metalFeatures.nativeTextureSwizzle = true; - _metalFeatures.placementHeaps = true; + _metalFeatures.placementHeaps = useMTLHeaps; } } @@ -957,7 +965,6 @@ break; #endif } - } // Initializes the physical device features of this instance. @@ -2656,10 +2663,9 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope } MVKLogInfo("Using %s for Vulkan semaphores.", _useMTLFenceForSemaphores ? "MTLFence" : (_useMTLEventForSemaphores ? "MTLEvent" : "emulation")); -#ifndef MVK_CONFIG_USE_COMMAND_POOLING -# define MVK_CONFIG_USE_COMMAND_POOLING 1 -#endif - _useCommandPooling = MVK_CONFIG_USE_COMMAND_POOLING; +# ifndef MVK_CONFIG_USE_COMMAND_POOLING +# define MVK_CONFIG_USE_COMMAND_POOLING 1 +# endif MVK_SET_FROM_ENV_OR_BUILD_BOOL(_useCommandPooling, MVK_CONFIG_USE_COMMAND_POOLING); #if MVK_MACOS diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm index 6f7bc0c2f..c231f2eb1 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKInstance.mm @@ -289,7 +289,7 @@ #if MVK_MACOS NSArray* rawMTLDevs = [MTLCopyAllDevices() autorelease]; if (rawMTLDevs) { - bool forceLowPower = MVK_CONFIG_FORCE_LOW_POWER_GPU; + bool forceLowPower; MVK_SET_FROM_ENV_OR_BUILD_BOOL(forceLowPower, MVK_CONFIG_FORCE_LOW_POWER_GPU); // Populate the array of appropriate MTLDevices From c6b642db1964a77e6bbd65eb0bfd780ca46db9ac Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Sat, 4 Apr 2020 16:25:13 -0400 Subject: [PATCH 2/5] Fix acquisition ordering of swapchain images. Remove obsolete MVKSwapchainImageAvailability::waitCount member that was initializing randomly and corrupting swapchain image acquisition ordering evaluations. Rename several member functions to clarify purpose. --- MoltenVK/MoltenVK/GPUObjects/MVKImage.h | 9 ++-- MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 44 ++++++++++---------- MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm | 12 +++--- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h index fc1ba816d..c8c1c8b71 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h @@ -236,8 +236,8 @@ class MVKImage : public MVKResource { void initSubresources(const VkImageCreateInfo* pCreateInfo); void initSubresourceLayout(MVKImageSubresource& imgSubRez); virtual id newMTLTexture(); - void resetMTLTexture(); - void resetIOSurface(); + void releaseMTLTexture(); + void releaseIOSurface(); MTLTextureDescriptor* newMTLTextureDescriptor(); void updateMTLTextureContent(MVKImageSubresource& subresource, VkDeviceSize offset, VkDeviceSize size); void getMTLTextureContent(MVKImageSubresource& subresource, VkDeviceSize offset, VkDeviceSize size); @@ -277,7 +277,6 @@ class MVKImage : public MVKResource { /** Indicates the relative availability of each image in the swapchain. */ typedef struct MVKSwapchainImageAvailability { uint64_t acquisitionID; /**< When this image was last made available, relative to the other images in the swapchain. Smaller value is earlier. */ - uint32_t waitCount; /**< The number of semaphores already waiting for this image. */ bool isAvailable; /**< Indicates whether this image is currently available. */ bool operator< (const MVKSwapchainImageAvailability& rhs) const; @@ -327,10 +326,10 @@ class MVKSwapchainImage : public MVKImage { id newMTLTexture() override; id getCAMetalDrawable(); - void resetMetalDrawable(); + void releaseMetalDrawable(); MVKSwapchainImageAvailability getAvailability(); void makeAvailable(); - void signalWhenAvailable(MVKSemaphore* semaphore, MVKFence* fence); + void acquireAndSignalWhenAvailable(MVKSemaphore* semaphore, MVKFence* fence); void signal(MVKSwapchainSignaler& signaler, id mtlCmdBuff); void signalPresentationSemaphore(id mtlCmdBuff); static void markAsTracked(MVKSwapchainSignaler& signaler); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 4a226d94d..8a16ef2f9 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -300,8 +300,8 @@ VkResult MVKImage::setMTLTexture(id mtlTexture) { lock_guard lock(_lock); - resetMTLTexture(); - resetIOSurface(); + releaseMTLTexture(); + releaseIOSurface(); _mtlTexture = [mtlTexture retain]; // retained @@ -349,14 +349,14 @@ } // Removes and releases the MTLTexture object, and all associated texture views -void MVKImage::resetMTLTexture() { +void MVKImage::releaseMTLTexture() { [_mtlTexture release]; _mtlTexture = nil; for (auto elem : _mtlTextureViews) { [elem.second release]; } _mtlTextureViews.clear(); } -void MVKImage::resetIOSurface() { +void MVKImage::releaseIOSurface() { if (_ioSurface) { CFRelease(_ioSurface); _ioSurface = nil; @@ -372,8 +372,8 @@ #if MVK_SUPPORT_IOSURFACE_BOOL - resetMTLTexture(); - resetIOSurface(); + releaseMTLTexture(); + releaseIOSurface(); MVKPixelFormats* pixFmts = getPixelFormats(); @@ -788,14 +788,20 @@ MVKImage::~MVKImage() { if (_deviceMemory) { _deviceMemory->removeImage(this); } - resetMTLTexture(); - resetIOSurface(); + releaseMTLTexture(); + releaseIOSurface(); } #pragma mark - #pragma mark MVKSwapchainImage +bool MVKSwapchainImageAvailability::operator< (const MVKSwapchainImageAvailability& rhs) const { + if ( isAvailable && !rhs.isAvailable) { return true; } + if ( !isAvailable && rhs.isAvailable) { return false; } + return acquisitionID < rhs.acquisitionID; +} + VkResult MVKSwapchainImage::bindDeviceMemory(MVKDeviceMemory*, VkDeviceSize) { return VK_ERROR_OUT_OF_DEVICE_MEMORY; } @@ -820,16 +826,6 @@ return VK_SUCCESS; } -bool MVKSwapchainImageAvailability::operator< (const MVKSwapchainImageAvailability& rhs) const { - if ( isAvailable && !rhs.isAvailable) { return true; } - if ( !isAvailable && rhs.isAvailable) { return false; } - - if (waitCount < rhs.waitCount) { return true; } - if (waitCount > rhs.waitCount) { return false; } - - return acquisitionID < rhs.acquisitionID; -} - MVKSwapchainImageAvailability MVKSwapchainImage::getAvailability() { lock_guard lock(_availabilityLock); @@ -870,9 +866,13 @@ // MVKLogDebug("Signaling%s swapchain image %p semaphore %p from present, with %lu remaining semaphores.", (_availability.isAvailable ? " pre-signaled" : ""), this, signaler.first, _availabilitySignalers.size()); } -void MVKSwapchainImage::signalWhenAvailable(MVKSemaphore* semaphore, MVKFence* fence) { +void MVKSwapchainImage::acquireAndSignalWhenAvailable(MVKSemaphore* semaphore, MVKFence* fence) { lock_guard lock(_availabilityLock); + // Now that this image is being acquired, release the existing drawable and its texture. + // This is not done earlier so the texture is retained for any post-processing such as screen captures, etc. + releaseMetalDrawable(); + auto signaler = make_pair(semaphore, fence); if (_availability.isAvailable) { _availability.isAvailable = false; @@ -968,8 +968,8 @@ } // Resets the MTLTexture and CAMetalDrawable underlying this image. -void MVKSwapchainImage::resetMetalDrawable() { - resetMTLTexture(); // Release texture first so drawable will be last to release it +void MVKSwapchainImage::releaseMetalDrawable() { + releaseMTLTexture(); // Release texture first so drawable will be last to release it [_mtlDrawable release]; _mtlDrawable = nil; } @@ -991,7 +991,7 @@ } MVKSwapchainImage::~MVKSwapchainImage() { - resetMetalDrawable(); + releaseMetalDrawable(); } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm index b93d3b94d..13041b34c 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm @@ -80,11 +80,9 @@ if ( getIsSurfaceLost() ) { return VK_ERROR_SURFACE_LOST_KHR; } - // Find the image that has the smallest availability measure + // Find the image that has the shortest wait by finding the smallest availability measure. MVKSwapchainImage* minWaitImage = nullptr; - MVKSwapchainImageAvailability minAvailability = { .acquisitionID = kMVKUndefinedLargeUInt64, - .waitCount = kMVKUndefinedLargeUInt32, - .isAvailable = false }; + MVKSwapchainImageAvailability minAvailability = { kMVKUndefinedLargeUInt64, false }; uint32_t imgCnt = getImageCount(); for (uint32_t imgIdx = 0; imgIdx < imgCnt; imgIdx++) { MVKSwapchainImage* img = getImage(imgIdx); @@ -95,10 +93,10 @@ } } - // Return the index of the image with the shortest wait and signal the semaphore and fence when it's available + // Return the index of the image with the shortest wait, + // and signal the semaphore and fence when it's available *pImageIndex = minWaitImage->_swapchainIndex; - minWaitImage->resetMetalDrawable(); - minWaitImage->signalWhenAvailable((MVKSemaphore*)semaphore, (MVKFence*)fence); + minWaitImage->acquireAndSignalWhenAvailable((MVKSemaphore*)semaphore, (MVKFence*)fence); return getHasSurfaceSizeChanged() ? VK_ERROR_OUT_OF_DATE_KHR : VK_SUCCESS; } From aa27fd6588fd0a2343e0b43bd5bf587716af9082 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Sat, 4 Apr 2020 20:25:23 -0400 Subject: [PATCH 3/5] MVKSwapchainImage always retrieve MTLTexture directly from CAMetalDrawable. --- MoltenVK/MoltenVK/GPUObjects/MVKImage.h | 8 +-- MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 63 +++++++++++------------- 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h index c8c1c8b71..c44f47853 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h @@ -147,7 +147,7 @@ class MVKImage : public MVKResource { #pragma mark Metal /** Returns the Metal texture underlying this image. */ - id getMTLTexture(); + virtual id getMTLTexture(); /** Returns a Metal texture that interprets the pixels in the specified format. */ id getMTLTexture(MTLPixelFormat mtlPixFmt); @@ -235,7 +235,7 @@ class MVKImage : public MVKResource { bool validateUseTexelBuffer(); void initSubresources(const VkImageCreateInfo* pCreateInfo); void initSubresourceLayout(MVKImageSubresource& imgSubRez); - virtual id newMTLTexture(); + id newMTLTexture(); void releaseMTLTexture(); void releaseIOSurface(); MTLTextureDescriptor* newMTLTextureDescriptor(); @@ -300,6 +300,9 @@ class MVKSwapchainImage : public MVKImage { #pragma mark Metal + /** Returns the Metal texture used by the CAMetalDrawable underlying this image. */ + id getMTLTexture() override; + /** * Presents the contained drawable to the OS, releases the Metal drawable and its * texture back to the Metal layer's pool, and makes the image memory available for new use. @@ -324,7 +327,6 @@ class MVKSwapchainImage : public MVKImage { protected: friend MVKSwapchain; - id newMTLTexture() override; id getCAMetalDrawable(); void releaseMetalDrawable(); MVKSwapchainImageAvailability getAvailability(); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 8a16ef2f9..65637b5f3 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -298,34 +298,6 @@ return mtlTex; } -VkResult MVKImage::setMTLTexture(id mtlTexture) { - lock_guard lock(_lock); - releaseMTLTexture(); - releaseIOSurface(); - - _mtlTexture = [mtlTexture retain]; // retained - - _mtlPixelFormat = _mtlTexture.pixelFormat; - _mtlTextureType = _mtlTexture.textureType; - _extent.width = uint32_t(_mtlTexture.width); - _extent.height = uint32_t(_mtlTexture.height); - _extent.depth = uint32_t(_mtlTexture.depth); - _mipLevels = uint32_t(_mtlTexture.mipmapLevelCount); - _samples = mvkVkSampleCountFlagBitsFromSampleCount(_mtlTexture.sampleCount); - _arrayLayers = uint32_t(_mtlTexture.arrayLength); - _usage = getPixelFormats()->getVkImageUsageFlagsFromMTLTextureUsage(_mtlTexture.usage, _mtlPixelFormat); - - if (_device->_pMetalFeatures->ioSurfaces) { - _ioSurface = mtlTexture.iosurface; - CFRetain(_ioSurface); - } - - return VK_SUCCESS; -} - -// Creates and returns a retained Metal texture suitable for use in this instance. -// This implementation creates a new MTLTexture from a MTLTextureDescriptor and possible IOSurface. -// Subclasses may override this function to create the MTLTexture in a different manner. id MVKImage::newMTLTexture() { id mtlTex = nil; MTLTextureDescriptor* mtlTexDesc = newMTLTextureDescriptor(); // temp retain @@ -348,6 +320,32 @@ return mtlTex; } +VkResult MVKImage::setMTLTexture(id mtlTexture) { + lock_guard lock(_lock); + + releaseMTLTexture(); + releaseIOSurface(); + + _mtlTexture = [mtlTexture retain]; // retained + + _mtlPixelFormat = mtlTexture.pixelFormat; + _mtlTextureType = mtlTexture.textureType; + _extent.width = uint32_t(mtlTexture.width); + _extent.height = uint32_t(mtlTexture.height); + _extent.depth = uint32_t(mtlTexture.depth); + _mipLevels = uint32_t(mtlTexture.mipmapLevelCount); + _samples = mvkVkSampleCountFlagBitsFromSampleCount(mtlTexture.sampleCount); + _arrayLayers = uint32_t(mtlTexture.arrayLength); + _usage = getPixelFormats()->getVkImageUsageFlagsFromMTLTextureUsage(mtlTexture.usage, _mtlPixelFormat); + + if (_device->_pMetalFeatures->ioSurfaces) { + _ioSurface = mtlTexture.iosurface; + CFRetain(_ioSurface); + } + + return VK_SUCCESS; +} + // Removes and releases the MTLTexture object, and all associated texture views void MVKImage::releaseMTLTexture() { [_mtlTexture release]; @@ -929,11 +927,8 @@ #pragma mark Metal -// Creates and returns a retained Metal texture suitable for use in this instance. -// This implementation retrieves a MTLTexture from the CAMetalDrawable. -id MVKSwapchainImage::newMTLTexture() { - return [[getCAMetalDrawable() texture] retain]; -} +// Overridden to always retrieve the MTLTexture directly from the CAMetalDrawable. +id MVKSwapchainImage::getMTLTexture() { return [getCAMetalDrawable() texture]; } id MVKSwapchainImage::getCAMetalDrawable() { while ( !_mtlDrawable ) { @@ -941,7 +936,7 @@ uint64_t startTime = _device->getPerformanceTimestamp(); _mtlDrawable = [_swapchain->_mtlLayer.nextDrawable retain]; - if ( !_mtlDrawable ) { MVKLogError("CAMetalDrawable could not be acquired after %.6f ms.", mvkGetElapsedMilliseconds(startTime)); } + if ( !_mtlDrawable ) { MVKLogError("CAMetalDrawable could not be acquired."); } _device->addActivityPerformance(_device->_performanceStatistics.queue.nextCAMetalDrawable, startTime); } From 70bf788f9fe478306113040ea298b63f08339665 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Sun, 5 Apr 2020 15:15:24 -0400 Subject: [PATCH 4/5] Fix issue of reseting CAMetalDrawable and MTLTexture of peer swapchain images. Add MVKPresentableSwapchainImage and MVKPeerSwapchainImage subclasses to MVKSwapchainImage, with MVKPresentableSwapchainImage instances created inside swapchain, and MVKPeerSwapchainImage instances created using vkCreateImage(). MVKPeerSwapchainImage retrieve and share CAMetalDrawable from corresponding MVKPresentableSwapchainImage. --- Docs/Whats_New.md | 1 + MoltenVK/MoltenVK/GPUObjects/MVKDevice.h | 14 +- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 16 +-- MoltenVK/MoltenVK/GPUObjects/MVKImage.h | 89 ++++++++++--- MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 127 ++++++++++++------- MoltenVK/MoltenVK/GPUObjects/MVKQueue.h | 2 +- MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm | 6 +- MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h | 8 +- MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm | 14 +- 9 files changed, 183 insertions(+), 94 deletions(-) diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index c50838c44..92649bccf 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -32,6 +32,7 @@ Released 2020/04/05 - Fix issue causing screen captures from swapchain image to deadlock. - Fix memory estimates for iOS 13+. - Broaden conditions for host read sync for image memory barriers on macOS. +- Fix issue of reseting `CAMetalDrawable` and `MTLTexture` of peer swapchain images. - Fix the `make install` build command to overwrite the existing framework in the system framework library, and update `README.md` to clarify the instructions for using `make install`. - Update the `README.md` and `MoltenVK_Runtime_UserGuide.md` documents to clarify that diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h index 95bbad25d..d17710188 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.h @@ -42,7 +42,7 @@ class MVKResource; class MVKBuffer; class MVKBufferView; class MVKImage; -class MVKSwapchainImage; +class MVKPresentableSwapchainImage; class MVKImageView; class MVKSwapchain; class MVKDeviceMemory; @@ -450,12 +450,12 @@ class MVKDevice : public MVKDispatchableVulkanAPIObject { void destroySwapchain(MVKSwapchain* mvkSwpChn, const VkAllocationCallbacks* pAllocator); - MVKSwapchainImage* createSwapchainImage(const VkImageCreateInfo* pCreateInfo, - MVKSwapchain* swapchain, - uint32_t swapchainIndex, - const VkAllocationCallbacks* pAllocator); - void destroySwapchainImage(MVKSwapchainImage* mvkImg, - const VkAllocationCallbacks* pAllocator); + MVKPresentableSwapchainImage* createPresentableSwapchainImage(const VkImageCreateInfo* pCreateInfo, + MVKSwapchain* swapchain, + uint32_t swapchainIndex, + const VkAllocationCallbacks* pAllocator); + void destroyPresentableSwapchainImage(MVKPresentableSwapchainImage* mvkImg, + const VkAllocationCallbacks* pAllocator); MVKFence* createFence(const VkFenceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index d09363665..c9781fd0a 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -2138,7 +2138,7 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope } } if (swapchainInfo) { - return createSwapchainImage(pCreateInfo, (MVKSwapchain*)swapchainInfo->swapchain, uint32_t(-1), pAllocator); + return (MVKImage*)addResource(new MVKPeerSwapchainImage(this, pCreateInfo, (MVKSwapchain*)swapchainInfo->swapchain, uint32_t(-1))); } return (MVKImage*)addResource(new MVKImage(this, pCreateInfo)); } @@ -2169,15 +2169,15 @@ static uint32_t mvkGetEntryProperty(io_registry_entry_t entry, CFStringRef prope mvkSwpChn->destroy(); } -MVKSwapchainImage* MVKDevice::createSwapchainImage(const VkImageCreateInfo* pCreateInfo, - MVKSwapchain* swapchain, - uint32_t swapchainIndex, - const VkAllocationCallbacks* pAllocator) { - return (MVKSwapchainImage*)addResource(new MVKSwapchainImage(this, pCreateInfo, swapchain, swapchainIndex)); +MVKPresentableSwapchainImage* MVKDevice::createPresentableSwapchainImage(const VkImageCreateInfo* pCreateInfo, + MVKSwapchain* swapchain, + uint32_t swapchainIndex, + const VkAllocationCallbacks* pAllocator) { + return (MVKPresentableSwapchainImage*)addResource(new MVKPresentableSwapchainImage(this, pCreateInfo, swapchain, swapchainIndex)); } -void MVKDevice::destroySwapchainImage(MVKSwapchainImage* mvkImg, - const VkAllocationCallbacks* pAllocator) { +void MVKDevice::destroyPresentableSwapchainImage(MVKPresentableSwapchainImage* mvkImg, + const VkAllocationCallbacks* pAllocator) { removeResource(mvkImg); mvkImg->destroy(); } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h index c44f47853..89e5af024 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h @@ -274,6 +274,41 @@ class MVKImage : public MVKResource { #pragma mark - #pragma mark MVKSwapchainImage +/** Abstract class of Vulkan image used as a rendering destination within a swapchain. */ +class MVKSwapchainImage : public MVKImage { + +public: + + /** Binds this resource to the specified offset within the specified memory allocation. */ + VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override; + +#pragma mark Metal + + /** Returns the Metal texture used by the CAMetalDrawable underlying this image. */ + id getMTLTexture() override; + + +#pragma mark Construction + + /** Constructs an instance for the specified device and swapchain. */ + MVKSwapchainImage(MVKDevice* device, + const VkImageCreateInfo* pCreateInfo, + MVKSwapchain* swapchain, + uint32_t swapchainIndex); + +protected: + friend class MVKPeerSwapchainImage; + + virtual id getCAMetalDrawable() = 0; + + MVKSwapchain* _swapchain; + uint32_t _swapchainIndex; +}; + + +#pragma mark - +#pragma mark MVKPresentableSwapchainImage + /** Indicates the relative availability of each image in the swapchain. */ typedef struct MVKSwapchainImageAvailability { uint64_t acquisitionID; /**< When this image was last made available, relative to the other images in the swapchain. Smaller value is earlier. */ @@ -286,23 +321,13 @@ typedef struct MVKSwapchainImageAvailability { typedef std::pair MVKSwapchainSignaler; -/** Represents a Vulkan image used as a rendering destination within a swapchain. */ -class MVKSwapchainImage : public MVKImage { +/** Represents a Vulkan swapchain image that can be submitted to the presentation engine. */ +class MVKPresentableSwapchainImage : public MVKSwapchainImage { public: - /** Binds this resource to the specified offset within the specified memory allocation. */ - VkResult bindDeviceMemory(MVKDeviceMemory* mvkMem, VkDeviceSize memOffset) override; - - /** Binds this resource according to the specified bind information. */ - VkResult bindDeviceMemory2(const void* pBindInfo) override; - - #pragma mark Metal - /** Returns the Metal texture used by the CAMetalDrawable underlying this image. */ - id getMTLTexture() override; - /** * Presents the contained drawable to the OS, releases the Metal drawable and its * texture back to the Metal layer's pool, and makes the image memory available for new use. @@ -317,17 +342,17 @@ class MVKSwapchainImage : public MVKImage { #pragma mark Construction /** Constructs an instance for the specified device and swapchain. */ - MVKSwapchainImage(MVKDevice* device, - const VkImageCreateInfo* pCreateInfo, - MVKSwapchain* swapchain, - uint32_t swapchainIndex); + MVKPresentableSwapchainImage(MVKDevice* device, + const VkImageCreateInfo* pCreateInfo, + MVKSwapchain* swapchain, + uint32_t swapchainIndex); - ~MVKSwapchainImage() override; + ~MVKPresentableSwapchainImage() override; protected: friend MVKSwapchain; - id getCAMetalDrawable(); + id getCAMetalDrawable() override; void releaseMetalDrawable(); MVKSwapchainImageAvailability getAvailability(); void makeAvailable(); @@ -338,8 +363,6 @@ class MVKSwapchainImage : public MVKImage { static void unmarkAsTracked(MVKSwapchainSignaler& signaler); void renderWatermark(id mtlCmdBuff); - MVKSwapchain* _swapchain; - uint32_t _swapchainIndex; id _mtlDrawable; MVKSwapchainImageAvailability _availability; MVKVectorInline _availabilitySignalers; @@ -348,6 +371,32 @@ class MVKSwapchainImage : public MVKImage { }; +#pragma mark - +#pragma mark MVKPeerSwapchainImage + +/** Represents a Vulkan swapchain image that can be associated as a peer to a swapchain image. */ +class MVKPeerSwapchainImage : public MVKSwapchainImage { + +public: + + /** Binds this resource according to the specified bind information. */ + VkResult bindDeviceMemory2(const void* pBindInfo) override; + + +#pragma mark Construction + + /** Constructs an instance for the specified device and swapchain. */ + MVKPeerSwapchainImage(MVKDevice* device, + const VkImageCreateInfo* pCreateInfo, + MVKSwapchain* swapchain, + uint32_t swapchainIndex); + +protected: + id getCAMetalDrawable() override; + +}; + + #pragma mark - #pragma mark MVKImageView diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 65637b5f3..97c52e7e3 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -794,37 +794,38 @@ #pragma mark - #pragma mark MVKSwapchainImage -bool MVKSwapchainImageAvailability::operator< (const MVKSwapchainImageAvailability& rhs) const { - if ( isAvailable && !rhs.isAvailable) { return true; } - if ( !isAvailable && rhs.isAvailable) { return false; } - return acquisitionID < rhs.acquisitionID; -} - VkResult MVKSwapchainImage::bindDeviceMemory(MVKDeviceMemory*, VkDeviceSize) { return VK_ERROR_OUT_OF_DEVICE_MEMORY; } -VkResult MVKSwapchainImage::bindDeviceMemory2(const void* pBindInfo) { - const auto* imageInfo = (const VkBindImageMemoryInfo*)pBindInfo; - const VkBindImageMemorySwapchainInfoKHR* swapchainInfo = nullptr; - for (const auto* next = (const VkBaseInStructure*)imageInfo->pNext; next; next = next->pNext) { - switch (next->sType) { - case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: - swapchainInfo = (const VkBindImageMemorySwapchainInfoKHR*)next; - break; - default: - break; - } - if (swapchainInfo) { break; } - } - if (!swapchainInfo) { - return VK_ERROR_OUT_OF_DEVICE_MEMORY; - } - _swapchainIndex = swapchainInfo->imageIndex; - return VK_SUCCESS; + +#pragma mark Metal + +// Overridden to always retrieve the MTLTexture directly from the CAMetalDrawable. +id MVKSwapchainImage::getMTLTexture() { return [getCAMetalDrawable() texture]; } + + +#pragma mark Construction + +MVKSwapchainImage::MVKSwapchainImage(MVKDevice* device, + const VkImageCreateInfo* pCreateInfo, + MVKSwapchain* swapchain, + uint32_t swapchainIndex) : MVKImage(device, pCreateInfo) { + _swapchain = swapchain; + _swapchainIndex = swapchainIndex; } -MVKSwapchainImageAvailability MVKSwapchainImage::getAvailability() { + +#pragma mark - +#pragma mark MVKPresentableSwapchainImage + +bool MVKSwapchainImageAvailability::operator< (const MVKSwapchainImageAvailability& rhs) const { + if ( isAvailable && !rhs.isAvailable) { return true; } + if ( !isAvailable && rhs.isAvailable) { return false; } + return acquisitionID < rhs.acquisitionID; +} + +MVKSwapchainImageAvailability MVKPresentableSwapchainImage::getAvailability() { lock_guard lock(_availabilityLock); return _availability; @@ -833,7 +834,7 @@ // Makes an image available for acquisition by the app. // If any semaphores are waiting to be signaled when this image becomes available, the // earliest semaphore is signaled, and this image remains unavailable for other uses. -void MVKSwapchainImage::makeAvailable() { +void MVKPresentableSwapchainImage::makeAvailable() { lock_guard lock(_availabilityLock); // Mark when this event happened, relative to that of other images @@ -864,7 +865,7 @@ // MVKLogDebug("Signaling%s swapchain image %p semaphore %p from present, with %lu remaining semaphores.", (_availability.isAvailable ? " pre-signaled" : ""), this, signaler.first, _availabilitySignalers.size()); } -void MVKSwapchainImage::acquireAndSignalWhenAvailable(MVKSemaphore* semaphore, MVKFence* fence) { +void MVKPresentableSwapchainImage::acquireAndSignalWhenAvailable(MVKSemaphore* semaphore, MVKFence* fence) { lock_guard lock(_availabilityLock); // Now that this image is being acquired, release the existing drawable and its texture. @@ -897,7 +898,7 @@ } // If present, signal the semaphore for the first waiter for the given image. -void MVKSwapchainImage::signalPresentationSemaphore(id mtlCmdBuff) { +void MVKPresentableSwapchainImage::signalPresentationSemaphore(id mtlCmdBuff) { lock_guard lock(_availabilityLock); if ( !_availabilitySignalers.empty() ) { @@ -907,19 +908,19 @@ } // Signal either or both of the semaphore and fence in the specified tracker pair. -void MVKSwapchainImage::signal(MVKSwapchainSignaler& signaler, id mtlCmdBuff) { +void MVKPresentableSwapchainImage::signal(MVKSwapchainSignaler& signaler, id mtlCmdBuff) { if (signaler.first) { signaler.first->encodeSignal(mtlCmdBuff); } if (signaler.second) { signaler.second->signal(); } } // Tell the semaphore and fence that they are being tracked for future signaling. -void MVKSwapchainImage::markAsTracked(MVKSwapchainSignaler& signaler) { +void MVKPresentableSwapchainImage::markAsTracked(MVKSwapchainSignaler& signaler) { if (signaler.first) { signaler.first->retain(); } if (signaler.second) { signaler.second->retain(); } } // Tell the semaphore and fence that they are no longer being tracked for future signaling. -void MVKSwapchainImage::unmarkAsTracked(MVKSwapchainSignaler& signaler) { +void MVKPresentableSwapchainImage::unmarkAsTracked(MVKSwapchainSignaler& signaler) { if (signaler.first) { signaler.first->release(); } if (signaler.second) { signaler.second->release(); } } @@ -927,10 +928,7 @@ #pragma mark Metal -// Overridden to always retrieve the MTLTexture directly from the CAMetalDrawable. -id MVKSwapchainImage::getMTLTexture() { return [getCAMetalDrawable() texture]; } - -id MVKSwapchainImage::getCAMetalDrawable() { +id MVKPresentableSwapchainImage::getCAMetalDrawable() { while ( !_mtlDrawable ) { @autoreleasepool { // Reclaim auto-released drawable object before end of loop uint64_t startTime = _device->getPerformanceTimestamp(); @@ -945,7 +943,7 @@ } // Present the drawable and make myself available only once the command buffer has completed. -void MVKSwapchainImage::presentCAMetalDrawable(id mtlCmdBuff) { +void MVKPresentableSwapchainImage::presentCAMetalDrawable(id mtlCmdBuff) { _swapchain->willPresentSurface(getMTLTexture(), mtlCmdBuff); NSString* scName = _swapchain->getDebugName(); @@ -963,7 +961,7 @@ } // Resets the MTLTexture and CAMetalDrawable underlying this image. -void MVKSwapchainImage::releaseMetalDrawable() { +void MVKPresentableSwapchainImage::releaseMetalDrawable() { releaseMTLTexture(); // Release texture first so drawable will be last to release it [_mtlDrawable release]; _mtlDrawable = nil; @@ -972,12 +970,12 @@ #pragma mark Construction -MVKSwapchainImage::MVKSwapchainImage(MVKDevice* device, - const VkImageCreateInfo* pCreateInfo, - MVKSwapchain* swapchain, - uint32_t swapchainIndex) : MVKImage(device, pCreateInfo) { - _swapchain = swapchain; - _swapchainIndex = swapchainIndex; +MVKPresentableSwapchainImage::MVKPresentableSwapchainImage(MVKDevice* device, + const VkImageCreateInfo* pCreateInfo, + MVKSwapchain* swapchain, + uint32_t swapchainIndex) : + MVKSwapchainImage(device, pCreateInfo, swapchain, swapchainIndex) { + _mtlDrawable = nil; _availability.acquisitionID = _swapchain->getNextAcquisitionID(); @@ -985,11 +983,52 @@ _preSignaler = make_pair(nullptr, nullptr); } -MVKSwapchainImage::~MVKSwapchainImage() { +MVKPresentableSwapchainImage::~MVKPresentableSwapchainImage() { releaseMetalDrawable(); } +#pragma mark - +#pragma mark MVKPeerSwapchainImage + +VkResult MVKPeerSwapchainImage::bindDeviceMemory2(const void* pBindInfo) { + const auto* imageInfo = (const VkBindImageMemoryInfo*)pBindInfo; + const VkBindImageMemorySwapchainInfoKHR* swapchainInfo = nullptr; + for (const auto* next = (const VkBaseInStructure*)imageInfo->pNext; next; next = next->pNext) { + switch (next->sType) { + case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: + swapchainInfo = (const VkBindImageMemorySwapchainInfoKHR*)next; + break; + default: + break; + } + if (swapchainInfo) { break; } + } + if (!swapchainInfo) { + return VK_ERROR_OUT_OF_DEVICE_MEMORY; + } + _swapchainIndex = swapchainInfo->imageIndex; + return VK_SUCCESS; +} + + +#pragma mark Metal + +id MVKPeerSwapchainImage::getCAMetalDrawable() { + return ((MVKSwapchainImage*)_swapchain->getPresentableImage(_swapchainIndex))->getCAMetalDrawable(); +} + + +#pragma mark Construction + +MVKPeerSwapchainImage::MVKPeerSwapchainImage(MVKDevice* device, + const VkImageCreateInfo* pCreateInfo, + MVKSwapchain* swapchain, + uint32_t swapchainIndex) : + MVKSwapchainImage(device, pCreateInfo, swapchain, swapchainIndex) {} + + + #pragma mark - #pragma mark MVKImageView diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h index 9dda53c45..c705a9df8 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.h @@ -228,6 +228,6 @@ class MVKQueuePresentSurfaceSubmission : public MVKQueueSubmission { protected: id getMTLCommandBuffer(); - MVKVectorInline _surfaceImages; + MVKVectorInline _presentableImages; }; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm index 794c9442d..4c71d02af 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKQueue.mm @@ -339,7 +339,7 @@ // The semaphores know what to do. id mtlCmdBuff = getMTLCommandBuffer(); for (auto& ws : _waitSemaphores) { ws->encodeWait(mtlCmdBuff); } - for (auto& si : _surfaceImages) { si->presentCAMetalDrawable(mtlCmdBuff); } + for (auto& img : _presentableImages) { img->presentCAMetalDrawable(mtlCmdBuff); } for (auto& ws : _waitSemaphores) { ws->encodeWait(nil); } [mtlCmdBuff commit]; @@ -363,10 +363,10 @@ : MVKQueueSubmission(queue, pPresentInfo->waitSemaphoreCount, pPresentInfo->pWaitSemaphores) { // Populate the array of swapchain images, testing each one for a change in surface size - _surfaceImages.reserve(pPresentInfo->swapchainCount); + _presentableImages.reserve(pPresentInfo->swapchainCount); for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) { MVKSwapchain* mvkSC = (MVKSwapchain*)pPresentInfo->pSwapchains[i]; - _surfaceImages.push_back(mvkSC->getImage(pPresentInfo->pImageIndices[i])); + _presentableImages.push_back(mvkSC->getPresentableImage(pPresentInfo->pImageIndices[i])); // Surface loss takes precedence over out-of-date errors. if (mvkSC->getIsSurfaceLost()) { setConfigurationResult(VK_ERROR_SURFACE_LOST_KHR); diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h index 8b88c6441..8a3304594 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h @@ -42,10 +42,10 @@ class MVKSwapchain : public MVKVulkanAPIDeviceObject { VkDebugReportObjectTypeEXT getVkDebugReportObjectType() override { return VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT; } /** Returns the number of images in this swapchain. */ - inline uint32_t getImageCount() { return (uint32_t)_surfaceImages.size(); } + inline uint32_t getImageCount() { return (uint32_t)_presentableImages.size(); } /** Returns the image at the specified index. */ - inline MVKSwapchainImage* getImage(uint32_t index) { return _surfaceImages[index]; } + inline MVKPresentableSwapchainImage* getPresentableImage(uint32_t index) { return _presentableImages[index]; } /** * Returns the array of presentable images associated with this swapchain. @@ -89,7 +89,7 @@ class MVKSwapchain : public MVKVulkanAPIDeviceObject { ~MVKSwapchain() override; protected: - friend class MVKSwapchainImage; + friend class MVKPresentableSwapchainImage; void propogateDebugName() override; void initCAMetalLayer(const VkSwapchainCreateInfoKHR* pCreateInfo, uint32_t imgCnt); @@ -103,7 +103,7 @@ class MVKSwapchain : public MVKVulkanAPIDeviceObject { CAMetalLayer* _mtlLayer; MVKWatermark* _licenseWatermark; - MVKVectorInline _surfaceImages; + MVKVectorInline _presentableImages; std::atomic _currentAcquisitionID; CGSize _mtlLayerOrigDrawSize; MVKSwapchainPerformance _performanceStatistics; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm index 13041b34c..ddf6d27f0 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm @@ -40,10 +40,10 @@ void MVKSwapchain::propogateDebugName() { if (_debugName) { - size_t imgCnt = _surfaceImages.size(); + size_t imgCnt = _presentableImages.size(); for (size_t imgIdx = 0; imgIdx < imgCnt; imgIdx++) { NSString* nsName = [[NSString alloc] initWithFormat: @"%@(%lu)", _debugName, imgIdx]; // temp retain - _surfaceImages[imgIdx]->setDebugName(nsName.UTF8String); + _presentableImages[imgIdx]->setDebugName(nsName.UTF8String); [nsName release]; // release temp string } } @@ -66,7 +66,7 @@ // Now populate the images for (uint32_t imgIdx = 0; imgIdx < *pCount; imgIdx++) { - pSwapchainImages[imgIdx] = (VkImage)_surfaceImages[imgIdx]; + pSwapchainImages[imgIdx] = (VkImage)_presentableImages[imgIdx]; } return result; @@ -81,11 +81,11 @@ if ( getIsSurfaceLost() ) { return VK_ERROR_SURFACE_LOST_KHR; } // Find the image that has the shortest wait by finding the smallest availability measure. - MVKSwapchainImage* minWaitImage = nullptr; + MVKPresentableSwapchainImage* minWaitImage = nullptr; MVKSwapchainImageAvailability minAvailability = { kMVKUndefinedLargeUInt64, false }; uint32_t imgCnt = getImageCount(); for (uint32_t imgIdx = 0; imgIdx < imgCnt; imgIdx++) { - MVKSwapchainImage* img = getImage(imgIdx); + auto* img = getPresentableImage(imgIdx); auto imgAvail = img->getAvailability(); if (imgAvail < minAvailability) { minAvailability = imgAvail; @@ -382,7 +382,7 @@ static inline CIE1931XY VkXYColorEXTToCIE1931XY(VkXYColorEXT xy) { } for (uint32_t imgIdx = 0; imgIdx < imgCnt; imgIdx++) { - _surfaceImages.push_back(_device->createSwapchainImage(&imgInfo, this, imgIdx, NULL)); + _presentableImages.push_back(_device->createPresentableSwapchainImage(&imgInfo, this, imgIdx, NULL)); } MVKLogInfo("Created %d swapchain images with initial size (%d, %d).", imgCnt, imgExtent.width, imgExtent.height); @@ -403,7 +403,7 @@ static inline CIE1931XY VkXYColorEXTToCIE1931XY(VkXYColorEXT xy) { } MVKSwapchain::~MVKSwapchain() { - for (auto& img : _surfaceImages) { _device->destroySwapchainImage(img, NULL); } + for (auto& img : _presentableImages) { _device->destroyPresentableSwapchainImage(img, NULL); } if (_licenseWatermark) { _licenseWatermark->destroy(); } [this->_layerObserver release]; From a644c98864a868352d3ea5b1529927b940bca506 Mon Sep 17 00:00:00 2001 From: Bill Hollings Date: Sun, 5 Apr 2020 20:44:44 -0400 Subject: [PATCH 5/5] Disable API-Samples demos and document in Demos/README.md. --- Demos/Demos.xcworkspace/contents.xcworkspacedata | 3 --- Demos/README.md | 11 ++++++++--- Docs/Whats_New.md | 1 + 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Demos/Demos.xcworkspace/contents.xcworkspacedata b/Demos/Demos.xcworkspace/contents.xcworkspacedata index 87886c356..c306685bc 100644 --- a/Demos/Demos.xcworkspace/contents.xcworkspacedata +++ b/Demos/Demos.xcworkspace/contents.xcworkspacedata @@ -7,9 +7,6 @@ - - diff --git a/Demos/README.md b/Demos/README.md index bf32a4bc5..3b33c84e8 100644 --- a/Demos/README.md +++ b/Demos/README.md @@ -64,7 +64,12 @@ as a system library instead. ### *API-Samples* -This *Xcode* project actually contains a large number of modular demos, with each demo +> **_Note:_** The `Vulkan-Samples API-Samples` have recently changed to use a different build + process that involves converting GLSL to SPIR-V via scripts. This upgrade has not yet been + integrated into the *Xcode*-based build environment used to build these demos here. + As a result, the `API-Samples` demos have been disabled here until this can be corrected. + +This *Xcode* project contains a large number of modular demos, with each demo demonstrating a particular *Vulkan* feature, or suite of calls. This demo can be found in the `LunarG-VulkanSamples/API-Samples` folder, and in the @@ -77,7 +82,7 @@ To specify which of the many modular demos to run, open the `Samples.h` in the ` project in the *Xcode Project Navigator* in the `Demos.xcworkspace` *Xcode* workspace, and follow the instructions in the comments within that file. -> **Note:** For simplicity, the `API-Samples` demos are bare-bones. Each of the `API-Samples` +> **_Note:_** For simplicity, the `API-Samples` demos are bare-bones. Each of the `API-Samples` > demos renders a single frame during app startup, and then leaves the rendered image static. > There is no display loop or motion in any of these demos. > **This is normal for these demos, and the demo has not "hung" or "crashed" when this occurs.** @@ -91,7 +96,7 @@ The `API-Samples` demo is a simple example of installing **MoltenVK** as a *stat ### *Hologram* -> **Note:** In order to build the `Hologram` demo, you must have *Python3* installed +> **_Note:_** In order to build the `Hologram` demo, you must have *Python3* installed > on your build computer. This is a sophisticated particle demo that populates command buffers from multiple threads. diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index 92649bccf..18df43410 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -38,6 +38,7 @@ Released 2020/04/05 - Update the `README.md` and `MoltenVK_Runtime_UserGuide.md` documents to clarify that **MoltenVK** is not a fully-compliant implementation of *Vulkan*. - Support Xcode 11.4. +- Disable `API-Samples` demos and document in `Demos/README.md`. - Update dependency libraries to match *Vulkan SDK 1.2.135*. - Update to latest SPIRV-Cross version: - MSL: Support inline uniform blocks in argument buffers.