MVKCmdClearImage return error if texture is not renderable.
diff --git a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm
index 237c9c3..c7b9087 100644
--- a/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm
+++ b/MoltenVK/MoltenVK/Commands/MVKCmdTransfer.mm
@@ -1055,8 +1055,15 @@
for (uint32_t i = 0; i < rangeCount; i++) {
_subresourceRanges.push_back(pRanges[i]);
}
+
+ // Validate
+ if ( !_image->getSupportsAllFormatFeatures(VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ) {
+ setConfigurationResult(reportError(VK_ERROR_FEATURE_NOT_PRESENT, "vkCmdClearImage(): Format %s cannot be cleared on this device.", mvkVkFormatName(_image->getVkFormat())));
+ }
}
void MVKCmdClearImage::encode(MVKCommandEncoder* cmdEncoder) {
+ if (getConfigurationResult()) { return; }
+
id<MTLTexture> imgMTLTex = _image->getMTLTexture();
if ( !imgMTLTex ) { return; }
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
index 7403d03..0c5e3bf 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.h
@@ -61,9 +61,21 @@
/** Returns the Vulkan image format of this image. */
VkFormat getVkFormat();
- /** Returns whether this texture is compressed. */
+ /** Returns whether this image is compressed. */
bool getIsCompressed();
+ /**
+ * Returns whether the format of this image supports ANY of the indicated feature flags,
+ * taking into consideration whether this image is using linear or optimal tiling.
+ */
+ bool getSupportsAnyFormatFeature(VkFormatFeatureFlags requiredFormatFeatureFlags);
+
+ /**
+ * Returns whether the format of this image supports ALL of the indicated feature flags,
+ * taking into consideration whether this image is using linear or optimal tiling.
+ */
+ bool getSupportsAllFormatFeatures(VkFormatFeatureFlags requiredFormatFeatureFlags);
+
/**
* Returns the 3D extent of this image at the base mipmap level.
* For 2D or cube images, the Z component will be 1.
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
index c08c036..3c979d7 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKImage.mm
@@ -45,6 +45,20 @@
return mvkFormatTypeFromMTLPixelFormat(_mtlPixelFormat) == kMVKFormatCompressed;
}
+bool MVKImage::getSupportsAnyFormatFeature(VkFormatFeatureFlags requiredFormatFeatureFlags) {
+ VkFormatProperties props;
+ _device->getPhysicalDevice()->getFormatProperties(getVkFormat(), &props);
+ VkFormatFeatureFlags imageFeatureFlags = _isLinear ? props.linearTilingFeatures : props.optimalTilingFeatures;
+ return mvkIsAnyFlagEnabled(imageFeatureFlags, requiredFormatFeatureFlags);
+}
+
+bool MVKImage::getSupportsAllFormatFeatures(VkFormatFeatureFlags requiredFormatFeatureFlags) {
+ VkFormatProperties props;
+ _device->getPhysicalDevice()->getFormatProperties(getVkFormat(), &props);
+ VkFormatFeatureFlags imageFeatureFlags = _isLinear ? props.linearTilingFeatures : props.optimalTilingFeatures;
+ return mvkAreAllFlagsEnabled(imageFeatureFlags, requiredFormatFeatureFlags);
+}
+
VkExtent3D MVKImage::getExtent3D(uint32_t mipLevel) {
return mvkMipmapLevelSizeFromBaseSize3D(_extent, mipLevel);
}
@@ -388,13 +402,10 @@
mvkDisableFlag(usage, MTLTextureUsagePixelFormatView);
}
- // If this format doesn't support being blitted to, and the usage
- // doesn't specify use as an attachment, turn off
- // MTLTextureUsageRenderTarget.
- VkFormatProperties props;
- _device->getPhysicalDevice()->getFormatProperties(getVkFormat(), &props);
- if (!mvkAreAllFlagsEnabled(_isLinear ? props.linearTilingFeatures : props.optimalTilingFeatures, VK_FORMAT_FEATURE_BLIT_DST_BIT) &&
- !mvkIsAnyFlagEnabled(_usage, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
+ // If this format doesn't support being rendered to, disable MTLTextureUsageRenderTarget.
+ if ( !getSupportsAnyFormatFeature(VK_FORMAT_FEATURE_BLIT_DST_BIT |
+ VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
+ VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ) {
mvkDisableFlag(usage, MTLTextureUsageRenderTarget);
}