diff --git a/Demos/Cube/macOS/DemoViewController.m b/Demos/Cube/macOS/DemoViewController.m index 5ec96aed..d04697fd 100644 --- a/Demos/Cube/macOS/DemoViewController.m +++ b/Demos/Cube/macOS/DemoViewController.m @@ -88,4 +88,16 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, return layer; } +/** + * If this view moves to a screen that has a different resolution scale (eg. Standard <=> Retina), + * update the contentsScale of the layer, which will trigger a Vulkan VK_SUBOPTIMAL_KHR result, which + * causes this demo to replace the swapchain, in order to optimize rendering for the new resolution. + */ +-(BOOL) layer: (CALayer *)layer shouldInheritContentsScale: (CGFloat)newScale fromWindow: (NSWindow *)window { + if (newScale == layer.contentsScale) { return NO; } + + layer.contentsScale = newScale; + return YES; +} + @end diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md index d5fa9a6d..1a6bef6f 100644 --- a/Docs/Whats_New.md +++ b/Docs/Whats_New.md @@ -30,6 +30,7 @@ Released TBD - Fix query pool wait block when query is not encoded to be written to. - Fix `vkUpdateDescriptorSetWithTemplate()` for inline block descriptors. - Ignore sampler update in descriptor set bindings that use immutable samplers. +- Update _macOS Cube_ demo to demonstrate optimizing swapchain across multiple screens. - Update `VK_MVK_MOLTENVK_SPEC_VERSION` to version `35`. diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h index 250210ff..7521e656 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.h @@ -73,15 +73,15 @@ public: uint32_t* pImageIndex); /** Returns whether the parent surface is now lost and this swapchain must be recreated. */ - inline bool getIsSurfaceLost() { return _surfaceLost; } + bool getIsSurfaceLost() { return _surfaceLost; } - /** Returns whether the surface size has changed since the last time this function was called. */ - inline bool getHasSurfaceSizeChanged() { + /** Returns whether the surface size or resolution scale has changed since the last time this function was called. */ + bool getHasSurfaceSizeChanged() { return !CGSizeEqualToSize(_mtlLayer.naturalDrawableSizeMVK, _mtlLayer.drawableSize); } /** Returns the status of the surface. Surface loss takes precedence over out-of-date errors. */ - inline VkResult getSurfaceStatus() { + VkResult getSurfaceStatus() { if (_device->getConfigurationResult() != VK_SUCCESS) { return _device->getConfigurationResult(); } if (getIsSurfaceLost()) { return VK_ERROR_SURFACE_LOST_KHR; } if (getHasSurfaceSizeChanged()) { return VK_SUBOPTIMAL_KHR; } diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm index 68e7e239..137eaa1f 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm @@ -409,7 +409,8 @@ void MVKSwapchain::initSurfaceImages(const VkSwapchainCreateInfoKHR* pCreateInfo _presentableImages.push_back(_device->createPresentableSwapchainImage(&imgInfo, this, imgIdx, NULL)); } - MVKLogInfo("Created %d swapchain images with initial size (%d, %d).", imgCnt, imgExtent.width, imgExtent.height); + MVKLogInfo("Created %d swapchain images with initial size (%d, %d) and contents scale %.1f.", + imgCnt, imgExtent.width, imgExtent.height, _mtlLayer.contentsScale); } VkResult MVKSwapchain::getRefreshCycleDuration(VkRefreshCycleDurationGOOGLE *pRefreshCycleDuration) {