Add workaround for apps that use one semaphore for all swapchain images.
Support deferred secondary signaling of semaphore & fence acquired while image is free. Add MVKBaseObject::destroy() function to support customization of object destruction. Support deferred destruction of MVKSemaphore & MVKFence instances.
This commit is contained in:
parent
4c746bb288
commit
793f3fdaf3
@ -1037,7 +1037,8 @@ MVKBuffer* MVKDevice::createBuffer(const VkBufferCreateInfo* pCreateInfo,
|
||||
|
||||
void MVKDevice::destroyBuffer(MVKBuffer* mvkBuff,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete removeResource(mvkBuff);
|
||||
removeResource(mvkBuff);
|
||||
mvkBuff->destroy();
|
||||
}
|
||||
|
||||
MVKBufferView* MVKDevice::createBufferView(const VkBufferViewCreateInfo* pCreateInfo,
|
||||
@ -1047,7 +1048,7 @@ MVKBufferView* MVKDevice::createBufferView(const VkBufferViewCreateInfo* pCreate
|
||||
|
||||
void MVKDevice::destroyBufferView(MVKBufferView* mvkBuffView,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkBuffView;
|
||||
mvkBuffView->destroy();
|
||||
}
|
||||
|
||||
MVKImage* MVKDevice::createImage(const VkImageCreateInfo* pCreateInfo,
|
||||
@ -1057,7 +1058,8 @@ MVKImage* MVKDevice::createImage(const VkImageCreateInfo* pCreateInfo,
|
||||
|
||||
void MVKDevice::destroyImage(MVKImage* mvkImg,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete removeResource(mvkImg);
|
||||
removeResource(mvkImg);
|
||||
mvkImg->destroy();
|
||||
}
|
||||
|
||||
MVKImageView* MVKDevice::createImageView(const VkImageViewCreateInfo* pCreateInfo,
|
||||
@ -1067,7 +1069,7 @@ MVKImageView* MVKDevice::createImageView(const VkImageViewCreateInfo* pCreateInf
|
||||
|
||||
void MVKDevice::destroyImageView(MVKImageView* mvkImgView,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkImgView;
|
||||
mvkImgView->destroy();
|
||||
}
|
||||
|
||||
MVKSwapchain* MVKDevice::createSwapchain(const VkSwapchainCreateInfoKHR* pCreateInfo,
|
||||
@ -1077,7 +1079,7 @@ MVKSwapchain* MVKDevice::createSwapchain(const VkSwapchainCreateInfoKHR* pCreate
|
||||
|
||||
void MVKDevice::destroySwapchain(MVKSwapchain* mvkSwpChn,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkSwpChn;
|
||||
mvkSwpChn->destroy();
|
||||
}
|
||||
|
||||
MVKSwapchainImage* MVKDevice::createSwapchainImage(const VkImageCreateInfo* pCreateInfo,
|
||||
@ -1088,7 +1090,8 @@ MVKSwapchainImage* MVKDevice::createSwapchainImage(const VkImageCreateInfo* pCre
|
||||
|
||||
void MVKDevice::destroySwapchainImage(MVKSwapchainImage* mvkImg,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete removeResource(mvkImg);
|
||||
removeResource(mvkImg);
|
||||
mvkImg->destroy();
|
||||
}
|
||||
|
||||
MVKFence* MVKDevice::createFence(const VkFenceCreateInfo* pCreateInfo,
|
||||
@ -1098,7 +1101,7 @@ MVKFence* MVKDevice::createFence(const VkFenceCreateInfo* pCreateInfo,
|
||||
|
||||
void MVKDevice::destroyFence(MVKFence* mvkFence,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkFence;
|
||||
mvkFence->destroy();
|
||||
}
|
||||
|
||||
MVKSemaphore* MVKDevice::createSemaphore(const VkSemaphoreCreateInfo* pCreateInfo,
|
||||
@ -1108,7 +1111,7 @@ MVKSemaphore* MVKDevice::createSemaphore(const VkSemaphoreCreateInfo* pCreateInf
|
||||
|
||||
void MVKDevice::destroySemaphore(MVKSemaphore* mvkSem4,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkSem4;
|
||||
mvkSem4->destroy();
|
||||
}
|
||||
|
||||
MVKQueryPool* MVKDevice::createQueryPool(const VkQueryPoolCreateInfo* pCreateInfo,
|
||||
@ -1127,7 +1130,7 @@ MVKQueryPool* MVKDevice::createQueryPool(const VkQueryPoolCreateInfo* pCreateInf
|
||||
|
||||
void MVKDevice::destroyQueryPool(MVKQueryPool* mvkQP,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkQP;
|
||||
mvkQP->destroy();
|
||||
}
|
||||
|
||||
MVKShaderModule* MVKDevice::createShaderModule(const VkShaderModuleCreateInfo* pCreateInfo,
|
||||
@ -1137,7 +1140,7 @@ MVKShaderModule* MVKDevice::createShaderModule(const VkShaderModuleCreateInfo* p
|
||||
|
||||
void MVKDevice::destroyShaderModule(MVKShaderModule* mvkShdrMod,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkShdrMod;
|
||||
mvkShdrMod->destroy();
|
||||
}
|
||||
|
||||
MVKPipelineCache* MVKDevice::createPipelineCache(const VkPipelineCacheCreateInfo* pCreateInfo,
|
||||
@ -1147,7 +1150,7 @@ MVKPipelineCache* MVKDevice::createPipelineCache(const VkPipelineCacheCreateInfo
|
||||
|
||||
void MVKDevice::destroyPipelineCache(MVKPipelineCache* mvkPLC,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkPLC;
|
||||
mvkPLC->destroy();
|
||||
}
|
||||
|
||||
MVKPipelineLayout* MVKDevice::createPipelineLayout(const VkPipelineLayoutCreateInfo* pCreateInfo,
|
||||
@ -1157,7 +1160,7 @@ MVKPipelineLayout* MVKDevice::createPipelineLayout(const VkPipelineLayoutCreateI
|
||||
|
||||
void MVKDevice::destroyPipelineLayout(MVKPipelineLayout* mvkPLL,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkPLL;
|
||||
mvkPLL->destroy();
|
||||
}
|
||||
|
||||
template<typename PipelineType, typename PipelineInfoType>
|
||||
@ -1193,7 +1196,7 @@ VkResult MVKDevice::createPipelines(VkPipelineCache pipelineCache,
|
||||
} else {
|
||||
rslt = plRslt;
|
||||
pPipelines[plIdx] = VK_NULL_HANDLE;
|
||||
delete mvkPL;
|
||||
mvkPL->destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1218,7 +1221,7 @@ template VkResult MVKDevice::createPipelines<MVKComputePipeline, VkComputePipeli
|
||||
|
||||
void MVKDevice::destroyPipeline(MVKPipeline* mvkPL,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkPL;
|
||||
mvkPL->destroy();
|
||||
}
|
||||
|
||||
MVKSampler* MVKDevice::createSampler(const VkSamplerCreateInfo* pCreateInfo,
|
||||
@ -1228,7 +1231,7 @@ MVKSampler* MVKDevice::createSampler(const VkSamplerCreateInfo* pCreateInfo,
|
||||
|
||||
void MVKDevice::destroySampler(MVKSampler* mvkSamp,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkSamp;
|
||||
mvkSamp->destroy();
|
||||
}
|
||||
|
||||
MVKDescriptorSetLayout* MVKDevice::createDescriptorSetLayout(const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
|
||||
@ -1238,7 +1241,7 @@ MVKDescriptorSetLayout* MVKDevice::createDescriptorSetLayout(const VkDescriptorS
|
||||
|
||||
void MVKDevice::destroyDescriptorSetLayout(MVKDescriptorSetLayout* mvkDSL,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkDSL;
|
||||
mvkDSL->destroy();
|
||||
}
|
||||
|
||||
MVKDescriptorPool* MVKDevice::createDescriptorPool(const VkDescriptorPoolCreateInfo* pCreateInfo,
|
||||
@ -1248,7 +1251,7 @@ MVKDescriptorPool* MVKDevice::createDescriptorPool(const VkDescriptorPoolCreateI
|
||||
|
||||
void MVKDevice::destroyDescriptorPool(MVKDescriptorPool* mvkDP,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkDP;
|
||||
mvkDP->destroy();
|
||||
}
|
||||
|
||||
MVKFramebuffer* MVKDevice::createFramebuffer(const VkFramebufferCreateInfo* pCreateInfo,
|
||||
@ -1258,7 +1261,7 @@ MVKFramebuffer* MVKDevice::createFramebuffer(const VkFramebufferCreateInfo* pCre
|
||||
|
||||
void MVKDevice::destroyFramebuffer(MVKFramebuffer* mvkFB,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkFB;
|
||||
mvkFB->destroy();
|
||||
}
|
||||
|
||||
MVKRenderPass* MVKDevice::createRenderPass(const VkRenderPassCreateInfo* pCreateInfo,
|
||||
@ -1268,7 +1271,7 @@ MVKRenderPass* MVKDevice::createRenderPass(const VkRenderPassCreateInfo* pCreate
|
||||
|
||||
void MVKDevice::destroyRenderPass(MVKRenderPass* mvkRP,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkRP;
|
||||
mvkRP->destroy();
|
||||
}
|
||||
|
||||
MVKCommandPool* MVKDevice::createCommandPool(const VkCommandPoolCreateInfo* pCreateInfo,
|
||||
@ -1278,7 +1281,7 @@ MVKCommandPool* MVKDevice::createCommandPool(const VkCommandPoolCreateInfo* pCre
|
||||
|
||||
void MVKDevice::destroyCommandPool(MVKCommandPool* mvkCmdPool,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkCmdPool;
|
||||
mvkCmdPool->destroy();
|
||||
}
|
||||
|
||||
MVKDeviceMemory* MVKDevice::allocateMemory(const VkMemoryAllocateInfo* pAllocateInfo,
|
||||
@ -1288,7 +1291,7 @@ MVKDeviceMemory* MVKDevice::allocateMemory(const VkMemoryAllocateInfo* pAllocate
|
||||
|
||||
void MVKDevice::freeMemory(MVKDeviceMemory* mvkDevMem,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
delete mvkDevMem;
|
||||
mvkDevMem->destroy();
|
||||
}
|
||||
|
||||
/** Adds the specified resource for tracking, and returns the added resource. */
|
||||
@ -1407,7 +1410,6 @@ uint32_t MVKDevice::expandVisibilityResultMTLBuffer(uint32_t queryCount) {
|
||||
#pragma mark Construction
|
||||
|
||||
MVKDevice::MVKDevice(MVKPhysicalDevice* physicalDevice, const VkDeviceCreateInfo* pCreateInfo) : _mvkConfig() {
|
||||
// MVKLogDebug("Creating MVKDevice. Elapsed time: %.6f ms.", mvkGetElapsedMilliseconds());
|
||||
|
||||
initPerformanceTracking();
|
||||
|
||||
@ -1485,7 +1487,7 @@ void MVKDevice::initPerformanceTracking() {
|
||||
MVKDevice::~MVKDevice() {
|
||||
mvkDestroyContainerContents(_queueFamilies);
|
||||
[_globalVisibilityResultMTLBuffer release];
|
||||
delete _commandResourceFactory;
|
||||
_commandResourceFactory->destroy();
|
||||
}
|
||||
|
||||
|
||||
|
@ -310,6 +310,9 @@ protected:
|
||||
#pragma mark -
|
||||
#pragma mark MVKSwapchainImage
|
||||
|
||||
/** Tracks a semaphore and fence for later signaling. */
|
||||
typedef std::pair<MVKSemaphore*, MVKFence*> MVKSwapchainSignaler;
|
||||
|
||||
/** Indicates the relative availability of each image in the swapchain. */
|
||||
typedef struct MVKSwapchainImageAvailability_t {
|
||||
uint64_t acquisitionID; /**< When this image was last made available, relative to the other images in the swapchain. Smaller value is earlier. */
|
||||
@ -327,14 +330,6 @@ public:
|
||||
/** Returns the index of this image within the encompassing swapchain. */
|
||||
inline uint32_t getSwapchainIndex() { return _swapchainIndex; }
|
||||
|
||||
/**
|
||||
* Makes this 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 makeAvailable();
|
||||
|
||||
/**
|
||||
* Registers a semaphore and/or fence that will be signaled when this image becomes available.
|
||||
* This function accepts both a semaphore and a fence, and either none, one, or both may be provided.
|
||||
@ -373,14 +368,18 @@ protected:
|
||||
id<CAMetalDrawable> getCAMetalDrawable();
|
||||
void resetCAMetalDrawable();
|
||||
void resetMetalSurface();
|
||||
void signal(std::pair<MVKSemaphore*, MVKFence*> tracker);
|
||||
void signal(MVKSwapchainSignaler& signaler);
|
||||
void markAsTracked(MVKSwapchainSignaler& signaler);
|
||||
void unmarkAsTracked(MVKSwapchainSignaler& signaler);
|
||||
void makeAvailable();
|
||||
void renderWatermark(id<MTLCommandBuffer> mtlCmdBuff);
|
||||
|
||||
MVKSwapchain* _swapchain;
|
||||
uint32_t _swapchainIndex;
|
||||
id<CAMetalDrawable> _mtlDrawable;
|
||||
std::mutex _availabilityLock;
|
||||
std::list<std::pair<MVKSemaphore*, MVKFence*>> _availabilityTrackers;
|
||||
std::list<MVKSwapchainSignaler> _availabilitySignalers;
|
||||
MVKSwapchainSignaler _preSignaled;
|
||||
MVKSwapchainImageAvailability _availability;
|
||||
};
|
||||
|
||||
|
@ -203,9 +203,6 @@ VkResult MVKImage::pullFromDevice(VkDeviceSize offset, VkDeviceSize size) {
|
||||
}
|
||||
|
||||
void* MVKImage::map(VkDeviceSize offset, VkDeviceSize size) {
|
||||
// MVKLogDebug("Comparing map to image %p with memory offset %d and size %d.", this, _deviceMemoryOffset, _byteCount);
|
||||
// if (doesContain(offset, size)) { MVKLogDebug("Mapping %d bytes to single image %p.", size, this); }
|
||||
|
||||
return (doesContain(offset, size)
|
||||
? _deviceMemory->allocateMappedMemory(offset, size)
|
||||
: VK_NULL_HANDLE);
|
||||
@ -773,54 +770,77 @@ bool MVKSwapchainImageAvailability_t::operator< (const MVKSwapchainImageAvailabi
|
||||
return acquisitionID < rhs.acquisitionID;
|
||||
}
|
||||
|
||||
// Makes this 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() {
|
||||
lock_guard<mutex> lock(_availabilityLock);
|
||||
|
||||
// Mark when this event happened, relative to that of other images
|
||||
_availability.acquisitionID = _swapchain->getNextAcquisitionID();
|
||||
|
||||
// If there are no availability trackers waiting, mark this image as available.
|
||||
// Otherwise, mark this image as unavailable, and extract and signal the first semaphore and fence.
|
||||
if ( _availabilityTrackers.empty() ) {
|
||||
_availability.isAvailable = true;
|
||||
// Mark this image as available if no semaphores or fences are waiting to be signaled.
|
||||
_availability.isAvailable = _availabilitySignalers.empty();
|
||||
|
||||
MVKSwapchainSignaler signaler;
|
||||
if (_availability.isAvailable) {
|
||||
// If this image is now available, signal the semaphore and fence that were associated
|
||||
// with the last time this image was acquired while available. This is a workaround for
|
||||
// when an app uses a single semaphore or fence for more than one swapchain image.
|
||||
// Becuase the semaphore or fence will be signaled by more than one image, it will
|
||||
// get out of sync, and the final use of the image would not be signaled as a result.
|
||||
|
||||
signaler = _preSignaled;
|
||||
} else {
|
||||
_availability.isAvailable = false;
|
||||
auto tracker = _availabilityTrackers.front();
|
||||
_availabilityTrackers.pop_front();
|
||||
signal(tracker);
|
||||
// If this image is not yet available, extract and signal the first semaphore and fence.
|
||||
|
||||
signaler = _availabilitySignalers.front();
|
||||
_availabilitySignalers.pop_front();
|
||||
}
|
||||
|
||||
// MVKLogDebug("Finished presentation of MVKSwapchainImage %p. Elapsed time: %.6f ms.", this, mvkGetElapsedMilliseconds());
|
||||
// Signal the semaphore and fence, and let them know they are no longer being tracked.
|
||||
signal(signaler);
|
||||
unmarkAsTracked(signaler);
|
||||
|
||||
// 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) {
|
||||
lock_guard<mutex> lock(_availabilityLock);
|
||||
// MVKLogDebug("Requesting signal when MVKSwapchain image %p is free to semaphore %p and fence %p.", this, semaphore, fence);
|
||||
auto tracker = make_pair(semaphore, fence);
|
||||
auto signaler = make_pair(semaphore, fence);
|
||||
if (_availability.isAvailable) {
|
||||
_availability.isAvailable = false;
|
||||
signal(tracker);
|
||||
signal(signaler);
|
||||
_preSignaled = signaler;
|
||||
} else {
|
||||
_availabilityTrackers.push_back(tracker);
|
||||
_availabilitySignalers.push_back(signaler);
|
||||
}
|
||||
markAsTracked(signaler);
|
||||
|
||||
// MVKLogDebug("%s swapchain image %p semaphore %p in acquire with %lu other semaphores.", (_availability.isAvailable ? "Signaling" : "Tracking"), this, semaphore, _availabilitySignalers.size());
|
||||
}
|
||||
|
||||
/** Signal either or both of the semaphore and fence in the specified tracker pair. */
|
||||
void MVKSwapchainImage::signal(pair<MVKSemaphore*, MVKFence*> tracker) {
|
||||
void MVKSwapchainImage::signal(MVKSwapchainSignaler& signaler) {
|
||||
if (signaler.first) { signaler.first->signal(); }
|
||||
if (signaler.second) { signaler.second->signal(); }
|
||||
}
|
||||
|
||||
MVKSemaphore* semaphore = tracker.first;
|
||||
if (semaphore) { semaphore->signal(); }
|
||||
// Tell the semaphore and fence that they are being tracked for future signaling.
|
||||
void MVKSwapchainImage::markAsTracked(MVKSwapchainSignaler& signaler) {
|
||||
if (signaler.first) { signaler.first->wasAddedToSignaler(); }
|
||||
if (signaler.second) { signaler.second->wasAddedToSignaler(); }
|
||||
}
|
||||
|
||||
MVKFence* fence = tracker.second;
|
||||
if (fence) { fence->signal(); }
|
||||
|
||||
// MVKLogDebug("MVKSwapchainImage %p signalling semaphore %p and fence %p.", this, semaphore, fence);
|
||||
// Tell the semaphore and fence that they are no longer being tracked for future signaling.
|
||||
void MVKSwapchainImage::unmarkAsTracked(MVKSwapchainSignaler& signaler) {
|
||||
if (signaler.first) { signaler.first->wasRemovedFromSignaler(); }
|
||||
if (signaler.second) { signaler.second->wasRemovedFromSignaler(); }
|
||||
}
|
||||
|
||||
const MVKSwapchainImageAvailability* MVKSwapchainImage::getAvailability() {
|
||||
lock_guard<mutex> lock(_availabilityLock);
|
||||
_availability.waitCount = (uint32_t)_availabilityTrackers.size();
|
||||
_availability.waitCount = (uint32_t)_availabilitySignalers.size();
|
||||
return &_availability;
|
||||
}
|
||||
|
||||
@ -833,12 +853,7 @@ const MVKSwapchainImageAvailability* MVKSwapchainImage::getAvailability() {
|
||||
* This implementation retrieves a MTLTexture from the CAMetalDrawable.
|
||||
*/
|
||||
id<MTLTexture> MVKSwapchainImage::newMTLTexture() {
|
||||
// return [[getCAMetalDrawable() texture] retain];
|
||||
id<CAMetalDrawable> mtlDrwbl = getCAMetalDrawable();
|
||||
id<MTLTexture> mtlTex = [[mtlDrwbl texture] retain];
|
||||
// MVKLogDebug("Retrieved MTLTexture %p from CAMetalDrawable %p in MVKSwapchain image: %p. Elapsed time: %.6f ms.",
|
||||
// mtlTex, mtlDrwbl, this, mvkGetElapsedMilliseconds());
|
||||
return mtlTex;
|
||||
return [[getCAMetalDrawable() texture] retain];
|
||||
}
|
||||
|
||||
id<CAMetalDrawable> MVKSwapchainImage::getCAMetalDrawable() {
|
||||
@ -847,15 +862,12 @@ id<CAMetalDrawable> MVKSwapchainImage::getCAMetalDrawable() {
|
||||
_mtlDrawable = [_swapchain->getNextCAMetalDrawable() retain]; // retained
|
||||
}
|
||||
MVKAssert(_mtlDrawable, "Could not aquire an available CAMetalDrawable from the CAMetalLayer in MVKSwapchain image: %p.", this);
|
||||
// MVKLogDebug("Retrieved CAMetalDrawable %p with retain count %d in MVKSwapchain image: %p. Elapsed time: %.6f ms.",
|
||||
// _mtlDrawable, _mtlDrawable.retainCount, this, mvkGetElapsedMilliseconds());
|
||||
}
|
||||
return _mtlDrawable;
|
||||
}
|
||||
|
||||
void MVKSwapchainImage::presentCAMetalDrawable(id<MTLCommandBuffer> mtlCmdBuff) {
|
||||
// MVKLogDebug("Presenting CAMetalDrawable: %s with retain count %d in MVKSwapchain image: %p. Elapsed time: %.6f ms.",
|
||||
// _mtlDrawable.description.UTF8String, _mtlDrawable.retainCount, this, mvkGetElapsedMilliseconds());
|
||||
// MVKLogDebug("Presenting swapchain image %p from present.", this);
|
||||
|
||||
id<CAMetalDrawable> mtlDrawable = getCAMetalDrawable();
|
||||
_swapchain->willPresentSurface(getMTLTexture(), mtlCmdBuff);
|
||||
@ -876,16 +888,12 @@ void MVKSwapchainImage::presentCAMetalDrawable(id<MTLCommandBuffer> mtlCmdBuff)
|
||||
|
||||
/** Removes and releases the Metal drawable object, so that it can be lazily created by getCAMetalDrawable(). */
|
||||
void MVKSwapchainImage::resetCAMetalDrawable() {
|
||||
// MVKLogDebug("Releasing MTLDrawable: %s with retain count %d in MVKSwapchain image: %p.",
|
||||
// _mtlDrawable.description.UTF8String, _mtlDrawable.retainCount, this);
|
||||
[_mtlDrawable release];
|
||||
_mtlDrawable = nil;
|
||||
}
|
||||
|
||||
/** Resets the MTLTexture and CAMetalDrawable underlying this image. */
|
||||
void MVKSwapchainImage::resetMetalSurface() {
|
||||
// MVKLogDebug("Resetting MTLTexture: %p and CAMetalDrawable %p in MVKSwapchain image: %p. Elapsed time: %.6f ms.",
|
||||
// _mtlTexture, _mtlDrawable, this, mvkGetElapsedMilliseconds());
|
||||
resetMTLTexture(); // Release texture first so drawable will be last to release it
|
||||
resetCAMetalDrawable();
|
||||
}
|
||||
@ -900,10 +908,9 @@ MVKSwapchainImage::MVKSwapchainImage(MVKDevice* device,
|
||||
_swapchainIndex = _swapchain->getImageCount();
|
||||
_availability.acquisitionID = _swapchain->getNextAcquisitionID();
|
||||
_availability.isAvailable = true;
|
||||
_preSignaled = make_pair(nullptr, nullptr);
|
||||
_mtlDrawable = nil;
|
||||
_canSupportMTLTextureView = false; // Override...swapchains never support Metal image view.
|
||||
|
||||
// MVKLogDebug("Created MVKSwapchain image %p.", this);
|
||||
}
|
||||
|
||||
MVKSwapchainImage::~MVKSwapchainImage() {
|
||||
|
@ -269,8 +269,12 @@ void MVKQueueSubmission::recordResult(VkResult vkResult) {
|
||||
#pragma mark -
|
||||
#pragma mark MVKQueueCommandBufferSubmission
|
||||
|
||||
std::atomic<uint32_t> _subCount;
|
||||
|
||||
void MVKQueueCommandBufferSubmission::execute() {
|
||||
|
||||
// MVKLogDebug("Executing submission %p.", this);
|
||||
|
||||
// Execute each command buffer, or if no command buffers, but a fence or semaphores,
|
||||
// create an empty MTLCommandBuffer to trigger the semaphores and fence.
|
||||
if ( !_cmdBuffers.empty() ) {
|
||||
@ -325,6 +329,8 @@ NSString* MVKQueueCommandBufferSubmission::getMTLCommandBufferName() {
|
||||
|
||||
void MVKQueueCommandBufferSubmission::finish() {
|
||||
|
||||
// MVKLogDebug("Finishing submission %p. Submission count %u.", this, _subCount--);
|
||||
|
||||
// Signal each of the signal semaphores.
|
||||
for (auto& ss : _signalSemaphores) { ss->signal(); }
|
||||
|
||||
@ -364,6 +370,8 @@ MVKQueueCommandBufferSubmission::MVKQueueCommandBufferSubmission(MVKDevice* devi
|
||||
_fence = (MVKFence*)fence;
|
||||
_cmdBuffUse= cmdBuffUse;
|
||||
_activeMTLCommandBuffer = nil;
|
||||
|
||||
// MVKLogDebug("Creating submission %p. Submission count %u.", this, ++_subCount);
|
||||
}
|
||||
|
||||
|
||||
|
@ -73,12 +73,9 @@ VkResult MVKSwapchain::acquireNextImageKHR(uint64_t timeout,
|
||||
minWaitIndex = mvkSCImg->getSwapchainIndex();
|
||||
}
|
||||
}
|
||||
// MVKLogDebug("Selected MVKSwapchainImage %p, index: %d to trigger semaphore %p and fence %p", _surfaceImages[minWaitIndex], minWaitIndex, semaphore, fence);
|
||||
|
||||
*pImageIndex = minWaitIndex; // Return the index of the image with the shortest wait
|
||||
|
||||
_surfaceImages[minWaitIndex]->signalWhenAvailable((MVKSemaphore*)semaphore, (MVKFence*)fence);
|
||||
|
||||
return getHasSurfaceSizeChanged() ? VK_SUBOPTIMAL_KHR : VK_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -96,11 +96,45 @@ private:
|
||||
};
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark MVKSignalable
|
||||
|
||||
/** Abstract class for Vulkan semaphores and fences. */
|
||||
class MVKSignalable : public MVKBaseDeviceObject {
|
||||
|
||||
public:
|
||||
|
||||
/* Called when this object has been added to a tracker for later signaling. */
|
||||
void wasAddedToSignaler();
|
||||
|
||||
/**
|
||||
* Called when this object has been removed from a tracker for later signaling.
|
||||
* If this object was destroyed while this signal was pending, it will now be deleted.
|
||||
*/
|
||||
void wasRemovedFromSignaler();
|
||||
|
||||
/** If this object is waiting to be signaled, deletion will be deferred until then. */
|
||||
void destroy() override;
|
||||
|
||||
|
||||
#pragma mark Construction
|
||||
|
||||
MVKSignalable(MVKDevice* device) : MVKBaseDeviceObject(device) {}
|
||||
|
||||
protected:
|
||||
void maybeDestroy();
|
||||
|
||||
std::mutex _signalerLock;
|
||||
uint32_t _signalerCount = 0;
|
||||
bool _isDestroyed = false;
|
||||
};
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark MVKSemaphore
|
||||
|
||||
/** Represents a Vulkan semaphore. */
|
||||
class MVKSemaphore : public MVKBaseDeviceObject {
|
||||
class MVKSemaphore : public MVKSignalable {
|
||||
|
||||
public:
|
||||
|
||||
@ -121,7 +155,7 @@ public:
|
||||
#pragma mark Construction
|
||||
|
||||
MVKSemaphore(MVKDevice* device, const VkSemaphoreCreateInfo* pCreateInfo)
|
||||
: MVKBaseDeviceObject(device), _blocker(false, 1) {}
|
||||
: MVKSignalable(device), _blocker(false, 1) {}
|
||||
|
||||
protected:
|
||||
MVKSemaphoreImpl _blocker;
|
||||
@ -132,7 +166,7 @@ protected:
|
||||
#pragma mark MVKFence
|
||||
|
||||
/** Represents a Vulkan fence. */
|
||||
class MVKFence : public MVKBaseDeviceObject {
|
||||
class MVKFence : public MVKSignalable {
|
||||
|
||||
public:
|
||||
|
||||
@ -165,7 +199,7 @@ public:
|
||||
|
||||
#pragma mark Construction
|
||||
|
||||
MVKFence(MVKDevice* device, const VkFenceCreateInfo* pCreateInfo) : MVKBaseDeviceObject(device),
|
||||
MVKFence(MVKDevice* device, const VkFenceCreateInfo* pCreateInfo) : MVKSignalable(device),
|
||||
_isSignaled(mvkAreFlagsEnabled(pCreateInfo->flags, VK_FENCE_CREATE_SIGNALED_BIT)) {}
|
||||
|
||||
~MVKFence() override;
|
||||
|
@ -31,7 +31,7 @@ void MVKSemaphoreImpl::release() {
|
||||
|
||||
// Either decrement the reservation counter, or clear it altogether
|
||||
if (_shouldWaitAll) {
|
||||
_reservationCount--;
|
||||
if (_reservationCount > 0) { _reservationCount--; }
|
||||
} else {
|
||||
_reservationCount = 0;
|
||||
}
|
||||
@ -65,6 +65,36 @@ bool MVKSemaphoreImpl::wait(uint64_t timeout, bool reserveAgain) {
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark MVKSignalable
|
||||
|
||||
void MVKSignalable::wasAddedToSignaler() {
|
||||
lock_guard<mutex> lock(_signalerLock);
|
||||
|
||||
_signalerCount++;
|
||||
}
|
||||
|
||||
void MVKSignalable::wasRemovedFromSignaler() {
|
||||
lock_guard<mutex> lock(_signalerLock);
|
||||
|
||||
if (_signalerCount > 0) { _signalerCount--; }
|
||||
maybeDestroy();
|
||||
}
|
||||
|
||||
void MVKSignalable::destroy() {
|
||||
lock_guard<mutex> lock(_signalerLock);
|
||||
|
||||
_isDestroyed = true;
|
||||
maybeDestroy();
|
||||
}
|
||||
|
||||
void MVKSignalable::maybeDestroy() {
|
||||
if (_isDestroyed && _signalerCount == 0) {
|
||||
MVKBaseDeviceObject::destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark MVKSemaphore
|
||||
|
||||
|
@ -37,6 +37,9 @@ public:
|
||||
/** Returns the name of the class of which this object is an instance. */
|
||||
std::string className();
|
||||
|
||||
/** Destroys this object. Default behaviour simply deletes it. Subclasses may override to delay deletion. */
|
||||
virtual void destroy() { delete this; }
|
||||
|
||||
virtual ~MVKBaseObject() {}
|
||||
};
|
||||
|
||||
|
@ -60,8 +60,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyInstance(
|
||||
VkInstance instance,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
|
||||
MVKInstance* mvkInst = MVKInstance::getMVKInstance(instance);
|
||||
delete mvkInst;
|
||||
MVKInstance::getMVKInstance(instance)->destroy();
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL VkResult vkEnumeratePhysicalDevices(
|
||||
@ -168,8 +167,7 @@ MVK_PUBLIC_SYMBOL void vkDestroyDevice(
|
||||
VkDevice device,
|
||||
const VkAllocationCallbacks* pAllocator) {
|
||||
|
||||
MVKDevice* mvkDev = MVKDevice::getMVKDevice(device);
|
||||
delete mvkDev;
|
||||
MVKDevice::getMVKDevice(device)->destroy();
|
||||
}
|
||||
|
||||
MVK_PUBLIC_SYMBOL VkResult vkEnumerateInstanceExtensionProperties(
|
||||
|
Loading…
x
Reference in New Issue
Block a user