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`.
This commit is contained in:
Chip Davis 2018-10-02 16:11:00 -05:00
parent 70dae8946a
commit b86e6b2be3
3 changed files with 47 additions and 7 deletions

View File

@ -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;

View File

@ -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;
}

View File

@ -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 \