Fix vulkan caps checks for external formats.
Change-Id: I586e823efefdfbdf0397e3c1940e787930daaa00
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243738
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 0035236..d231736 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -1194,11 +1194,33 @@
}
}
+// For many checks in caps, we need to know whether the GrBackendFormat is external or not. If it is
+// external the VkFormat will be VK_NULL_HANDLE which is not handled by our various format
+// capability checks.
+static bool backend_format_is_external(const GrBackendFormat& format) {
+ const GrVkYcbcrConversionInfo* ycbcrInfo = format.getVkYcbcrConversionInfo();
+ SkASSERT(ycbcrInfo);
+
+ // All external formats have a valid ycbcrInfo used for sampling and a non zero external format.
+ if (ycbcrInfo->isValid() && ycbcrInfo->fExternalFormat != 0) {
+#ifdef SK_DEBUG
+ VkFormat vkFormat;
+ SkAssertResult(format.asVkFormat(&vkFormat));
+ SkASSERT(vkFormat == VK_NULL_HANDLE);
+#endif
+ return true;
+ }
+ return false;
+}
+
bool GrVkCaps::isFormatSRGB(const GrBackendFormat& format) const {
VkFormat vkFormat;
if (!format.asVkFormat(&vkFormat)) {
return false;
}
+ if (backend_format_is_external(format)) {
+ return false;
+ }
return format_is_srgb(vkFormat);
}
@@ -1209,8 +1231,6 @@
return false;
}
- SkASSERT(GrVkFormatIsSupported(vkFormat));
-
return vkFormat == VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK;
}
@@ -1231,6 +1251,11 @@
if (!format.asVkFormat(&vkFormat)) {
return false;
}
+ if (backend_format_is_external(format)) {
+ // We can always texture from an external format (assuming we have the ycbcr conversion
+ // info which we require to be passed in).
+ return true;
+ }
return this->isVkFormatTexturable(vkFormat);
}
@@ -1338,8 +1363,9 @@
return {GrColorType::kUnknown, 0};
}
-
- if (GrVkFormatNeedsYcbcrSampler(vkFormat)) {
+ // We don't support the ability to upload to external formats or formats that require a ycbcr
+ // sampler. In general these types of formats are only used for sampling in a shader.
+ if (backend_format_is_external(surfaceFormat) || GrVkFormatNeedsYcbcrSampler(vkFormat)) {
return {GrColorType::kUnknown, 0};
}
@@ -1400,7 +1426,7 @@
if (ycbcrInfo->isValid() && !GrVkFormatNeedsYcbcrSampler(vkFormat)) {
// Format may be undefined for external images, which are required to have YCbCr conversion.
- if (VK_FORMAT_UNDEFINED == vkFormat) {
+ if (VK_FORMAT_UNDEFINED == vkFormat && ycbcrInfo->fExternalFormat != 0) {
return true;
}
return false;
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 899360e..e1e6d3a 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1105,14 +1105,17 @@
return false;
}
+ if (info.fImageLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && !caps.supportsSwapchain()) {
+ return false;
+ }
+
if (info.fYcbcrConversionInfo.isValid()) {
if (!caps.supportsYcbcrConversion()) {
return false;
}
- }
-
- if (info.fImageLayout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR && !caps.supportsSwapchain()) {
- return false;
+ if (info.fYcbcrConversionInfo.fExternalFormat != 0) {
+ return true;
+ }
}
SkASSERT(GrVkFormatColorTypePairIsValid(info.fFormat, colorType));
@@ -1120,6 +1123,9 @@
}
static bool check_tex_image_info(const GrVkCaps& caps, const GrVkImageInfo& info) {
+ if (info.fYcbcrConversionInfo.isValid() && info.fYcbcrConversionInfo.fExternalFormat != 0) {
+ return true;
+ }
if (info.fImageTiling == VK_IMAGE_TILING_OPTIMAL) {
if (!caps.isVkFormatTexturable(info.fFormat)) {
return false;
@@ -1344,6 +1350,7 @@
SkDebugf("Trying to create mipmap for linear tiled texture");
return false;
}
+ SkASSERT(tex->texturePriv().textureType() == GrTextureType::k2D);
// determine if we can blit to and from this format
const GrVkCaps& caps = this->vkCaps();
diff --git a/src/gpu/vk/GrVkImage.cpp b/src/gpu/vk/GrVkImage.cpp
index 9ed290a..2b05d00 100644
--- a/src/gpu/vk/GrVkImage.cpp
+++ b/src/gpu/vk/GrVkImage.cpp
@@ -79,7 +79,6 @@
case VK_FORMAT_D32_SFLOAT_S8_UINT:
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
default:
- SkASSERT(GrVkFormatIsSupported(format));
return VK_IMAGE_ASPECT_COLOR_BIT;
}
}
diff --git a/src/gpu/vk/GrVkTexture.cpp b/src/gpu/vk/GrVkTexture.cpp
index 5d09f66..e162b34 100644
--- a/src/gpu/vk/GrVkTexture.cpp
+++ b/src/gpu/vk/GrVkTexture.cpp
@@ -31,6 +31,8 @@
GrTextureType::k2D, mipMapsStatus)
, fTextureView(view) {
SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
+ // We don't support creating external GrVkTextures
+ SkASSERT(!info.fYcbcrConversionInfo.isValid() || !info.fYcbcrConversionInfo.fExternalFormat);
this->registerWithCache(budgeted);
if (GrVkFormatIsCompressed(info.fFormat)) {
this->setReadOnly();
@@ -40,11 +42,11 @@
GrVkTexture::GrVkTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc, const GrVkImageInfo& info,
sk_sp<GrVkImageLayout> layout, const GrVkImageView* view,
GrMipMapsStatus mipMapsStatus, GrBackendObjectOwnership ownership,
- GrWrapCacheable cacheable, GrIOType ioType)
+ GrWrapCacheable cacheable, GrIOType ioType, bool isExternal)
: GrSurface(gpu, {desc.fWidth, desc.fHeight}, desc.fConfig, info.fProtected)
, GrVkImage(info, std::move(layout), ownership)
, INHERITED(gpu, {desc.fWidth, desc.fHeight}, desc.fConfig, info.fProtected,
- GrTextureType::k2D, mipMapsStatus)
+ isExternal ? GrTextureType::kExternal : GrTextureType::k2D, mipMapsStatus)
, fTextureView(view) {
SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
if (ioType == kRead_GrIOType) {
@@ -67,6 +69,9 @@
GrTextureType::k2D, mipMapsStatus)
, fTextureView(view) {
SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount));
+ // Since this ctor is only called from GrVkTextureRenderTarget, we can't have a ycbcr conversion
+ // since we don't support that on render targets.
+ SkASSERT(!info.fYcbcrConversionInfo.isValid());
}
sk_sp<GrVkTexture> GrVkTexture::MakeNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
@@ -116,8 +121,11 @@
GrBackendObjectOwnership ownership = kBorrow_GrWrapOwnership == wrapOwnership
? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned;
+ bool isExternal = info.fYcbcrConversionInfo.isValid() &&
+ (info.fYcbcrConversionInfo.fExternalFormat != 0);
return sk_sp<GrVkTexture>(new GrVkTexture(gpu, desc, info, std::move(layout), imageView,
- mipMapsStatus, ownership, cacheable, ioType));
+ mipMapsStatus, ownership, cacheable, ioType,
+ isExternal));
}
GrVkTexture::~GrVkTexture() {
diff --git a/src/gpu/vk/GrVkTexture.h b/src/gpu/vk/GrVkTexture.h
index f0a02fc..6d90826 100644
--- a/src/gpu/vk/GrVkTexture.h
+++ b/src/gpu/vk/GrVkTexture.h
@@ -62,7 +62,7 @@
GrMipMapsStatus);
GrVkTexture(GrVkGpu*, const GrSurfaceDesc&, const GrVkImageInfo&, sk_sp<GrVkImageLayout>,
const GrVkImageView*, GrMipMapsStatus, GrBackendObjectOwnership, GrWrapCacheable,
- GrIOType);
+ GrIOType, bool isExternal);
// In Vulkan we call the release proc after we are finished with the underlying
// GrVkImage::Resource object (which occurs after the GPU has finished all work on it).
diff --git a/src/gpu/vk/GrVkUniformHandler.cpp b/src/gpu/vk/GrVkUniformHandler.cpp
index 22a2594..cb41ae2 100644
--- a/src/gpu/vk/GrVkUniformHandler.cpp
+++ b/src/gpu/vk/GrVkUniformHandler.cpp
@@ -294,7 +294,8 @@
void GrVkUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
for (int i = 0; i < fSamplers.count(); ++i) {
const UniformInfo& sampler = fSamplers[i];
- SkASSERT(sampler.fVariable.getType() == kTexture2DSampler_GrSLType);
+ SkASSERT(sampler.fVariable.getType() == kTexture2DSampler_GrSLType ||
+ sampler.fVariable.getType() == kTextureExternalSampler_GrSLType);
if (visibility == sampler.fVisibility) {
sampler.fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
out->append(";\n");