Queue submissions retain wait semaphores until MTLCommandBuffer finishes.

Add additional Vulkan error strings (unrelated).
This commit is contained in:
Bill Hollings 2023-02-04 11:27:16 -05:00
parent fabad21405
commit 3250569260
5 changed files with 84 additions and 54 deletions

View File

@ -25,6 +25,7 @@ Released TBA
was sometimes incorrectly disabled due to a Metal driver bug.
- Detect when size of surface has changed under the covers.
- Change rounding of surface size provided by Metal from truncation to rounding-with-half-to-even.
- Queue submissions retain wait semaphores until `MTLCommandBuffer` finishes.
MoltenVK 1.2.2

View File

@ -1338,15 +1338,21 @@ void MVKPresentableSwapchainImage::presentCAMetalDrawable(id<MTLCommandBuffer> m
_availabilitySignalers.erase(sigIter);
}
// Ensure this image and the drawable are not destroyed while awaiting MTLCommandBuffer completion.
// We retain the drawable separately because new drawable might be acquired by this image by then.
// Ensure this image, the drawable, and the present fence are not destroyed while
// awaiting MTLCommandBuffer completion. We retain the drawable separately because
// a new drawable might be acquired by this image by then.
retain();
[mtlDrwbl retain];
auto* fence = presentInfo.fence;
if (fence) { fence->retain(); }
[mtlCmdBuff addCompletedHandler: ^(id<MTLCommandBuffer> mcb) {
[mtlDrwbl release];
makeAvailable(signaler);
release();
if (presentInfo.fence) { presentInfo.fence->signal(); }
if (fence) {
fence->signal();
fence->release();
}
}];
signalPresentationSemaphore(signaler, mtlCmdBuff);

View File

@ -189,6 +189,8 @@ public:
protected:
friend class MVKQueue;
virtual void finish() = 0;
MVKQueue* _queue;
MVKSmallVector<std::pair<MVKSemaphore*, uint64_t>> _waitSemaphores;
};
@ -213,7 +215,7 @@ protected:
id<MTLCommandBuffer> getActiveMTLCommandBuffer();
void setActiveMTLCommandBuffer(id<MTLCommandBuffer> mtlCmdBuff);
void commitActiveMTLCommandBuffer(bool signalCompletion = false);
virtual void finish();
void finish() override;
virtual void submitCommandBuffers() {}
MVKSmallVector<std::pair<MVKSemaphore*, uint64_t>> _signalSemaphores;
@ -270,7 +272,7 @@ public:
const VkPresentInfoKHR* pPresentInfo);
protected:
void stopAutoGPUCapture();
void finish() override;
MVKSmallVector<MVKImagePresentInfo, 4> _presentInfo;
};

View File

@ -290,11 +290,15 @@ MVKQueueSubmission::MVKQueueSubmission(MVKQueue* queue,
_waitSemaphores.reserve(waitSemaphoreCount);
for (uint32_t i = 0; i < waitSemaphoreCount; i++) {
_waitSemaphores.push_back(make_pair((MVKSemaphore*)pWaitSemaphores[i], (uint64_t)0));
auto* sem4 = (MVKSemaphore*)pWaitSemaphores[i];
sem4->retain();
uint64_t sem4Val = 0;
_waitSemaphores.emplace_back(sem4, sem4Val);
}
}
MVKQueueSubmission::~MVKQueueSubmission() {
for (auto s : _waitSemaphores) { s.first->release(); }
_queue->release();
}
@ -530,33 +534,42 @@ void MVKQueueFullCommandBufferSubmission<N>::finish() {
#pragma mark -
#pragma mark MVKQueuePresentSurfaceSubmission
// If the semaphores are encodable, wait on them by encoding them on the MTLCommandBuffer before presenting.
// If the semaphores are not encodable, wait on them inline after presenting.
// The semaphores know what to do.
void MVKQueuePresentSurfaceSubmission::execute() {
// If the semaphores are encodable, wait on them by encoding them on the MTLCommandBuffer before presenting.
// If the semaphores are not encodable, wait on them inline after presenting.
// The semaphores know what to do.
id<MTLCommandBuffer> mtlCmdBuff = _queue->getMTLCommandBuffer(kMVKCommandUseQueuePresent);
[mtlCmdBuff enqueue];
for (auto& ws : _waitSemaphores) { ws.first->encodeWait(mtlCmdBuff, 0); }
// Add completion handler that will destroy this submission only once the MTLCommandBuffer
// is finished with the resources retained here, including the wait semaphores.
// Completion handlers are also added in presentCAMetalDrawable() to retain the swapchain images.
[mtlCmdBuff addCompletedHandler: ^(id<MTLCommandBuffer> mcb) {
this->finish();
}];
for (int i = 0; i < _presentInfo.size(); i++ ) {
_presentInfo[i].presentableImage->presentCAMetalDrawable(mtlCmdBuff, _presentInfo[i]);
}
for (auto& ws : _waitSemaphores) { ws.first->encodeWait(nil, 0); }
[mtlCmdBuff commit];
}
// Let Xcode know the current frame is done, then start a new frame
void MVKQueuePresentSurfaceSubmission::finish() {
// Let Xcode know the current frame is done, then start a new frame,
// and if auto GPU capture is active, and it's time to stop it, do so.
auto cs = _queue->_submissionCaptureScope;
cs->endScope();
cs->beginScope();
stopAutoGPUCapture();
this->destroy();
}
void MVKQueuePresentSurfaceSubmission::stopAutoGPUCapture() {
if (_queue->_queueFamily->getIndex() == mvkConfig().defaultGPUCaptureScopeQueueFamilyIndex &&
_queue->_index == mvkConfig().defaultGPUCaptureScopeQueueIndex) {
_queue->getDevice()->stopAutoGPUCapture(MVK_CONFIG_AUTO_GPU_CAPTURE_SCOPE_FRAME);
}
this->destroy();
}
MVKQueuePresentSurfaceSubmission::MVKQueuePresentSurfaceSubmission(MVKQueue* queue,

View File

@ -24,49 +24,57 @@
const char* mvkVkResultName(VkResult vkResult) {
switch (vkResult) {
CASE_STRINGIFY(VK_SUCCESS);
CASE_STRINGIFY(VK_NOT_READY);
CASE_STRINGIFY(VK_TIMEOUT);
CASE_STRINGIFY(VK_EVENT_SET);
CASE_STRINGIFY(VK_EVENT_RESET);
CASE_STRINGIFY(VK_INCOMPLETE);
CASE_STRINGIFY(VK_SUCCESS);
CASE_STRINGIFY(VK_NOT_READY);
CASE_STRINGIFY(VK_TIMEOUT);
CASE_STRINGIFY(VK_EVENT_SET);
CASE_STRINGIFY(VK_EVENT_RESET);
CASE_STRINGIFY(VK_INCOMPLETE);
CASE_STRINGIFY(VK_ERROR_OUT_OF_HOST_MEMORY);
CASE_STRINGIFY(VK_ERROR_OUT_OF_DEVICE_MEMORY);
CASE_STRINGIFY(VK_ERROR_INITIALIZATION_FAILED);
CASE_STRINGIFY(VK_ERROR_DEVICE_LOST);
CASE_STRINGIFY(VK_ERROR_MEMORY_MAP_FAILED);
CASE_STRINGIFY(VK_ERROR_LAYER_NOT_PRESENT);
CASE_STRINGIFY(VK_ERROR_EXTENSION_NOT_PRESENT);
CASE_STRINGIFY(VK_ERROR_FEATURE_NOT_PRESENT);
CASE_STRINGIFY(VK_ERROR_INCOMPATIBLE_DRIVER);
CASE_STRINGIFY(VK_ERROR_TOO_MANY_OBJECTS);
CASE_STRINGIFY(VK_ERROR_FORMAT_NOT_SUPPORTED);
CASE_STRINGIFY(VK_ERROR_FRAGMENTED_POOL);
CASE_STRINGIFY(VK_ERROR_OUT_OF_HOST_MEMORY);
CASE_STRINGIFY(VK_ERROR_OUT_OF_DEVICE_MEMORY);
CASE_STRINGIFY(VK_ERROR_INITIALIZATION_FAILED);
CASE_STRINGIFY(VK_ERROR_DEVICE_LOST);
CASE_STRINGIFY(VK_ERROR_MEMORY_MAP_FAILED);
CASE_STRINGIFY(VK_ERROR_LAYER_NOT_PRESENT);
CASE_STRINGIFY(VK_ERROR_EXTENSION_NOT_PRESENT);
CASE_STRINGIFY(VK_ERROR_FEATURE_NOT_PRESENT);
CASE_STRINGIFY(VK_ERROR_INCOMPATIBLE_DRIVER);
CASE_STRINGIFY(VK_ERROR_TOO_MANY_OBJECTS);
CASE_STRINGIFY(VK_ERROR_FORMAT_NOT_SUPPORTED);
CASE_STRINGIFY(VK_ERROR_FRAGMENTED_POOL);
CASE_STRINGIFY(VK_ERROR_UNKNOWN);
CASE_STRINGIFY(VK_ERROR_OUT_OF_POOL_MEMORY);
CASE_STRINGIFY(VK_ERROR_INVALID_EXTERNAL_HANDLE);
CASE_STRINGIFY(VK_ERROR_FRAGMENTATION);
CASE_STRINGIFY(VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS);
CASE_STRINGIFY(VK_ERROR_UNKNOWN);
CASE_STRINGIFY(VK_ERROR_OUT_OF_POOL_MEMORY);
CASE_STRINGIFY(VK_ERROR_INVALID_EXTERNAL_HANDLE);
CASE_STRINGIFY(VK_ERROR_FRAGMENTATION);
CASE_STRINGIFY(VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS);
CASE_STRINGIFY(VK_PIPELINE_COMPILE_REQUIRED);
CASE_STRINGIFY(VK_ERROR_SURFACE_LOST_KHR);
CASE_STRINGIFY(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
CASE_STRINGIFY(VK_SUBOPTIMAL_KHR);
CASE_STRINGIFY(VK_ERROR_OUT_OF_DATE_KHR);
CASE_STRINGIFY(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
CASE_STRINGIFY(VK_ERROR_SURFACE_LOST_KHR);
CASE_STRINGIFY(VK_ERROR_NATIVE_WINDOW_IN_USE_KHR);
CASE_STRINGIFY(VK_SUBOPTIMAL_KHR);
CASE_STRINGIFY(VK_ERROR_OUT_OF_DATE_KHR);
CASE_STRINGIFY(VK_ERROR_INCOMPATIBLE_DISPLAY_KHR);
CASE_STRINGIFY(VK_ERROR_VALIDATION_FAILED_EXT);
CASE_STRINGIFY(VK_ERROR_INVALID_SHADER_NV);
CASE_STRINGIFY(VK_ERROR_VALIDATION_FAILED_EXT);
CASE_STRINGIFY(VK_ERROR_INVALID_SHADER_NV);
CASE_STRINGIFY(VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR);
CASE_STRINGIFY(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
CASE_STRINGIFY(VK_ERROR_NOT_PERMITTED_EXT);
CASE_STRINGIFY(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT);
CASE_STRINGIFY(VK_THREAD_IDLE_KHR);
CASE_STRINGIFY(VK_THREAD_DONE_KHR);
CASE_STRINGIFY(VK_OPERATION_DEFERRED_KHR);
CASE_STRINGIFY(VK_OPERATION_NOT_DEFERRED_KHR);
CASE_STRINGIFY(VK_PIPELINE_COMPILE_REQUIRED_EXT);
CASE_STRINGIFY(VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR);
CASE_STRINGIFY(VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR);
CASE_STRINGIFY(VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR);
CASE_STRINGIFY(VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR);
CASE_STRINGIFY(VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR);
CASE_STRINGIFY(VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT);
CASE_STRINGIFY(VK_ERROR_NOT_PERMITTED_KHR);
CASE_STRINGIFY(VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT);
CASE_STRINGIFY(VK_THREAD_IDLE_KHR);
CASE_STRINGIFY(VK_THREAD_DONE_KHR);
CASE_STRINGIFY(VK_OPERATION_DEFERRED_KHR);
CASE_STRINGIFY(VK_OPERATION_NOT_DEFERRED_KHR);
CASE_STRINGIFY(VK_ERROR_COMPRESSION_EXHAUSTED_EXT);
default: return "VK_UNKNOWN_VK_Result";
}