Merge pull request #852 from billhollings/master
Various fixes resulting from testing for SDK release.
This commit is contained in:
commit
1a25de5500
3
Demos/Demos.xcworkspace/contents.xcworkspacedata
generated
3
Demos/Demos.xcworkspace/contents.xcworkspacedata
generated
@ -7,9 +7,6 @@
|
||||
<Group
|
||||
location = "container:"
|
||||
name = "LunarG-VulkanSamples">
|
||||
<FileRef
|
||||
location = "group:LunarG-VulkanSamples/API-Samples/API-Samples.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:LunarG-VulkanSamples/Cube/Cube.xcodeproj">
|
||||
</FileRef>
|
||||
|
@ -64,7 +64,12 @@ as a system library instead.
|
||||
<a name="lunarg-vulkan-samples-api"></a>
|
||||
### *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
|
||||
<a name="lunarg-vulkan-samples-hologram"></a>
|
||||
### *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.
|
||||
|
@ -32,11 +32,13 @@ 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
|
||||
**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.
|
||||
|
@ -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 */,
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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 @@ public:
|
||||
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);
|
||||
|
@ -773,7 +773,15 @@ MVKPhysicalDevice::MVKPhysicalDevice(MVKInstance* mvkInstance, id<MTLDevice> mtl
|
||||
|
||||
// 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 @@ void MVKPhysicalDevice::initMetalFeatures() {
|
||||
|
||||
if ( mvkOSVersionIsAtLeast(13.0) ) {
|
||||
_metalFeatures.mslVersionEnum = MTLLanguageVersion2_2;
|
||||
_metalFeatures.placementHeaps = true;
|
||||
_metalFeatures.placementHeaps = useMTLHeaps;
|
||||
if (supportsMTLGPUFamily(Apple4)) {
|
||||
_metalFeatures.nativeTextureSwizzle = true;
|
||||
}
|
||||
@ -904,7 +912,7 @@ void MVKPhysicalDevice::initMetalFeatures() {
|
||||
_metalFeatures.native3DCompressedTextures = true;
|
||||
if (supportsMTLGPUFamily(Mac2)) {
|
||||
_metalFeatures.nativeTextureSwizzle = true;
|
||||
_metalFeatures.placementHeaps = true;
|
||||
_metalFeatures.placementHeaps = useMTLHeaps;
|
||||
}
|
||||
}
|
||||
|
||||
@ -957,7 +965,6 @@ void MVKPhysicalDevice::initMetalFeatures() {
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Initializes the physical device features of this instance.
|
||||
@ -2131,7 +2138,7 @@ MVKImage* MVKDevice::createImage(const VkImageCreateInfo* pCreateInfo,
|
||||
}
|
||||
}
|
||||
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));
|
||||
}
|
||||
@ -2162,15 +2169,15 @@ void MVKDevice::destroySwapchain(MVKSwapchain* mvkSwpChn,
|
||||
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();
|
||||
}
|
||||
@ -2656,10 +2663,9 @@ void MVKDevice::initPhysicalDevice(MVKPhysicalDevice* physicalDevice, const VkDe
|
||||
}
|
||||
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
|
||||
|
@ -147,7 +147,7 @@ public:
|
||||
#pragma mark Metal
|
||||
|
||||
/** Returns the Metal texture underlying this image. */
|
||||
id<MTLTexture> getMTLTexture();
|
||||
virtual id<MTLTexture> getMTLTexture();
|
||||
|
||||
/** Returns a Metal texture that interprets the pixels in the specified format. */
|
||||
id<MTLTexture> getMTLTexture(MTLPixelFormat mtlPixFmt);
|
||||
@ -235,9 +235,9 @@ protected:
|
||||
bool validateUseTexelBuffer();
|
||||
void initSubresources(const VkImageCreateInfo* pCreateInfo);
|
||||
void initSubresourceLayout(MVKImageSubresource& imgSubRez);
|
||||
virtual id<MTLTexture> newMTLTexture();
|
||||
void resetMTLTexture();
|
||||
void resetIOSurface();
|
||||
id<MTLTexture> newMTLTexture();
|
||||
void releaseMTLTexture();
|
||||
void releaseIOSurface();
|
||||
MTLTextureDescriptor* newMTLTextureDescriptor();
|
||||
void updateMTLTextureContent(MVKImageSubresource& subresource, VkDeviceSize offset, VkDeviceSize size);
|
||||
void getMTLTextureContent(MVKImageSubresource& subresource, VkDeviceSize offset, VkDeviceSize size);
|
||||
@ -274,10 +274,44 @@ protected:
|
||||
#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<MTLTexture> 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<CAMetalDrawable> 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. */
|
||||
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;
|
||||
@ -287,18 +321,11 @@ typedef struct MVKSwapchainImageAvailability {
|
||||
typedef std::pair<MVKSemaphore*, MVKFence*> 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
|
||||
|
||||
/**
|
||||
@ -315,30 +342,27 @@ public:
|
||||
#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<MTLTexture> newMTLTexture() override;
|
||||
id<CAMetalDrawable> getCAMetalDrawable();
|
||||
void resetMetalDrawable();
|
||||
id<CAMetalDrawable> getCAMetalDrawable() override;
|
||||
void releaseMetalDrawable();
|
||||
MVKSwapchainImageAvailability getAvailability();
|
||||
void makeAvailable();
|
||||
void signalWhenAvailable(MVKSemaphore* semaphore, MVKFence* fence);
|
||||
void acquireAndSignalWhenAvailable(MVKSemaphore* semaphore, MVKFence* fence);
|
||||
void signal(MVKSwapchainSignaler& signaler, id<MTLCommandBuffer> mtlCmdBuff);
|
||||
void signalPresentationSemaphore(id<MTLCommandBuffer> mtlCmdBuff);
|
||||
static void markAsTracked(MVKSwapchainSignaler& signaler);
|
||||
static void unmarkAsTracked(MVKSwapchainSignaler& signaler);
|
||||
void renderWatermark(id<MTLCommandBuffer> mtlCmdBuff);
|
||||
|
||||
MVKSwapchain* _swapchain;
|
||||
uint32_t _swapchainIndex;
|
||||
id<CAMetalDrawable> _mtlDrawable;
|
||||
MVKSwapchainImageAvailability _availability;
|
||||
MVKVectorInline<MVKSwapchainSignaler, 1> _availabilitySignalers;
|
||||
@ -347,6 +371,32 @@ protected:
|
||||
};
|
||||
|
||||
|
||||
#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<CAMetalDrawable> getCAMetalDrawable() override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark MVKImageView
|
||||
|
||||
|
@ -298,34 +298,6 @@ id<MTLTexture> MVKImage::getMTLTexture(MTLPixelFormat mtlPixFmt) {
|
||||
return mtlTex;
|
||||
}
|
||||
|
||||
VkResult MVKImage::setMTLTexture(id<MTLTexture> mtlTexture) {
|
||||
lock_guard<mutex> lock(_lock);
|
||||
resetMTLTexture();
|
||||
resetIOSurface();
|
||||
|
||||
_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<MTLTexture> MVKImage::newMTLTexture() {
|
||||
id<MTLTexture> mtlTex = nil;
|
||||
MTLTextureDescriptor* mtlTexDesc = newMTLTextureDescriptor(); // temp retain
|
||||
@ -348,15 +320,41 @@ id<MTLTexture> MVKImage::newMTLTexture() {
|
||||
return mtlTex;
|
||||
}
|
||||
|
||||
VkResult MVKImage::setMTLTexture(id<MTLTexture> mtlTexture) {
|
||||
lock_guard<mutex> 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::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 +370,8 @@ VkResult MVKImage::useIOSurface(IOSurfaceRef ioSurface) {
|
||||
|
||||
#if MVK_SUPPORT_IOSURFACE_BOOL
|
||||
|
||||
resetMTLTexture();
|
||||
resetIOSurface();
|
||||
releaseMTLTexture();
|
||||
releaseIOSurface();
|
||||
|
||||
MVKPixelFormats* pixFmts = getPixelFormats();
|
||||
|
||||
@ -788,8 +786,8 @@ void MVKImage::initSubresourceLayout(MVKImageSubresource& imgSubRez) {
|
||||
|
||||
MVKImage::~MVKImage() {
|
||||
if (_deviceMemory) { _deviceMemory->removeImage(this); }
|
||||
resetMTLTexture();
|
||||
resetIOSurface();
|
||||
releaseMTLTexture();
|
||||
releaseIOSurface();
|
||||
}
|
||||
|
||||
|
||||
@ -800,37 +798,34 @@ 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<MTLTexture> 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;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark MVKPresentableSwapchainImage
|
||||
|
||||
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() {
|
||||
MVKSwapchainImageAvailability MVKPresentableSwapchainImage::getAvailability() {
|
||||
lock_guard<mutex> lock(_availabilityLock);
|
||||
|
||||
return _availability;
|
||||
@ -839,7 +834,7 @@ MVKSwapchainImageAvailability MVKSwapchainImage::getAvailability() {
|
||||
// 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<mutex> lock(_availabilityLock);
|
||||
|
||||
// Mark when this event happened, relative to that of other images
|
||||
@ -870,9 +865,13 @@ void MVKSwapchainImage::makeAvailable() {
|
||||
// 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 MVKPresentableSwapchainImage::acquireAndSignalWhenAvailable(MVKSemaphore* semaphore, MVKFence* fence) {
|
||||
lock_guard<mutex> 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;
|
||||
@ -899,7 +898,7 @@ void MVKSwapchainImage::signalWhenAvailable(MVKSemaphore* semaphore, MVKFence* f
|
||||
}
|
||||
|
||||
// If present, signal the semaphore for the first waiter for the given image.
|
||||
void MVKSwapchainImage::signalPresentationSemaphore(id<MTLCommandBuffer> mtlCmdBuff) {
|
||||
void MVKPresentableSwapchainImage::signalPresentationSemaphore(id<MTLCommandBuffer> mtlCmdBuff) {
|
||||
lock_guard<mutex> lock(_availabilityLock);
|
||||
|
||||
if ( !_availabilitySignalers.empty() ) {
|
||||
@ -909,19 +908,19 @@ void MVKSwapchainImage::signalPresentationSemaphore(id<MTLCommandBuffer> mtlCmdB
|
||||
}
|
||||
|
||||
// Signal either or both of the semaphore and fence in the specified tracker pair.
|
||||
void MVKSwapchainImage::signal(MVKSwapchainSignaler& signaler, id<MTLCommandBuffer> mtlCmdBuff) {
|
||||
void MVKPresentableSwapchainImage::signal(MVKSwapchainSignaler& signaler, id<MTLCommandBuffer> 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(); }
|
||||
}
|
||||
@ -929,19 +928,13 @@ void MVKSwapchainImage::unmarkAsTracked(MVKSwapchainSignaler& signaler) {
|
||||
|
||||
#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<MTLTexture> MVKSwapchainImage::newMTLTexture() {
|
||||
return [[getCAMetalDrawable() texture] retain];
|
||||
}
|
||||
|
||||
id<CAMetalDrawable> MVKSwapchainImage::getCAMetalDrawable() {
|
||||
id<CAMetalDrawable> MVKPresentableSwapchainImage::getCAMetalDrawable() {
|
||||
while ( !_mtlDrawable ) {
|
||||
@autoreleasepool { // Reclaim auto-released drawable object before end of loop
|
||||
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);
|
||||
}
|
||||
@ -950,7 +943,7 @@ id<CAMetalDrawable> MVKSwapchainImage::getCAMetalDrawable() {
|
||||
}
|
||||
|
||||
// Present the drawable and make myself available only once the command buffer has completed.
|
||||
void MVKSwapchainImage::presentCAMetalDrawable(id<MTLCommandBuffer> mtlCmdBuff) {
|
||||
void MVKPresentableSwapchainImage::presentCAMetalDrawable(id<MTLCommandBuffer> mtlCmdBuff) {
|
||||
_swapchain->willPresentSurface(getMTLTexture(), mtlCmdBuff);
|
||||
|
||||
NSString* scName = _swapchain->getDebugName();
|
||||
@ -968,8 +961,8 @@ void MVKSwapchainImage::presentCAMetalDrawable(id<MTLCommandBuffer> mtlCmdBuff)
|
||||
}
|
||||
|
||||
// Resets the MTLTexture and CAMetalDrawable underlying this image.
|
||||
void MVKSwapchainImage::resetMetalDrawable() {
|
||||
resetMTLTexture(); // Release texture first so drawable will be last to release it
|
||||
void MVKPresentableSwapchainImage::releaseMetalDrawable() {
|
||||
releaseMTLTexture(); // Release texture first so drawable will be last to release it
|
||||
[_mtlDrawable release];
|
||||
_mtlDrawable = nil;
|
||||
}
|
||||
@ -977,12 +970,12 @@ void MVKSwapchainImage::resetMetalDrawable() {
|
||||
|
||||
#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();
|
||||
@ -990,11 +983,52 @@ MVKSwapchainImage::MVKSwapchainImage(MVKDevice* device,
|
||||
_preSignaler = make_pair(nullptr, nullptr);
|
||||
}
|
||||
|
||||
MVKSwapchainImage::~MVKSwapchainImage() {
|
||||
resetMetalDrawable();
|
||||
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<CAMetalDrawable> 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
|
||||
|
||||
|
@ -289,7 +289,7 @@ static NSArray<id<MTLDevice>>* availableMTLDevicesArray() {
|
||||
#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
|
||||
|
@ -228,6 +228,6 @@ public:
|
||||
protected:
|
||||
id<MTLCommandBuffer> getMTLCommandBuffer();
|
||||
|
||||
MVKVectorInline<MVKSwapchainImage*, 4> _surfaceImages;
|
||||
MVKVectorInline<MVKPresentableSwapchainImage*, 4> _presentableImages;
|
||||
};
|
||||
|
||||
|
@ -339,7 +339,7 @@ void MVKQueuePresentSurfaceSubmission::execute() {
|
||||
// The semaphores know what to do.
|
||||
id<MTLCommandBuffer> 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 @@ MVKQueuePresentSurfaceSubmission::MVKQueuePresentSurfaceSubmission(MVKQueue* que
|
||||
: 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);
|
||||
|
@ -42,10 +42,10 @@ public:
|
||||
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 @@ public:
|
||||
~MVKSwapchain() override;
|
||||
|
||||
protected:
|
||||
friend class MVKSwapchainImage;
|
||||
friend class MVKPresentableSwapchainImage;
|
||||
|
||||
void propogateDebugName() override;
|
||||
void initCAMetalLayer(const VkSwapchainCreateInfoKHR* pCreateInfo, uint32_t imgCnt);
|
||||
@ -103,7 +103,7 @@ protected:
|
||||
|
||||
CAMetalLayer* _mtlLayer;
|
||||
MVKWatermark* _licenseWatermark;
|
||||
MVKVectorInline<MVKSwapchainImage*, kMVKMaxSwapchainImageCount> _surfaceImages;
|
||||
MVKVectorInline<MVKPresentableSwapchainImage*, kMVKMaxSwapchainImageCount> _presentableImages;
|
||||
std::atomic<uint64_t> _currentAcquisitionID;
|
||||
CGSize _mtlLayerOrigDrawSize;
|
||||
MVKSwapchainPerformance _performanceStatistics;
|
||||
|
@ -40,10 +40,10 @@ using namespace std;
|
||||
|
||||
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 @@ VkResult MVKSwapchain::getImages(uint32_t* pCount, VkImage* pSwapchainImages) {
|
||||
|
||||
// Now populate the images
|
||||
for (uint32_t imgIdx = 0; imgIdx < *pCount; imgIdx++) {
|
||||
pSwapchainImages[imgIdx] = (VkImage)_surfaceImages[imgIdx];
|
||||
pSwapchainImages[imgIdx] = (VkImage)_presentableImages[imgIdx];
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -80,14 +80,12 @@ VkResult MVKSwapchain::acquireNextImageKHR(uint64_t timeout,
|
||||
|
||||
if ( getIsSurfaceLost() ) { return VK_ERROR_SURFACE_LOST_KHR; }
|
||||
|
||||
// Find the image that has the smallest availability measure
|
||||
MVKSwapchainImage* minWaitImage = nullptr;
|
||||
MVKSwapchainImageAvailability minAvailability = { .acquisitionID = kMVKUndefinedLargeUInt64,
|
||||
.waitCount = kMVKUndefinedLargeUInt32,
|
||||
.isAvailable = false };
|
||||
// Find the image that has the shortest wait by finding the smallest availability measure.
|
||||
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;
|
||||
@ -95,10 +93,10 @@ VkResult MVKSwapchain::acquireNextImageKHR(uint64_t timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
@ -384,7 +382,7 @@ void MVKSwapchain::initSurfaceImages(const VkSwapchainCreateInfoKHR* pCreateInfo
|
||||
}
|
||||
|
||||
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);
|
||||
@ -405,7 +403,7 @@ void MVKSwapchain::initFrameIntervalTracking() {
|
||||
}
|
||||
|
||||
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];
|
||||
|
Loading…
x
Reference in New Issue
Block a user