From b86e6b2be31d1ba8a1dd862569e05191f76ffc8e Mon Sep 17 00:00:00 2001 From: Chip Davis Date: Tue, 2 Oct 2018 16:11:00 -0500 Subject: [PATCH] MVKDevice: Correct properties of linear-tiled images. According to the Vulkan spec, linear-tiled images *may* not be supported unless certain restrictions are satisfied. That means that implementations may support features--or restrictions--above and beyond the restrictions given in the Vulkan spec. Metal places these limitations on linear textures: * They must be 2D. * They may only have one mip level. * They may only have one array layer. * They may not be multisampled--sample count must be one. * On macOS, they may not be used as attachments. * They may not be depth/stencil textures. * They may not have a compressed format. Have `vkGetPhysicalDeviceFormatProperties()` and `vkGetPhysicalDeviceImageFormatProperties()` return results consistent with these constraints. Also, allow creation of linear textures with usages other than `VK_IMAGE_USAGE_TRANSFER_{SRC,DST}_BIT`. --- MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm | 40 +++++++++++++++++++++-- MoltenVK/MoltenVK/GPUObjects/MVKImage.mm | 6 ++-- MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm | 8 +++-- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm index e272b356..e8afc84d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm @@ -170,12 +170,17 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format, VkExtent3D maxExt; uint32_t maxLayers; uint32_t maxLevels; + VkSampleCountFlags sampleCounts = _metalFeatures.supportedSampleCounts; switch (type) { case VK_IMAGE_TYPE_1D: // Metal does not allow 1D textures to be used as attachments if (mvkIsAnyFlagEnabled(usage, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) { return VK_ERROR_FORMAT_NOT_SUPPORTED; } + // Metal does not allow linear tiling on 1D textures + if (tiling == VK_IMAGE_TILING_LINEAR) { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } maxExt.width = pLimits->maxImageDimension1D; maxExt.height = 1; maxExt.depth = 1; @@ -186,10 +191,35 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format, maxExt.width = pLimits->maxImageDimension2D; maxExt.height = pLimits->maxImageDimension2D; maxExt.depth = 1; - maxLevels = mvkMipmapLevels3D(maxExt); - maxLayers = pLimits->maxImageArrayLayers; + if (tiling == VK_IMAGE_TILING_LINEAR) { + // Linear textures have additional restrictions under Metal: + // - They may not be depth/stencil or compressed textures. + if (mvkFormatTypeFromVkFormat(format) == kMVKFormatDepthStencil || + mvkFormatTypeFromVkFormat(format) == kMVKFormatNone) { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } +#if MVK_MACOS + // - On macOS, they may not be used as framebuffer attachments. + if (mvkIsAnyFlagEnabled(usage, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT|VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT|VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) ) { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } +#endif + // - They may only have one mip level. + maxLevels = 1; + // - They may only have one layer. + maxLayers = 1; + // - They may not be multisampled. + sampleCounts = VK_SAMPLE_COUNT_1_BIT; + } else { + maxLevels = mvkMipmapLevels3D(maxExt); + maxLayers = pLimits->maxImageArrayLayers; + } break; case VK_IMAGE_TYPE_3D: + // Metal does not allow linear tiling on 3D textures + if (tiling == VK_IMAGE_TILING_LINEAR) { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } maxExt.width = pLimits->maxImageDimension3D; maxExt.height = pLimits->maxImageDimension3D; maxExt.depth = pLimits->maxImageDimension3D; @@ -197,6 +227,10 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format, maxLayers = 1; break; default: + // Metal does not allow linear tiling on anything but 2D textures + if (tiling == VK_IMAGE_TILING_LINEAR) { + return VK_ERROR_FORMAT_NOT_SUPPORTED; + } maxExt = { 1, 1, 1}; maxLayers = 1; maxLevels = 1; @@ -206,7 +240,7 @@ VkResult MVKPhysicalDevice::getImageFormatProperties(VkFormat format, pImageFormatProperties->maxExtent = maxExt; pImageFormatProperties->maxMipLevels = maxLevels; pImageFormatProperties->maxArrayLayers = maxLayers; - pImageFormatProperties->sampleCounts = _metalFeatures.supportedSampleCounts; + pImageFormatProperties->sampleCounts = sampleCounts; pImageFormatProperties->maxResourceSize = kMVKUndefinedLargeUInt64; return VK_SUCCESS; diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm index 030f0e24..8d936a5d 100644 --- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm +++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm @@ -546,10 +546,12 @@ bool MVKImage::validateLinear(const VkImageCreateInfo* pCreateInfo) { return false; } - if ( !mvkAreOnlyAnyFlagsEnabled(_usage, (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT)) ) { - setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, usage must only include VK_IMAGE_USAGE_TRANSFER_SRC_BIT and/or VK_IMAGE_USAGE_TRANSFER_DST_BIT.")); +#if MVK_MACOS + if ( mvkIsAnyFlagEnabled(_usage, (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) ) { + setConfigurationResult(mvkNotifyErrorWithText(VK_ERROR_FEATURE_NOT_PRESENT, "vkCreateImage() : If tiling is VK_IMAGE_TILING_LINEAR, usage must not include VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, and/or VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT.")); return false; } +#endif return true; } diff --git a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm index 3e67654a..a8bc1456 100644 --- a/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm +++ b/MoltenVK/MoltenVK/Vulkan/mvk_datatypes.mm @@ -61,10 +61,14 @@ using namespace std; # define MVK_FMT_DEPTH_FEATS (MVK_FMT_STENCIL_FEATS | VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) #endif -#define MVK_FMT_LINEAR_TILING_FEATS (VK_FORMAT_FEATURE_TRANSFER_SRC_BIT \ - | VK_FORMAT_FEATURE_TRANSFER_DST_BIT \ +#if MVK_MACOS +// macOS does not support linear images as framebuffer attachments. +#define MVK_FMT_LINEAR_TILING_FEATS (MVK_FMT_IMAGE_FEATS \ | VK_FORMAT_FEATURE_BLIT_SRC_BIT \ | VK_FORMAT_FEATURE_BLIT_DST_BIT) +#else +#define MVK_FMT_LINEAR_TILING_FEATS MVK_FMT_COLOR_FEATS +#endif #define MVK_FMT_BUFFER_FEATS (VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT \ | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT \