Set Metal texture usage to allow texture copy via view.
MVKCmdCopyImage uses texture view if formats different. Enable
MTLTextureUsagePixelFormatView for VK_IMAGE_USAGE_TRANSFER_SRC_BIT.
Refactor mvkMTLTextureUsageFromVkImageUsageFlags() to clarify Metal usages
and enable views on depth-stencil attachments by default.
diff --git a/Docs/Whats_New.md b/Docs/Whats_New.md
index 18dd946..9b4a7bb 100644
--- a/Docs/Whats_New.md
+++ b/Docs/Whats_New.md
@@ -30,6 +30,7 @@
- Separate `SPIRVToMSLConverterContext` into input config and output results.
- Fix pipeline cache lookups.
- Fix race condition between swapchain image destruction and presentation completion callback.
+- Set Metal texture usage to allow texture copy via view.
- Document that the functions in `vk_mvk_moltenvk.h` cannot be used with objects
retrieved through the *Vulkan SDK Loader and Layers* framework.
- Update `VK_MVK_MOLTENVK_SPEC_VERSION` to 21.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index cc977a5..0d1fd4e 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -373,16 +373,15 @@
}
MTLTextureUsage MVKImage::getMTLTextureUsage() {
+
MTLTextureUsage usage = mvkMTLTextureUsageFromVkImageUsageFlags(_usage);
- // If this is a depth/stencil texture, and the device supports it, tell
- // Metal we may create texture views of this, too.
- if ((_mtlPixelFormat == MTLPixelFormatDepth32Float_Stencil8
-#if MVK_MACOS
- || _mtlPixelFormat == MTLPixelFormatDepth24Unorm_Stencil8
-#endif
- ) && _device->_pMetalFeatures->stencilViews) {
- mvkEnableFlag(usage, MTLTextureUsagePixelFormatView);
+ // Remove view usage from D/S if Metal doesn't support it
+ if ( !_device->_pMetalFeatures->stencilViews &&
+ mvkMTLPixelFormatIsDepthFormat(_mtlPixelFormat) &&
+ mvkMTLPixelFormatIsStencilFormat(_mtlPixelFormat)) {
+
+ mvkDisableFlag(usage, MTLTextureUsagePixelFormatView);
}
// If this format doesn't support being blitted to, and the usage
diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm
index 0cdf559..fc9bbc8 100644
--- a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm
+++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm
@@ -840,33 +840,35 @@
MVK_PUBLIC_SYMBOL MTLTextureUsage mvkMTLTextureUsageFromVkImageUsageFlags(VkImageUsageFlags vkImageUsageFlags) {
MTLTextureUsage mtlUsage = MTLTextureUsageUnknown;
- if ( mvkAreFlagsEnabled(vkImageUsageFlags, VK_IMAGE_USAGE_TRANSFER_SRC_BIT) ) {
- mvkEnableFlag(mtlUsage, MTLTextureUsageShaderRead);
- }
- if ( mvkAreFlagsEnabled(vkImageUsageFlags, VK_IMAGE_USAGE_TRANSFER_DST_BIT) ) {
- mvkEnableFlag(mtlUsage, MTLTextureUsageRenderTarget);
- }
- if ( mvkAreFlagsEnabled(vkImageUsageFlags, VK_IMAGE_USAGE_SAMPLED_BIT) ) {
- mvkEnableFlag(mtlUsage, MTLTextureUsageShaderRead);
- mvkEnableFlag(mtlUsage, MTLTextureUsagePixelFormatView);
- }
- if ( mvkAreFlagsEnabled(vkImageUsageFlags, VK_IMAGE_USAGE_STORAGE_BIT) ) {
- mvkEnableFlag(mtlUsage, MTLTextureUsageShaderRead);
- mvkEnableFlag(mtlUsage, MTLTextureUsageShaderWrite);
- mvkEnableFlag(mtlUsage, MTLTextureUsagePixelFormatView);
- }
- if ( mvkAreFlagsEnabled(vkImageUsageFlags, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) ) {
- mvkEnableFlag(mtlUsage, MTLTextureUsageShaderRead);
- mvkEnableFlag(mtlUsage, MTLTextureUsagePixelFormatView);
- }
- if ( mvkAreFlagsEnabled(vkImageUsageFlags, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) ) {
- mvkEnableFlag(mtlUsage, MTLTextureUsageRenderTarget);
- mvkEnableFlag(mtlUsage, MTLTextureUsagePixelFormatView);
- }
- if ( mvkAreFlagsEnabled(vkImageUsageFlags, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ) {
- mvkEnableFlag(mtlUsage, MTLTextureUsageRenderTarget);
- mvkDisableFlag(mtlUsage, MTLTextureUsagePixelFormatView); // Clears bit. Do this last.
- }
+ // Read from...
+ if (mvkIsAnyFlagEnabled(vkImageUsageFlags, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
+ VK_IMAGE_USAGE_SAMPLED_BIT |
+ VK_IMAGE_USAGE_STORAGE_BIT |
+ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT))) {
+ mvkEnableFlag(mtlUsage, MTLTextureUsageShaderRead);
+ }
+
+ // Write to...
+ if (mvkIsAnyFlagEnabled(vkImageUsageFlags, (VK_IMAGE_USAGE_STORAGE_BIT))) {
+ mvkEnableFlag(mtlUsage, MTLTextureUsageShaderWrite);
+ }
+
+ // Render to...
+ if (mvkIsAnyFlagEnabled(vkImageUsageFlags, (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_TRANSFER_DST_BIT))) { // Scaling a BLIT may use rendering.
+ mvkEnableFlag(mtlUsage, MTLTextureUsageRenderTarget);
+ }
+
+ // Create view on...
+ if (mvkIsAnyFlagEnabled(vkImageUsageFlags, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | // May use temp view if transfer involves format change
+ VK_IMAGE_USAGE_SAMPLED_BIT |
+ VK_IMAGE_USAGE_STORAGE_BIT |
+ VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT))) { // D/S may be filtered out after device check
+ mvkEnableFlag(mtlUsage, MTLTextureUsagePixelFormatView);
+ }
return mtlUsage;
}